📄 mod_gsoap.c
字号:
{ assert(NULL != This); SoapSharedLibraries_merge3(This->m_pLibraries, pParentConfig->m_pLibraries, pNewConfig->m_pLibraries); This->m_Type = ct_both;}static voidgsoapConfiguration_init(gsoapConfiguration * This, apr_pool_t * p){ This->m_pLibraries = (SoapSharedLibraries *) apr_pcalloc(p, sizeof(SoapSharedLibraries)); SoapSharedLibraries_init(This->m_pLibraries, p); This->m_Type = ct_directory;}static gsoapConfiguration *gsoapConfiguration_create(apr_pool_t * p){ gsoapConfiguration *pConfig = (gsoapConfiguration *) apr_pcalloc(p, sizeof(gsoapConfiguration)); gsoapConfiguration_init(pConfig, p); return pConfig;}/* * forward declarations */static int gsoap_handler(request_rec * r);static int gsoap_init(apr_pool_t * p, apr_pool_t * ptemp, apr_pool_t * plog, server_rec * psrec);static void *gsoap_create_dir_config(apr_pool_t * p, char *dirspec);static void *gsoap_merge_dir_config(apr_pool_t * p, void *parent_conf, void *newloc_conf);static void *gsoap_create_server_config(apr_pool_t * p, server_rec * s);static void *gsoap_merge_server_config(apr_pool_t * p, void *server1_conf, void *server2_conf);static bool AddSharedLibrary(gsoapConfiguration * pConfig, const char *pszPath, const bool bIsSOAPLibrary);/* * * * * We prototyped the various syntax for command handlers (routines that * * are called when the configuration parser detects a directive declared * * by our module) earlier. Now we actually declare a "real" routine that * * will be invoked by the parser when our "real" directive is * * encountered. * * * If a command handler encounters a problem processing the directive, it * * signals this fact by returning a non-NULL pointer to a string * * describing the problem. * * * The magic return value DECLINE_CMD is used to deal with directives * * that might be declared by multiple modules. If the command handler * * returns NULL, the directive was processed; if it returns DECLINE_CMD, * * the next module (if any) that declares the directive is given a chance * * at it. If it returns any other value, it's treated as the text of an * * error message. *//** Command handler for the TAKE1 "SOAPLibrary" directive. * We remember the load path for the shared library that contains the SOAP server. */static const char *cmd_SoapLibrary(cmd_parms * cmd, void *mconfig, const char *pszPath){ gsoapConfiguration *pConfig = (gsoapConfiguration *) mconfig; AddSharedLibrary(pConfig, pszPath, true); return NULL;}/** Command handler for the TAKE1 "SOAPSupportLibrary" directive. * We remember the load path for a shared library that must additionally loaded. * This is a mechanism to load libraries that the SOAPLibrary depends on. * This type of libraries do not contain our soap server. */static const char *cmd_SupportLibrary(cmd_parms * cmd, void *mconfig, const char *pszPath){ gsoapConfiguration *pConfig = (gsoapConfiguration *) mconfig; AddSharedLibrary(pConfig, pszPath, false); return NULL;}typedef const char *(*command_function_interface) ();/** List of directives specific to our module. */static const command_rec gsoap_cmds[] = { AP_INIT_TAKE1("SOAPLibrary", ///< directive name (command_function_interface) cmd_SoapLibrary, ///< config action routine NULL, ///< argument to include in call ACCESS_CONF, ///< where available "SOAP shared Library that will be dynamically loaded. - 1 argument (path)" ///< directive description ), AP_INIT_TAKE1("SupportLibrary", ///< directive name (command_function_interface) cmd_SupportLibrary, ///< config action routine NULL, ///< argument to include in call ACCESS_CONF, ///< where available "additional library that must be dynamically loaded - 1 argument (path)" ///< directive description ), {NULL}};/* * All of the routines have been declared now. Here's the list of * directives specific to our module, and information about where they * may appear and how the command parser should pass them to us for * processing. Note that care must be taken to ensure that there are NO * collisions of directive names between modules. *//* * Module definition for configuration. If a particular callback is not * needed, replace its routine name below with the word NULL. * * The number in brackets indicates the order in which the routine is called * during request processing. Note that not all routines are necessarily * called (such as if a resource doesn't have access restrictions). *//** List of callback routines and data structures that provide the hooks into our module. */static voidgsoap_hooks(apr_pool_t * p){ // I think this is the call to make to register a handler for method calls (GET PUT et. al.). // We will ask to be last so that the comment has a higher tendency to // go at the end. ap_hook_handler(gsoap_handler, NULL, NULL, APR_HOOK_LAST); //Register a handler for post config processing ap_hook_post_config(gsoap_init, NULL, NULL, APR_HOOK_MIDDLE);}module AP_MODULE_DECLARE_DATA gsoap_module = { STANDARD20_MODULE_STUFF, gsoap_create_dir_config, /* per-directory config creator */ gsoap_merge_dir_config, /* dir config merger */ gsoap_create_server_config, /* server config creator */ gsoap_merge_server_config, /* server config merger */ gsoap_cmds, /* command table */ gsoap_hooks, /*hooks */};/** helper to write out the headers */static intListHeadersCallback(void *rec, const char *key, const char *value){ request_rec *r = (request_rec *) rec; ap_rprintf(r, "%s: %s<br>", key, value); return 1;}/** write out the headers of the request. */static voidListHeaders(request_rec * r){ apr_table_do(ListHeadersCallback, r, r->headers_in, NULL);}/** send the error message to the client browser */static voidSendErrorMessage(request_rec * r, const char *pszError){ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "mod_gsoap: %s", pszError); r->content_type = "text/html"; ap_rputs(DOCTYPE_HTML_3_2, r); ap_rputs("<HTML>\n", r); ap_rputs(" <HEAD>\n", r); ap_rputs(" <TITLE>Apache Soap Handler\n", r); ap_rputs(" </TITLE>\n", r); ap_rputs(" </HEAD>\n", r); ap_rputs(" <BODY>\n", r); ap_rputs(" <H1>mod_gsoap Apache SOAP Server Error</H1>\n", r); ap_rprintf(r, "<p><strong>%s</strong><br>Please see the documentation at <a href=\"http://www.webware.at/SOAP\">WebWare</a> for details.</p>", pszError); ap_rputs(" <H2>Content headers of the request</H2>\n", r); ListHeaders(r); ap_rputs("</BODY></HTML>\n", r);}static intsend_header_to_gsoap(void *pvoid, const char *key, const char *value){ gsoapRequestConfiguration *pRqConf = NULL; struct soap *psoap = (struct soap *)pvoid; if(NULL != psoap) { pRqConf = getRequestConfiguration(psoap); } if(NULL == pRqConf) { return 0; } if(0 == strcasecmp(key, "SOAPAction") || 0 == strcasecmp(key, "Content-Type") || 0 == strcasecmp(key, "Status") || 0 == strcasecmp(key, "Content-Length")) { psoap->fparsehdr(psoap, key, value); } return 1;}/* * Callback functions for gsoap. We must parse the headers ourselves and * we must handle send/receive properly. */static inthttp_post_header(struct soap *soap, const char *key, const char *value){ gsoapRequestConfiguration *pRqConf = getRequestConfiguration(soap); request_rec *r = NULL == pRqConf ? NULL : pRqConf->r; if(NULL != value) { if(0 == strcasecmp(key, "SOAPAction")) { apr_table_set(r->headers_out, key, value); } else if(0 == strcasecmp(key, "Content-Type")) { r->content_type = apr_pstrdup(r->pool, value); } else if(0 == strcasecmp(key, "Content-Length")) { ap_set_content_length(r, atoi(value)); } } return SOAP_OK;}/** gsoap function that requests the next piece of data from us */static size_tfrecv(struct soap *psoap, char *pBuf, apr_size_t len){ request_rec *r = NULL; apr_size_t nRet = 0; gsoapRequestConfiguration *pRqConf = getRequestConfiguration(psoap); if(NULL != pRqConf) { r = pRqConf->r; if(!pRqConf->headers_received) { apr_table_do(send_header_to_gsoap, psoap, r->headers_in, NULL); pRqConf->headers_received = true; } if(r->remaining > 0) { nRet = ap_get_client_block(r, pBuf, len > r->remaining ? r->remaining : len); } } return nRet;}static intfsend(struct soap *psoap, const char *pBuf, apr_size_t len){ int nRet = SOAP_OK; gsoapRequestConfiguration *pRqConf = getRequestConfiguration(psoap); if(NULL != pRqConf) { request_rec *r = pRqConf->r; if(!pRqConf->headers_sent) { // ap_send_http_header(r); pRqConf->headers_sent = true; } nRet = ap_rwrite(pBuf, len, r) == len ? SOAP_OK : SOAP_FAULT; } else { nRet = SOAP_FAULT; } return nRet;}/** instead of real header parsing we skip that. */static inthttp_parse(struct soap *psoap){ return SOAP_OK;}/** make sure we go through soap_send_fault(), which calls fpoll */static intfpoll(struct soap *psoap){ return SOAP_OK;}/* * plugin functions */static intmod_gsoap_plugin_copy(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src){ /* * should this be a deep copy? */ *dst = *src; return SOAP_OK;}static voidmod_gsoap_delete(struct soap *soap, struct soap_plugin *p){}static intmod_gsoap_plugin(struct soap *soap, struct soap_plugin *p, void *arg){ p->id = mod_gsoap_id; p->data = arg; p->fcopy = mod_gsoap_plugin_copy; p->fdelete = mod_gsoap_delete; return SOAP_OK;}static voidset_callbacks(request_rec * r, gsoapRequestConfiguration * pRqConf, struct soap *psoap){ gsoapConfiguration *pConfig = getConfiguration(r); struct apache_soap_interface *pIntf = pConfig->m_pLibraries->m_pIntf; pRqConf->r = r; pRqConf->http_parse = psoap->fparse; psoap->user = pRqConf; psoap->frecv = frecv; psoap->fsend = fsend; psoap->fparse = http_parse; psoap->fposthdr = http_post_header; psoap->fpoll = fpoll; if(NULL != pIntf->fsoap_init) { (*pIntf->fsoap_register_plugin_arg) (psoap, mod_gsoap_plugin, (void *)pRqConf, r); } else { psoap->user = pRqConf; }}/* * * * Now we declare our content handlers, which are invoked when the server * * encounters a document which our module is supposed to have a chance to * * see. (See mod_mime's SetHandler and AddHandler directives, and the * * mod_info and mod_status examples, for more details.) * * * Since content handlers are dumping data directly into the connexion * * (using the r*() routines, such as rputs() and rprintf()) without * * intervention by other parts of the server, they need to make * * sure any accumulated HTTP headers are sent first. This is done by * * calling send_http_header(). Otherwise, no header will be sent at all, * * and the output sent to the client will actually be HTTP-uncompliant. *//** * SOAP content handler. * * @return the value that instructs the caller concerning what happened and what to do next. * OK ("we did our thing") * DECLINED ("this isn't something with which we want to get involved") * HTTP_mumble ("an error status should be reported") */static intgsoap_handler(request_rec * r){ static const int nResponseBufferLen = IOBUF_CHUNK_SIZE; const char *pszError = NULL; struct soap *psoap = NULL; struct apache_soap_interface *pIntf = NULL; int nRet = 0; char *pszResponse = NULL; gsoapConfiguration *pConfig = getConfiguration(r); gsoapRequestConfiguration *pRqConf = NULL; /* * only handle soap requests */ if(!strstr(r->handler, "soap")) return DECLINED; /* * only handle POST requests */ if(r->method_number != M_POST && r->method_number != M_GET) return DECLINED; pszResponse = apr_pcalloc(r->pool, nResponseBufferLen); assert(NULL != pConfig); psoap = (struct soap *)apr_pcalloc(r->pool, sizeof(struct soap)); pRqConf = apr_pcalloc(r->pool, sizeof(gsoapRequestConfiguration)); pszError = SoapSharedLibraries_loadAllLibraries(pConfig->m_pLibraries, r->pool, r); pIntf = pConfig->m_pLibraries->m_pIntf; ap_update_mtime(r, r->request_time); ap_set_last_modified(r); if(NULL != pszError) { static bool bFirstTime = true; if(bFirstTime) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, pszError); bFirstTime = false; } } /* * as a next step, we prepare a buffer that sends the request as first line to gsoap. * Then the remaining data. * We start returning bytes on frecv from this buffer, until it is empty. * then it is not necessary to fiddle around with gsoap's request line parsing. */ if(NULL == pszError) { pRqConf->r = r; pRqConf->headers_sent = false; pRqConf->headers_received = false; pRqConf->m_pszAllHeaders = NULL; pRqConf->m_nHeaderLength = strlen(r->the_request) + 2; pRqConf->m_pszCurrentHeaderReadingPosition = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -