httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pque...@apache.org
Subject svn commit: r359043 - /httpd/httpd/branches/fcgi-proxy-dev/modules/proxy/mod_proxy_fcgi.c
Date Mon, 26 Dec 2005 08:57:09 GMT
Author: pquerna
Date: Mon Dec 26 00:57:06 2005
New Revision: 359043

URL: http://svn.apache.org/viewcvs?rev=359043&view=rev
Log:
Add support for sending the environment to the backend fastcgi process 
to mod_proxy_fcgi.

* modules/proxy/mod_proxy_fcgi.c
  (proxy_fcgi_canon): Remove unused variables, wrap a long line.
  (send_begin_request): Helper function to send the FCGI_BEGIN_REQUEST
   message.
  (send_environment): Helper function to send the environment.
  (fcgi_do_request): Use send_begin_request and send_environment.

Submitted By: Garrett Rooney <rooneg apache.org>

Modified:
    httpd/httpd/branches/fcgi-proxy-dev/modules/proxy/mod_proxy_fcgi.c

Modified: httpd/httpd/branches/fcgi-proxy-dev/modules/proxy/mod_proxy_fcgi.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/fcgi-proxy-dev/modules/proxy/mod_proxy_fcgi.c?rev=359043&r1=359042&r2=359043&view=diff
==============================================================================
--- httpd/httpd/branches/fcgi-proxy-dev/modules/proxy/mod_proxy_fcgi.c (original)
+++ httpd/httpd/branches/fcgi-proxy-dev/modules/proxy/mod_proxy_fcgi.c Mon Dec 26 00:57:06
2005
@@ -26,7 +26,7 @@
  */
 static int proxy_fcgi_canon(request_rec *r, char *url)
 {
-    char *host, *path, *search, sport[7];
+    char *host, sport[7];
     const char *err;
     const char* scheme;
     apr_port_t port = 8000;
@@ -61,7 +61,8 @@
             host = apr_pstrcat(r->pool, "[", host, "]", NULL);
         }
         
-        r->filename = apr_pstrcat(r->pool, "proxy:", scheme, host, sport, "/", NULL);
+        r->filename = apr_pstrcat(r->pool, "proxy:", scheme, host, sport, "/",
+                                  NULL);
     }
     else if (strncmp(url, "local://", 8) == 0) {
         url += 6;
@@ -124,49 +125,208 @@
     unsigned char reserved[5];
 } fcgi_begin_request_body;
 
+
+static apr_status_t send_begin_request (proxy_conn_rec *conn, int request_id)
+{
+    struct iovec vec[2];
+    fcgi_header header;
+    fcgi_begin_request_body brb;
+    apr_size_t len;
+
+    header.version = FCGI_VERSION;
+    header.type = FCGI_BEGIN_REQUEST;
+    header.requestIdB1 = ((request_id >> 8) & 0xff);
+    header.requestIdB0 = ((request_id) & 0xff); 
+    header.contentLengthB1 = ((sizeof(brb) >> 8) & 0xff);
+    header.contentLengthB0 = ((sizeof(brb)) & 0xff); 
+    header.paddingLength = 0;
+
+    brb.roleB1 = ((FCGI_RESPONDER >> 8) & 0xff);
+    brb.roleB0 = ((FCGI_RESPONDER) & 0xff); 
+    brb.flags = FCGI_KEEP_CONN;
+
+    vec[0].iov_base = &header;
+    vec[0].iov_len = sizeof(header);
+    vec[1].iov_base = &brb;
+    vec[1].iov_len = sizeof(brb);
+
+    return apr_socket_sendv(conn->sock, vec, 2, &len);
+}
+
+static apr_status_t send_environment (proxy_conn_rec *conn, request_rec *r, 
+                                      int request_id)
+{
+    const apr_array_header_t *envarr;
+    const apr_table_entry_t *elts;
+    struct iovec vec[2];
+    fcgi_header header;
+    apr_size_t bodylen;
+    char *body, *itr;
+    apr_status_t rv;
+    apr_size_t len;
+    int i;
+
+    header.version = FCGI_VERSION;
+    header.type = FCGI_PARAMS;
+    header.requestIdB1 = ((request_id >> 8) & 0xff);
+    header.requestIdB0 = ((request_id) & 0xff); 
+
+    ap_add_common_vars(r);
+    ap_add_cgi_vars(r);
+
+    /* XXX are there any FastCGI specific env vars we need to send? */
+
+    /* XXX What if there is over 64k worth of data in the env? */
+    bodylen = 0;
+
+    /* XXX mod_cgi/mod_cgid use ap_create_environment here, which fills in
+     *     the TZ value specially.  We could use that, but it would mean
+     *     parsing the key/value pairs back OUT of the allocated env array,
+     *     not to mention allocating a totally useless array in the first
+     *     place, which would suck. */
+
+    envarr = apr_table_elts(r->subprocess_env);
+
+    elts = (const apr_table_entry_t *) envarr->elts;
+
+    for (i = 0; i < envarr->nelts; ++i) {
+        apr_size_t keylen, vallen;
+
+        if (! elts[i].key) {
+            continue;
+        }
+
+        keylen = strlen(elts[i].key);
+
+        if (keylen >> 7 == 0) {
+            bodylen += 1;
+        }
+        else {
+            bodylen += 4;
+        }
+
+        bodylen += keylen;
+
+        vallen = strlen(elts[i].val);
+
+        if (vallen >> 7 == 0) {
+            bodylen += 1;
+        }
+        else {
+            bodylen += 4;
+        }
+
+        bodylen += vallen;
+    }
+
+    body = apr_pcalloc(r->pool, bodylen);
+
+    itr = body;
+
+    for (i = 0; i < envarr->nelts; ++i) {
+        apr_size_t keylen, vallen;
+       
+        if (! elts[i].key) {
+            continue;
+        }
+
+        keylen = strlen(elts[i].key);
+
+        if (keylen >> 7 == 0) {
+            itr[0] = keylen & 0xff;
+            itr += 1;
+        }
+        else {
+            itr[0] = ((keylen >> 24) & 0xff) | 0x80;
+            itr[1] = ((keylen >> 16) & 0xff);
+            itr[2] = ((keylen >> 8) & 0xff);
+            itr[3] = ((keylen) & 0xff);
+            itr += 4;
+        }
+
+        vallen = strlen(elts[i].val);
+
+        if (vallen >> 7 == 0) {
+            itr[0] = vallen & 0xff;
+            itr += 1;
+        }
+        else {
+            itr[0] = ((vallen >> 24) & 0xff) | 0x80;
+            itr[1] = ((vallen >> 16) & 0xff);
+            itr[2] = ((vallen >> 8) & 0xff);
+            itr[3] = ((vallen) & 0xff);
+            itr += 4;
+        }
+
+        memcpy(itr, elts[i].key, keylen);
+        itr += keylen;
+
+        memcpy(itr, elts[i].val, vallen);
+        itr += vallen;
+    }
+
+    /* First we send the actual env... */
+    header.contentLengthB1 = ((bodylen >> 8) & 0xff);
+    header.contentLengthB0 = ((bodylen) & 0xff); 
+    header.paddingLength = 0;
+
+    vec[0].iov_base = &header;
+    vec[0].iov_len = sizeof(header);
+    vec[1].iov_base = body;
+    vec[1].iov_len = bodylen;
+
+    rv = apr_socket_sendv(conn->sock, vec, 2, &len);
+    if (rv) {
+        return rv;
+    }
+
+    /* Then, an empty record to signify the end of the stream. */
+    header.contentLengthB1 = 0;
+    header.contentLengthB0 = 0;
+    header.paddingLength = 0;
+
+    vec[0].iov_base = &header;
+    vec[0].iov_len = sizeof(header);
+
+    return apr_socket_sendv(conn->sock, vec, 1, &len);
+}
+
 /*
  * process the request and write the response.
  */
 static int fcgi_do_request(apr_pool_t *p, request_rec *r,
-                            proxy_conn_rec *conn,
-                            conn_rec *origin,
-                            proxy_dir_conf *conf,
-                            apr_uri_t *uri,
-                            char *url, char *server_portstr)
+                           proxy_conn_rec *conn,
+                           conn_rec *origin,
+                           proxy_dir_conf *conf,
+                           apr_uri_t *uri,
+                           char *url, char *server_portstr)
 {
+    /* Request IDs are arbitrary numbers that we assign to a
+     * single request. This would allow multiplex/pipelinig of 
+     * multiple requests to the same FastCGI connection, but 
+     * we don't support that, and always use a value of '1' to
+     * keep things simple. */
+    int request_id = 1; 
     apr_status_t rv;
-
-    {
-        struct iovec vec[2];
-        fcgi_header header;
-        fcgi_begin_request_body brb;
-    
-        /* Step 1: Send FCGI_BEGIN_REQUEST */
-        header.version = FCGI_VERSION;
-        header.type = FCGI_BEGIN_REQUEST;
-        header.requestIdB1 = ((1 >> 8) & 0xff);
-        header.requestIdB0 = ((1) & 0xff); 
-        header.contentLengthB1 = ((sizeof(brb) >> 8) & 0xff);
-        header.contentLengthB0 = ((sizeof(brb)) & 0xff); 
-        header.paddingLength = 0;
-    
-        brb.roleB1 = ((FCGI_RESPONDER >> 8) & 0xff);
-        brb.roleB0 = ((FCGI_RESPONDER) & 0xff); 
-        brb.flags = FCGI_KEEP_CONN;
-
-        vec[0].iov_base = &header;
-        vec[0].iov_len = sizeof(header);
-        vec[1].iov_base = &brb;
-        vec[1].iov_len = sizeof(brb);
-
-        rv = apr_socket_sendv(conn->sock, vec, 2, NULL);
-        if (rv != APR_SUCCESS) {
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
-                         "proxy: FCGI: Failed Writing Request to %s:", server_portstr);
-        }
+   
+    /* Step 1: Send FCGI_BEGIN_REQUEST */
+    rv = send_begin_request(conn, request_id);
+    if (rv != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
+                     "proxy: FCGI: Failed Writing Request to %s:",
+                     server_portstr);
+        return HTTP_SERVICE_UNAVAILABLE;
     }
     
     /* Step 2: Send Enviroment via FCGI_PARAMS */
+    rv = send_environment(conn, r, request_id);
+    if (rv != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
+                     "proxy: FCGI: Failed writing Environment to %s:",
+                     server_portstr);
+        return HTTP_SERVICE_UNAVAILABLE;
+    }
+
     /* Step 3: Send Request Body via FCGI_STDIN */
     /* Step 4: Read for CGI_STDOUT|CGI_STDERR */
     /* Step 5: Parse reply headers. */



Mime
View raw message