OPeNDAP Hyrax Back End Server (BES)
Updated for version 3.8.3
|
00001 // mod_opendap.cc 00002 00003 // This file is part of bes, A C++ back-end server implementation framework 00004 // for the OPeNDAP Data Access Protocol. 00005 00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research 00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact University Corporation for Atmospheric Research at 00024 // 3080 Center Green Drive, Boulder, CO 80301 00025 00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005 00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR. 00028 // 00029 // Authors: 00030 // pwest Patrick West <pwest@ucar.edu> 00031 // jgarcia Jose Garcia <jgarcia@ucar.edu> 00032 00033 #include <unistd.h> 00034 #include <iostream> 00035 00036 using std::cerr ; 00037 using std::endl ; 00038 using std::cout ; 00039 using std::flush ; 00040 00041 #include "httpd.h" 00042 #include "http_config.h" 00043 #include "http_core.h" 00044 #include "http_log.h" 00045 #include "http_protocol.h" 00046 #include "http_request.h" 00047 #include "http_main.h" 00048 #include "util_script.h" 00049 #include "util_md5.h" 00050 00051 #include "BESDataRequestInterface.h" 00052 #include "BESApacheWrapper.h" 00053 00054 char * ltoa(long val, char *buf,int base) 00055 { 00056 ldiv_t r; /* result of val / base */ 00057 if (base > 36 || base < 2) /* no conversion if wrong base */ 00058 { 00059 *buf = '\0'; 00060 return buf; 00061 } 00062 if (val < 0) 00063 *buf++ = '-'; 00064 r = ldiv (labs(val), base); 00065 /* output digits of val/base first */ 00066 if (r.quot > 0) 00067 buf = ltoa ( r.quot, buf, base); 00068 00069 /* output last digit */ 00070 00071 *buf++ = "0123456789abcdefghijklmnopqrstuvwxyz"[(int)r.rem]; 00072 *buf = '\0'; 00073 return buf; 00074 } 00075 00076 00077 static int util_read(request_rec *r, const char **rbuf) 00078 { 00079 int rc = OK; 00080 00081 if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) 00082 { 00083 return rc; 00084 } 00085 00086 if (ap_should_client_block(r)) 00087 { 00088 char argsbuffer[HUGE_STRING_LEN]; 00089 int rsize, len_read, rpos=0; 00090 long length = r->remaining; 00091 *rbuf = (char*) ap_pcalloc(r->pool, length + 1); 00092 00093 ap_hard_timeout("util_read", r); 00094 00095 while((len_read = ap_get_client_block(r, argsbuffer, sizeof(argsbuffer))) > 0) 00096 { 00097 ap_reset_timeout(r); 00098 if ((rpos + len_read) > length) 00099 { 00100 rsize = length - rpos; 00101 } 00102 else 00103 { 00104 rsize = len_read; 00105 } 00106 memcpy((char*)*rbuf + rpos, argsbuffer, rsize); 00107 rpos += rsize; 00108 } 00109 00110 ap_kill_timeout(r); 00111 } 00112 return rc; 00113 } 00114 00115 static int 00116 header_trace( void *data, const char *key, const char *val ) 00117 { 00118 request_rec *r = (request_rec *)data ; 00119 cerr << "Header Field '" << key << "' = '" << val << "'" << endl ; 00120 return TRUE ; 00121 } 00122 00123 static void 00124 list_headers( request_rec *r ) 00125 { 00126 ap_table_do( header_trace, r, r->headers_in, NULL ) ; 00127 } 00128 00129 static int opendap_handler(request_rec *r) 00130 { 00131 char port_number_buffer[80]; 00132 dup2(r->connection->client->fd,STDOUT_FILENO); 00133 BESDataRequestInterface rq; 00134 00135 // BEGIN Initialize all data request elements correctly to a null pointer 00136 rq.server_name=0; 00137 rq.server_address=0; 00138 rq.server_protocol=0; 00139 rq.server_port=0; 00140 rq.script_name=0; 00141 rq.user_address=0; 00142 rq.user_agent=0; 00143 rq.request=0; 00144 // END Initialize all the data request elements correctly to a null pointer 00145 00146 rq.server_name=ap_get_server_name(r); 00147 rq.server_address="jose"; 00148 rq.server_protocol=r->protocol; 00149 ltoa(ap_get_server_port(r), port_number_buffer, 10); 00150 rq.server_port=port_number_buffer; 00151 rq.script_name=r->uri; 00152 rq.user_address=r->connection->remote_ip; 00153 rq.user_agent = ap_table_get(r->headers_in, "User-Agent"); 00154 00155 const char* m_method = r->method; 00156 if (!m_method) 00157 { 00158 cerr << "mod_opendap: Fatal, Cannot load request method" << endl; 00159 return SERVER_ERROR; 00160 } 00161 00162 BESApacheWrapper wrapper; 00163 if ( strcmp(m_method, "GET") == 0 ) 00164 { 00165 if(r->parsed_uri.query) 00166 { 00167 wrapper.process_request(r->parsed_uri.query); 00168 rq.cookie=wrapper.process_user(r->parsed_uri.query); 00169 rq.token=wrapper.process_token(r->parsed_uri.query); 00170 } 00171 else 00172 { 00173 rq.request=0; 00174 rq.cookie=0; 00175 rq.token=0; 00176 } 00177 } 00178 else if (strcmp(m_method, "POST") == 0 ) 00179 { 00180 const char *post_data=0; 00181 util_read(r, &post_data); 00182 wrapper.process_request(post_data); 00183 rq.cookie=wrapper.process_user(post_data); 00184 rq.token=wrapper.process_token(r->parsed_uri.query); 00185 } 00186 else 00187 { 00188 rq.request=0; 00189 rq.cookie=0; 00190 rq.token=0; 00191 } 00192 00193 // These two lines will print out the header information to the error 00194 // log 00195 // list_headers( r ) ; 00196 // exit( 0 ) ; 00197 00198 if( !rq.cookie || !strcmp(rq.cookie,"") ) 00199 { 00200 rq.cookie = ap_table_get( r->headers_in, "Cookie" ) ; 00201 } 00202 00203 int status = 0 ; 00204 rq.request = wrapper.get_first_request() ; 00205 while( rq.request && status == 0 ) 00206 { 00207 status = wrapper.call_BES(rq); 00208 rq.request = wrapper.get_next_request() ; 00209 } 00210 00211 // always flush the socket at the end... 00212 // and since stdout is now the tcp/ip socket for this connection 00213 cout.flush() ; 00214 00215 // exit instead of returning 00216 exit( 0 ) ; 00217 00218 return OK; 00219 } 00220 00221 /* Make the name of the content handler known to Apache */ 00222 static handler_rec opendap_handlers[] = 00223 { 00224 {"opendap-handler", opendap_handler}, 00225 {NULL} 00226 }; 00227 00228 /* Tell Apache what phases of the transaction we handle */ 00229 module MODULE_VAR_EXPORT opendap_module = 00230 { 00231 STANDARD_MODULE_STUFF, 00232 NULL, /* module initializer */ 00233 NULL, /* per-directory config creator */ 00234 NULL, /* dir config merger */ 00235 NULL, /* server config creator */ 00236 NULL, /* server config merger */ 00237 NULL, /* command table */ 00238 opendap_handlers, /* [7] content handlers */ 00239 NULL, /* [2] URI-to-filename translation */ 00240 NULL, /* [5] check/validate user_id */ 00241 NULL, /* [6] check user_id is valid *here* */ 00242 NULL, /* [4] check access by host address */ 00243 NULL, /* [7] MIME type checker/setter */ 00244 NULL, /* [8] fixups */ 00245 NULL, /* [9] logger */ 00246 NULL, /* [3] header parser */ 00247 NULL, /* process initialization */ 00248 NULL, /* process exit/cleanup */ 00249 NULL /* [1] post read_request handling */ 00250 }; 00251