]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Refactor ap_read_request() to separate the parts that do socket reads
authorBrian Pane <brianp@apache.org>
Sat, 26 Nov 2005 03:20:52 +0000 (03:20 +0000)
committerBrian Pane <brianp@apache.org>
Sat, 26 Nov 2005 03:20:52 +0000 (03:20 +0000)
from the parts that update the request_rec.  This is a step towards
nonblocking, event-driven read support.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/async-read-dev@349068 13f79535-47bb-0310-9956-ffa450edef68

server/protocol.c

index f7f0a8ce1eb6073d72725c75f5b9489302b5fb79..30a3ce39b95d3916c4aed4247aa03a049643c662 100644 (file)
@@ -543,17 +543,75 @@ AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri)
     }
 }
 
-static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
+static void set_request_line(request_rec *r, char *line)
 {
+#if 0
+    conn_rec *conn = r->connection;
+#endif
     const char *ll;
     const char *uri;
     const char *pro;
+    int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
+    char http[5];
+    apr_size_t len;
+
+    r->request_time = apr_time_now();
+    ll = r->the_request = line;
+    r->method = ap_getword_white(r->pool, &ll);
+
+    uri = ap_getword_white(r->pool, &ll);
+
+    /* Provide quick information about the request method as soon as known */
+
+    r->method_number = ap_method_number_of(r->method);
+    if (r->method_number == M_GET && r->method[0] == 'H') {
+        r->header_only = 1;
+    }
+
+    ap_parse_uri(r, uri);
+
+    if (ll[0]) {
+        r->assbackwards = 0;
+        pro = ll;
+        len = strlen(ll);
+    } else {
+        r->assbackwards = 1;
+        pro = "HTTP/0.9";
+        len = 8;
+    }
+    r->protocol = apr_pstrmemdup(r->pool, pro, len);
+
+    /* XXX ap_update_connection_status(conn->id, "Protocol", r->protocol); */
+
+    /* Avoid sscanf in the common case */
+    if (len == 8
+        && pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P'
+        && pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.'
+        && apr_isdigit(pro[7])) {
+        r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0');
+    }
+    else if (3 == sscanf(r->protocol, "%4s/%u.%u", http, &major, &minor)
+             && (strcasecmp("http", http) == 0)
+             && (minor < HTTP_VERSION(1, 0)) ) { /* don't allow HTTP/0.1000 */
+        r->proto_num = HTTP_VERSION(major, minor);
+    }
+    else {
+        r->proto_num = HTTP_VERSION(1, 0);
+    }
 
 #if 0
-    conn_rec *conn = r->connection;
+/* XXX If we want to keep track of the Method, the protocol module should do
+ * it.  That support isn't in the scoreboard yet.  Hopefully next week
+ * sometime.   rbb */
+    ap_update_connection_status(AP_CHILD_THREAD_FROM_ID(conn->id), "Method",
+                                r->method);
 #endif
-    int major = 1, minor = 0;   /* Assume HTTP/1.0 if non-"HTTP" protocol */
-    char http[5];
+
+    return;
+}
+
+static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
+{
     apr_size_t len;
     int num_blank_lines = 0;
     int max_blank_lines = r->server->limit_req_fields;
@@ -605,55 +663,7 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
 
     /* we've probably got something to do, ignore graceful restart requests */
 
-    r->request_time = apr_time_now();
-    ll = r->the_request;
-    r->method = ap_getword_white(r->pool, &ll);
-
-#if 0
-/* XXX If we want to keep track of the Method, the protocol module should do
- * it.  That support isn't in the scoreboard yet.  Hopefully next week
- * sometime.   rbb */
-    ap_update_connection_status(AP_CHILD_THREAD_FROM_ID(conn->id), "Method",
-                                r->method);
-#endif
-
-    uri = ap_getword_white(r->pool, &ll);
-
-    /* Provide quick information about the request method as soon as known */
-
-    r->method_number = ap_method_number_of(r->method);
-    if (r->method_number == M_GET && r->method[0] == 'H') {
-        r->header_only = 1;
-    }
-
-    ap_parse_uri(r, uri);
-
-    if (ll[0]) {
-        r->assbackwards = 0;
-        pro = ll;
-        len = strlen(ll);
-    } else {
-        r->assbackwards = 1;
-        pro = "HTTP/0.9";
-        len = 8;
-    }
-    r->protocol = apr_pstrmemdup(r->pool, pro, len);
-
-    /* XXX ap_update_connection_status(conn->id, "Protocol", r->protocol); */
-
-    /* Avoid sscanf in the common case */
-    if (len == 8
-        && pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P'
-        && pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.'
-        && apr_isdigit(pro[7])) {
-        r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0');
-    }
-    else if (3 == sscanf(r->protocol, "%4s/%u.%u", http, &major, &minor)
-             && (strcasecmp("http", http) == 0)
-             && (minor < HTTP_VERSION(1, 0)) ) /* don't allow HTTP/0.1000 */
-        r->proto_num = HTTP_VERSION(major, minor);
-    else
-        r->proto_num = HTTP_VERSION(1, 0);
+    set_request_line(r, r->the_request);
 
     return 1;
 }
@@ -825,16 +835,11 @@ AP_DECLARE(void) ap_get_mime_headers(request_rec *r)
     apr_brigade_destroy(tmp_bb);
 }
 
-request_rec *ap_read_request(conn_rec *conn)
+static request_rec *init_request(conn_rec *conn)
 {
     request_rec *r;
     apr_pool_t *p;
-    const char *expect;
-    int access_status;
-    apr_bucket_brigade *tmp_bb;
-    apr_socket_t *csd;
-    apr_interval_time_t cur_timeout;
-
+    
     apr_pool_create(&p, conn->pool);
     apr_pool_tag(p, "request");
     r = apr_pcalloc(p, sizeof(request_rec));
@@ -876,77 +881,14 @@ request_rec *ap_read_request(conn_rec *conn)
      */
     r->used_path_info = AP_REQ_DEFAULT_PATH_INFO;
 
-    tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
-
-    /* Get the request... */
-    if (!read_request_line(r, tmp_bb)) {
-        if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "request failed: URI too long (longer than %d)", r->server->limit_req_line);
-            ap_send_error_response(r, 0);
-            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
-            ap_run_log_transaction(r);
-            apr_brigade_destroy(tmp_bb);
-            return r;
-        }
-
-        apr_brigade_destroy(tmp_bb);
-        return NULL;
-    }
-
-    /* We may have been in keep_alive_timeout mode, so toggle back
-     * to the normal timeout mode as we fetch the header lines,
-     * as necessary.
-     */
-    csd = ap_get_module_config(conn->conn_config, &core_module);
-    apr_socket_timeout_get(csd, &cur_timeout);
-    if (cur_timeout != conn->base_server->timeout) {
-        apr_socket_timeout_set(csd, conn->base_server->timeout);
-        cur_timeout = conn->base_server->timeout;
-    }
-
-    if (!r->assbackwards) {
-        ap_get_mime_headers_core(r, tmp_bb);
-        if (r->status != HTTP_REQUEST_TIME_OUT) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "request failed: error reading the headers");
-            ap_send_error_response(r, 0);
-            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
-            ap_run_log_transaction(r);
-            apr_brigade_destroy(tmp_bb);
-            return r;
-        }
-
-        if (apr_table_get(r->headers_in, "Transfer-Encoding")
-            && apr_table_get(r->headers_in, "Content-Length")) {
-            /* 2616 section 4.4, point 3: "if both Transfer-Encoding
-             * and Content-Length are received, the latter MUST be
-             * ignored"; so unset it here to prevent any confusion
-             * later. */
-            apr_table_unset(r->headers_in, "Content-Length");
-        }
-    }
-    else {
-        if (r->header_only) {
-            /*
-             * Client asked for headers only with HTTP/0.9, which doesn't send
-             * headers! Have to dink things just to make sure the error message
-             * comes through...
-             */
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                          "client sent invalid HTTP/0.9 request: HEAD %s",
-                          r->uri);
-            r->header_only = 0;
-            r->status = HTTP_BAD_REQUEST;
-            ap_send_error_response(r, 0);
-            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
-            ap_run_log_transaction(r);
-            apr_brigade_destroy(tmp_bb);
-            return r;
-        }
-    }
+    return r;
+}
 
-    apr_brigade_destroy(tmp_bb);
+static request_rec *request_post_read(request_rec *r, conn_rec *conn)
+{
+    apr_socket_t *csd;
+    const char *expect;
+    int access_status;
 
     r->status = HTTP_OK;                         /* Until further notice. */
 
@@ -958,9 +900,17 @@ request_rec *ap_read_request(conn_rec *conn)
     /* Toggle to the Host:-based vhost's timeout mode to fetch the
      * request body and send the response body, if needed.
      */
-    if (cur_timeout != r->server->timeout) {
-        apr_socket_timeout_set(csd, r->server->timeout);
-        cur_timeout = r->server->timeout;
+    csd = ap_get_module_config(conn->conn_config, &core_module);
+    apr_socket_timeout_set(csd, r->server->timeout);
+
+    if (apr_table_get(r->headers_in, "Transfer-Encoding") &&
+        apr_table_get(r->headers_in, "Content-Length")) {
+        /* 2616 section 4.4, point 3: "if both Transfer-Encoding
+         * and Content-Length are received, the latter MUST be
+         * ignored"; so unset it here to prevent any confusion
+         * later.
+         */
+        apr_table_unset(r->headers_in, "Content-Length");
     }
 
     /* we may have switched to another server */
@@ -1021,10 +971,84 @@ request_rec *ap_read_request(conn_rec *conn)
 
     ap_add_input_filter_handle(ap_http_input_filter_handle,
                                NULL, r, r->connection);
-
     return r;
 }
 
+request_rec *ap_read_request(conn_rec *conn)
+{
+    request_rec *r;
+    apr_bucket_brigade *tmp_bb;
+    apr_socket_t *csd;
+    apr_interval_time_t cur_timeout;
+
+    r = init_request(conn);
+
+    tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+
+    /* Get the request... */
+    if (!read_request_line(r, tmp_bb)) {
+        if (r->status == HTTP_REQUEST_URI_TOO_LARGE) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                          "request failed: URI too long (longer than %d)", r->server->limit_req_line);
+            ap_send_error_response(r, 0);
+            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+            ap_run_log_transaction(r);
+            apr_brigade_destroy(tmp_bb);
+            return r;
+        }
+
+        apr_brigade_destroy(tmp_bb);
+        return NULL;
+    }
+
+    /* We may have been in keep_alive_timeout mode, so toggle back
+     * to the normal timeout mode as we fetch the header lines,
+     * as necessary.
+     */
+    csd = ap_get_module_config(conn->conn_config, &core_module);
+    apr_socket_timeout_get(csd, &cur_timeout);
+    if (cur_timeout != conn->base_server->timeout) {
+        apr_socket_timeout_set(csd, conn->base_server->timeout);
+        cur_timeout = conn->base_server->timeout;
+    }
+
+    if (!r->assbackwards) {
+        ap_get_mime_headers_core(r, tmp_bb);
+        if (r->status != HTTP_REQUEST_TIME_OUT) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                          "request failed: error reading the headers");
+            ap_send_error_response(r, 0);
+            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+            ap_run_log_transaction(r);
+            apr_brigade_destroy(tmp_bb);
+            return r;
+        }
+    }
+    else {
+        if (r->header_only) {
+            /*
+             * Client asked for headers only with HTTP/0.9, which doesn't send
+             * headers! Have to dink things just to make sure the error message
+             * comes through...
+             */
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                          "client sent invalid HTTP/0.9 request: HEAD %s",
+                          r->uri);
+            r->header_only = 0;
+            r->status = HTTP_BAD_REQUEST;
+            ap_send_error_response(r, 0);
+            ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+            ap_run_log_transaction(r);
+            apr_brigade_destroy(tmp_bb);
+            return r;
+        }
+    }
+
+    apr_brigade_destroy(tmp_bb);
+
+    return request_post_read(r, conn);
+}
+
 /* if a request with a body creates a subrequest, clone the original request's
  * input headers minus any headers pertaining to the body which has already
  * been read.  out-of-line helper function for ap_set_sub_req_protocol.