You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by pq...@apache.org on 2005/12/27 08:23:47 UTC
svn commit: r359183 -
/httpd/httpd/branches/fcgi-proxy-dev/modules/proxy/mod_proxy_fcgi.c
Author: pquerna
Date: Mon Dec 26 23:23:44 2005
New Revision: 359183
URL: http://svn.apache.org/viewcvs?rev=359183&view=rev
Log:
Add support for sending the FASTCGI_STDIN stream of data to the fastcgi
process.
* modules/proxy/mod_proxy_fcgi.c
(fill_in_header): New helper function.
(send_begin_request, send_environment): Fix formatting, use fill_in_header.
(MAX_INPUT_BYTES): New constant.
(send_stdin): New function.
(fcgi_do_request): Send the body of the request via send_stdin.
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=359183&r1=359182&r2=359183&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 23:23:44 2005
@@ -125,21 +125,37 @@
unsigned char reserved[5];
} fcgi_begin_request_body;
+/*
+ * Initialize a fastcgi_header H of type TYPE with id ID.
+ *
+ * Sets the content length and padding length to 0, the caller should
+ * reset them to more appropriate values later if needed.
+ */
+static void fill_in_header(fcgi_header *h, int type, int id)
+{
+ h->version = FCGI_VERSION;
+
+ h->type = type;
+
+ h->requestIdB1 = ((id >> 8) & 0xff);
+ h->requestIdB0 = ((id) & 0xff);
+
+ h->contentLengthB1 = 0;
+ h->contentLengthB0 = 0;
+ h->paddingLength = 0;
+}
-static apr_status_t send_begin_request (proxy_conn_rec *conn, int request_id)
+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);
+ fill_in_header(&header, FCGI_BEGIN_REQUEST, request_id);
+
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);
@@ -153,8 +169,8 @@
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)
+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;
@@ -166,10 +182,7 @@
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);
+ fill_in_header(&header, FCGI_PARAMS, request_id);
ap_add_common_vars(r);
ap_add_cgi_vars(r);
@@ -292,6 +305,87 @@
}
/*
+ * An arbitrary buffer size for reading the stdin data from the client.
+ *
+ * Need to find a "better" value here, or at least justify the current
+ * value somehow.
+ */
+#define MAX_INPUT_BYTES 1024
+
+static apr_status_t send_stdin(proxy_conn_rec *conn, request_rec *r,
+ int request_id)
+{
+ apr_bucket_brigade *input_brigade;
+ apr_status_t rv = APR_SUCCESS;
+ struct iovec vec[2];
+ fcgi_header header;
+ int done = 0;
+
+ fill_in_header(&header, FCGI_STDIN, request_id);
+
+ input_brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+
+ while (! done) {
+ char buff[MAX_INPUT_BYTES];
+ apr_size_t buflen, len;
+
+ rv = ap_get_brigade(r->input_filters, input_brigade,
+ AP_MODE_READBYTES, APR_BLOCK_READ,
+ MAX_INPUT_BYTES);
+ if (rv != APR_SUCCESS) {
+ break;
+ }
+
+ if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
+ done = 1;
+ }
+
+ buflen = sizeof(buff);
+
+ rv = apr_brigade_flatten(input_brigade, buff, &buflen);
+
+ apr_brigade_cleanup(input_brigade);
+
+ if (rv != APR_SUCCESS) {
+ break;
+ }
+
+ header.contentLengthB1 = ((buflen >> 8) & 0xff);
+ header.contentLengthB0 = ((buflen) & 0xff);
+
+ vec[0].iov_base = &header;
+ vec[0].iov_len = sizeof(header);
+ vec[1].iov_base = buff;
+ vec[1].iov_len = buflen;
+
+ rv = apr_socket_sendv(conn->sock, vec, 2, &len);
+ if (rv != APR_SUCCESS) {
+ break;
+ }
+
+ /* XXX AJP updates conn->worker->s->transferred here, do we need to? */
+ }
+
+ /* If we got here successfully it means we sent all the data, so we need
+ * to send the final empty record to signify the end of the stream. */
+ if (rv == APR_SUCCESS) {
+ apr_size_t len;
+
+ header.contentLengthB1 = 0;
+ header.contentLengthB0 = 0;
+
+ vec[0].iov_base = &header;
+ vec[0].iov_len = sizeof(header);
+
+ rv = apr_socket_sendv(conn->sock, vec, 1, &len);
+ }
+
+ apr_brigade_destroy(input_brigade);
+
+ return rv;
+}
+
+/*
* process the request and write the response.
*/
static int fcgi_do_request(apr_pool_t *p, request_rec *r,
@@ -328,6 +422,14 @@
}
/* Step 3: Send Request Body via FCGI_STDIN */
+ rv = send_stdin(conn, r, request_id);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
+ "proxy: FCGI: Failed writing STDIN to %s:",
+ server_portstr);
+ return HTTP_SERVICE_UNAVAILABLE;
+ }
+
/* Step 4: Read for CGI_STDOUT|CGI_STDERR */
/* Step 5: Parse reply headers. */
/* Step 6: Stream reply body. */