pier 01/05/09 23:07:34
Modified: connectors/apache-1.3 mod_webapp.c
Log:
Updated module to reflect changes in library
Revision Changes Path
1.11 +387 -44 jakarta-tomcat-4.0/connectors/apache-1.3/mod_webapp.c
Index: mod_webapp.c
===================================================================
RCS file: /home/cvs/jakarta-tomcat-4.0/connectors/apache-1.3/mod_webapp.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- mod_webapp.c 2001/04/17 14:54:54 1.10
+++ mod_webapp.c 2001/05/10 06:07:33 1.11
@@ -57,7 +57,7 @@
/**
* @author Pier Fumagalli <mailto:[EMAIL PROTECTED]>
- * @version $Id: mod_webapp.c,v 1.10 2001/04/17 14:54:54 pier Exp $
+ * @version $Id: mod_webapp.c,v 1.11 2001/05/10 06:07:33 pier Exp $
*/
#include <httpd.h>
@@ -75,56 +75,399 @@
/* Module declaration */
module webapp_module;
+/* Wether the WebApp Library has been initialized or not */
+static boolean wam_initialized=FALSE;
+/* The list of configured connections */
+static wa_chain *wam_connections=NULL;
/* ************************************************************************* */
-/* CONFUGURATION ROUTINES */
+/* MODULE AND LIBRARY INITIALIZATION AND DESTRUCTION */
/* ************************************************************************* */
-/**
- * Configure a webapp connection.
- *
- * @param name The connection unique name.
- * @param connector The name of the WebApp connector to use.
- * @param parameters Connector-specific parameters (can be NULL).
- */
-static const char *webapp_config_connection (cmd_parms *cmd, void *mconfig,
- char *name, char *provider,
- char *parameter) {
- return(wa_connection_create(name, provider, parameter));
+/* Destroy the module and the WebApp Library */
+static void wam_destroy(void *nil) {
+ if (!wam_initialized) return;
+ wa_destroy();
+ wam_initialized=FALSE;
}
-/**
- * Configure a webapp application mount point.
- *
- * @param name The web application name.
- * @param cname The connection name.
- * @param path The web application root path.
- */
-static const char *webapp_config_mount (cmd_parms *cmd, void *mconfig,
- char *name, char *cname, char *path) {
- server_rec *s=cmd->server;
- wa_host *host=NULL;
+/* Initialize the module and the WebApp Library */
+static const char *wam_init(pool *p) {
+ const char *ret=NULL;
+
+ if(wam_initialized) return(NULL);
+ if ((ret=wa_init())!=NULL) return(ret);
+ ap_register_cleanup(p,NULL,wam_destroy,NULL);
+ wam_initialized=TRUE;
+ return(NULL);
+}
+
+/* ************************************************************************* */
+/* CONFIGURATION DIRECTIVES HANDLING */
+/* ************************************************************************* */
+
+/* Retrieve or create a wa_virtualhost structure for an Apache server_rec
+ and store it as the per-server module configuration */
+const char *wam_server(server_rec *svr, wa_virtualhost **h) {
+ wa_virtualhost *host=NULL;
+ char *name=svr->server_hostname;
+ int port=(int)svr->port;
+ const char *ret=NULL;
+
+ /* Attempt to retrieve the wa_virtualhost structure and create it
+ if necessary, storing it into the server_rec structure. */
+ host=ap_get_module_config(svr->module_config,&webapp_module);
+
+ /* If we already configured the wa_virtualhost, simply return it */
+ if (host!=NULL) {
+ *h=host;
+ return(NULL);
+ }
+
+ /* The wa_virtualhost was not found in the per-server module configuration
+ so we'll try to create it. */
+ ret=wa_cvirtualhost(&host,name,port);
+ if (ret!=NULL) {
+ *h=NULL;
+ return(ret);
+ }
+
+ /* We successfully created a wa_virtualhost structure, store it in the
+ per-server configuration member and return it. */
+ ap_set_module_config(svr->module_config,&webapp_module,host);
+ *h=host;
+ return(NULL);
+}
+
+/* Process the WebAppConnection directive. */
+static const char *wam_directive_connection(cmd_parms *cmd, void *mconfig,
+ char *name, char *prov, char *p) {
+ wa_connection *conn=NULL;
+ const char *ret=NULL;
+ wa_chain *elem=NULL;
+
+ /* Initialize the library */
+ if ((ret=wam_init(cmd->pool))!=NULL) return(ret);
+
+ /* Attempt to create a new wa_connection structure */
+ if ((ret=wa_cconnection(&conn,name,prov,p))!=NULL) return(ret);
+
+ /* Check if we have a duplicate connection with this name */
+ elem=wam_connections;
+ while (elem!=NULL) {
+ wa_connection *curr=(wa_connection *)elem->curr;
+ if (strcasecmp(conn->name,curr->name)==0)
+ return("Duplicate connection name");
+ elem=elem->next;
+ }
+
+ /* We don't have a duplicate connection, store it locally */
+ elem=apr_palloc(wa_pool,sizeof(wa_chain));
+ elem->curr=conn;
+ elem->next=wam_connections;
+ wam_connections=elem;
+ return(NULL);
+}
+
+/* Process the WebAppDeploy directive */
+static const char *wam_directive_deploy(cmd_parms *cmd, void *mconfig,
+ char *name, char *cnam, char *path) {
+ wa_virtualhost *host=NULL;
+ wa_application *appl=NULL;
wa_connection *conn=NULL;
- const char *mesg=NULL;
+ wa_chain *elem=NULL;
+ const char *ret=NULL;
+
+ /* Initialize the library and retrieve/create the host structure */
+ if ((ret=wam_init(cmd->pool))!=NULL) return(ret);
+ if ((ret=wam_server(cmd->server,&host))!=NULL) return(ret);
+
+ /* Retrieve the connection */
+ elem=wam_connections;
+ while(elem!=NULL) {
+ wa_connection *curr=(wa_connection *)elem->curr;
+ if (strcasecmp(curr->name,cnam)==0) {
+ conn=curr;
+ break;
+ }
+ elem=elem->next;
+ }
+ if (conn==NULL) return("Specified connection not configured");
+
+ /* Create a new wa_application member */
+ if ((ret=wa_capplication(&appl,name,path))!=NULL) return(ret);
+
+ /* Deploy the web application */
+ if ((ret=wa_deploy(appl,host,conn))!=NULL) return(ret);
+
+ /* Done */
+ return(NULL);
+}
+
+/* Process the WebAppInfo directive */
+static const char *wam_directive_info(cmd_parms *cmd, void *mconfig,
+ char *path) {
+ const char *ret;
+
+ /* We simply divert this call to a WebAppConnection and a WebAppDeploy
+ calls */
+ if ((ret=wam_directive_connection(cmd,mconfig,"_INFO_","info",""))!=NULL)
+ return(ret);
+ if ((ret=wam_directive_deploy(cmd,mconfig,"_INFO_","_INFO_",path))!=NULL)
+ return(ret);
+
+ return(NULL);
+}
+
+/* The list of Directives for the WebApp module */
+static const command_rec wam_directives[] = {
+ {
+ "WebAppInfo", /* directive name */
+ wam_directive_info, /* config action routine */
+ NULL, /* argument to include in call */
+ OR_OPTIONS, /* where available */
+ TAKE1, /* arguments */
+ "<uri-path>"
+ },{
+ "WebAppConnection", /* directive name */
+ wam_directive_connection, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ TAKE23, /* arguments */
+ "<name> <provider> [optional parameter]"
+ }, {
+ "WebAppDeploy", /* directive name */
+ wam_directive_deploy, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ TAKE3, /* arguments */
+ "<name> <connection> <uri-path>"
+ }, {NULL}
+
+};
+
+/* ************************************************************************* */
+/* CALLBACKS FROM WEB SERVER */
+/* ************************************************************************* */
+
+/* Log a message associated with a request */
+void wam_handler_log(wa_request *r, const char *f, const int l, char *msg) {
+ request_rec *req=(request_rec *)r->data;
+ server_rec *svr=req->server;
+
+ ap_log_error(f,l,APLOG_NOERRNO|APLOG_ERR,svr,"%s",msg);
+}
+
+/* Set the HTTP status of the response. */
+void wam_handler_setstatus(wa_request *r, int status) {
+ request_rec *req=(request_rec *)r->data;
+ server_rec *svr=req->server;
+
+ req->status=status;
+}
+
+/* Set the MIME Content-Type of the response. */
+void wam_handler_setctype(wa_request *r, char *type) {
+ request_rec *req=(request_rec *)r->data;
+ server_rec *svr=req->server;
+
+ if (type==NULL) return;
+
+ req->content_type=ap_pstrdup(req->pool,type);
+ ap_table_add(req->headers_out,"Content-Type",ap_pstrdup(req->pool,type));
+}
+
+/* Set a header in the HTTP response. */
+void wam_handler_setheader(wa_request *r, char *name, char *value) {
+ request_rec *req=(request_rec *)r->data;
+ server_rec *svr=req->server;
+
+ if (name==NULL) return;
+ if (value==NULL) value="";
+
+ ap_table_add(req->headers_out,ap_pstrdup(req->pool,name),
+ ap_pstrdup(req->pool,value));
+}
+
+/* Commit the first part of the response (status and headers) */
+void wam_handler_commit(wa_request *r) {
+ request_rec *req=(request_rec *)r->data;
+ server_rec *svr=req->server;
+
+ ap_send_http_header(req);
+// ap_rflush(req);
+}
+
+/* Flush all data in the response buffer */
+void wam_handler_flush(wa_request *r) {
+ request_rec *req=(request_rec *)r->data;
+ server_rec *svr=req->server;
+
+ ap_rflush(req);
+}
+
+/* Read a chunk of text from the request body */
+int wam_handler_read(wa_request *r, char *buf, int len) {
+ request_rec *req=(request_rec *)r->data;
+ server_rec *svr=req->server;
+ long ret=0;
+
+ // Check if we have something to read.
+ if (r->clen==0) return(0);
+
+ // Check if we had an error previously.
+ if (r->rlen==-1) return(-1);
+
+ // Send HTTP_CONTINUE to client when we're ready to read for the first time.
+ if (r->rlen==0) {
+ if (ap_should_client_block(req)==0) return(0);
+ }
+
+ // Read some data from the client and fill the buffer.
+ ret=ap_get_client_block(req,buf,len);
+ if (ret==-1) {
+ r->rlen=-1;
+ return(-1);
+ }
+
+ // We did read some bytes, increment the current rlen counter and return.
+ r->rlen+=ret;
+ return((int)ret);
+}
- // Retrieve (or create) our host structure
- host=wa_host_get(s->server_hostname,s->port);
- if (host==NULL) {
- mesg=wa_host_create(s->server_hostname,s->port);
- if (mesg!=NULL) return(mesg);
- host=wa_host_get(s->server_hostname,s->port);
- if (host==NULL) return("Cannot retrieve host information");
- }
-
- // Setup the webapp name, connection and path
- conn=wa_connection_get(cname);
- if (conn==NULL) return("Invalid connection name specified");
- return(wa_host_setapp(host, name, path, conn));
+/* Write a chunk of text into the response body. */
+int wam_handler_write(wa_request *r, char *buf, int len) {
+ request_rec *req=(request_rec *)r->data;
+ server_rec *svr=req->server;
+
+ return(ap_rwrite(buf, len, req));
+}
+
+/* The structure holding all callback handling functions for the library */
+static wa_handler wam_handler = {
+ wam_handler_log,
+ wam_handler_setstatus,
+ wam_handler_setctype,
+ wam_handler_setheader,
+ wam_handler_commit,
+ wam_handler_flush,
+ wam_handler_read,
+ wam_handler_write,
+};
+
+/* ************************************************************************* */
+/* REQUEST HANDLING */
+/* ************************************************************************* */
+
+/* Match an Apache request */
+static int wam_match(request_rec *r) {
+ wa_virtualhost *host=NULL;
+ wa_application *appl=NULL;
+ wa_chain *elem=NULL;
+
+ /* Check if this host was recognized */
+ host=ap_get_module_config(r->server->module_config,&webapp_module);
+ if (host==NULL) return(DECLINED);
+
+ /* Check if the uri is contained in one of our applications root path */
+ elem=host->apps;
+ while(elem!=NULL) {
+ appl=(wa_application *)elem->curr;
+ if (strncmp(appl->rpth,r->uri,strlen(appl->rpth))==0) break;
+
+ appl=NULL;
+ elem=elem->next;
+ }
+ if (appl==NULL) return(DECLINED);
+
+ /* The uri path is matched: set the handler and return */
+ r->handler=ap_pstrdup(r->pool,"webapp-handler");
- return (NULL);
+ /* Set the webapp request structure into Apache's request structure */
+ ap_set_module_config(r->request_config, &webapp_module, appl);
+ return(OK);
}
+/* Handle the current request */
+static int wam_invoke(request_rec *r) {
+ server_rec *svr=r->server;
+ conn_rec *con=r->connection;
+ wa_application *appl=NULL;
+ wa_request *req=NULL;
+ const char *msg=NULL;
+ char *stmp=NULL;
+ char *ctmp=NULL;
+ int ret=0;
+
+ /* Try to get a hold on the webapp request structure */
+ appl=(wa_application *)ap_get_module_config(r->request_config,
+
&webapp_module);
+ if (appl==NULL) return(DECLINED);
+
+ /* Allocate the webapp request structure */
+ if ((msg=wa_ralloc(&req, &wam_handler, r))!=NULL) {
+ ap_log_error(APLOG_MARK,APLOG_NOERRNO|APLOG_ERR,svr,"%s",msg);
+ return(HTTP_INTERNAL_SERVER_ERROR);
+ }
+
+ /* Set up the WebApp Library request structure client and server host
+ data (from the connection */
+ stmp=(char *)r->hostname;
+ ctmp=(char *)ap_get_remote_host(con,r->per_dir_config, REMOTE_HOST);
+ req->serv->host=apr_pstrdup(req->pool,stmp);
+ req->clnt->host=apr_pstrdup(req->pool,ctmp);
+ req->serv->addr=apr_pstrdup(req->pool,con->local_ip);
+ req->clnt->addr=apr_pstrdup(req->pool,con->remote_ip);
+ req->serv->port=con->local_addr.sin_port;
+ req->clnt->port=con->remote_addr.sin_port;
+
+ /* Set up all other members of the request structure */
+ req->meth=apr_pstrdup(req->pool,(char *)r->method);
+ req->ruri=apr_pstrdup(req->pool,r->uri);
+ req->args=apr_pstrdup(req->pool,r->args);
+ req->prot=apr_pstrdup(req->pool,r->protocol);
+ req->schm=apr_pstrdup(req->pool,ap_http_method(r));
+ req->user=apr_pstrdup(req->pool,con->user);
+ req->auth=apr_pstrdup(req->pool,con->ap_auth_type);
+ req->clen=0;
+ req->rlen=0;
+
+ /* Copy headers into webapp request structure */
+ if (r->headers_in!=NULL) {
+ array_header *arr=ap_table_elts(r->headers_in);
+ table_entry *ele=(table_entry *)arr->elts;
+ int x=0;
+
+ // Copy header pointers one by one
+ for (x=0; x<arr->nelts;x++) {
+ if (ele[x].key==NULL) continue;
+ if (ele[x].val==NULL) continue;
+ apr_table_add(req->hdrs,apr_pstrdup(req->pool,ele[x].key),
+
apr_pstrdup(req->pool,ele[x].val));
+ if (strcasecmp(ele[x].key,"Content-Length")==0)
+ req->clen=atol(ele[x].val);
+ }
+ }
+
+ /* Invoke the request */
+ ret=wa_rinvoke(req,appl);
+
+ /* Destroy the request member */
+ wa_rfree(req);
+ ap_rflush(r);
+
+ return(OK);
+}
+
+
+
+/* List of all available Apache handlers */
+static const handler_rec wam_handlers[] = {
+ {"webapp-handler", wam_invoke},
+ {NULL}
+};
+
/* Apache module declaration */
module webapp_module = {
STANDARD_MODULE_STUFF,
@@ -133,9 +476,9 @@
NULL, /* dir config merger */
NULL, /* server config creator */
NULL, /* server config merger */
- NULL, //webapp_commands, /* command table */
- NULL, //webapp_handlers, /* [9] list of handlers */
- NULL, //webapp_translate, /* [2] filename-to-URI translation
*/
+ wam_directives, /* command table */
+ wam_handlers, /* [9] list of handlers */
+ wam_match, /* [2] filename-to-URI translation */
NULL, /* [5] check/validate user_id */
NULL, /* [6] check user_id is valid *here* */
NULL, /* [4] check access by host address */
@@ -143,7 +486,7 @@
NULL, /* [8] fixups */
NULL, /* [10] logger */
NULL, /* [3] header parser */
- NULL, //webapp_init, /* child initializer */
- NULL, //webapp_exit, /* child exit/cleanup */
+ NULL, //webapp_init, /* child initializer */
+ NULL, //webapp_exit, /* child exit/cleanup */
NULL /* [1] post read_request handling */
};