On Fri, Apr 12, 2002 at 05:34:27PM -0700, Roy T. Fielding wrote:
> Also, the code that reads the chunk end is failing to read the trailers.

This patch should resolve this concern by placing get_mime_headers()
in http_protocol.c, adding ap_ prefix, and exporting it.  Previously,
it was static and in server/protocol.c.  I don't believe this
function belongs in server/protocol.c since it is so HTTP-specific,
but we *could* keep it in server/protocol.c if people want.

Thoughts?  This is *an* API change (a new call), but one we have
to make in order to handle trailers correctly.  -- justin

Index: include/http_protocol.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/http_protocol.h,v
retrieving revision 1.75
diff -u -r1.75 http_protocol.h
--- include/http_protocol.h     29 Mar 2002 08:17:19 -0000      1.75
+++ include/http_protocol.h     13 Apr 2002 03:20:03 -0000
@@ -91,6 +91,12 @@
  */ 
 request_rec *ap_read_request(conn_rec *c);
 
+/**
+ * Read the mime-encoded headers.
+ * @param r The current request
+ */
+void ap_get_mime_headers(request_rec *r);
+
 /* Finish up stuff after a request */
 
 /**
Index: modules/http/http_protocol.c
===================================================================
RCS file: /home/cvs/httpd-2.0/modules/http/http_protocol.c,v
retrieving revision 1.407
diff -u -r1.407 http_protocol.c
--- modules/http/http_protocol.c        1 Apr 2002 22:26:09 -0000       1.407
+++ modules/http/http_protocol.c        13 Apr 2002 03:20:07 -0000
@@ -111,6 +188,89 @@
  */
 #define METHOD_NUMBER_LAST  62
 
+AP_DECLARE(void) ap_get_mime_headers(request_rec *r)
+{
+    char* field;
+    char *value;
+    apr_size_t len;
+    int fields_read = 0;
+    apr_table_t *tmp_headers;
+
+    /* We'll use apr_table_overlap later to merge these into r->headers_in. */
+    tmp_headers = apr_table_make(r->pool, 50);
+
+    /*
+     * Read header lines until we get the empty separator line, a read error,
+     * the connection closes (EOF), reach the server limit, or we timeout.
+     */
+    while(1) {
+        apr_status_t rv;
+
+        field = NULL;
+        rv = ap_rgetline(&field, DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2,
+                         &len, r, 1);
+
+        /* ap_rgetline returns APR_ENOSPC if it fills up the buffer before
+         * finding the end-of-line.  This is only going to happen if it
+         * exceeds the configured limit for a field size.
+         * The cast is safe, limit_req_fieldsize cannot be negative
+         */
+        if (rv == APR_ENOSPC
+            || (rv == APR_SUCCESS 
+                && len > (apr_size_t)r->server->limit_req_fieldsize)) {
+            r->status = HTTP_BAD_REQUEST;
+            apr_table_setn(r->notes, "error-notes",
+                           apr_pstrcat(r->pool,
+                                       "Size of a request header field "
+                                       "exceeds server limit.<br />\n"
+                                       "<pre>\n",
+                                       ap_escape_html(r->pool, field),
+                                       "</pre>\n", NULL));
+            return;
+        }
+
+        if (rv != APR_SUCCESS) {
+            r->status = HTTP_BAD_REQUEST;
+            return;
+        }
+
+        /* Found a blank line, stop. */
+        if (len == 0) {
+            break;
+        }
+
+        if (r->server->limit_req_fields
+            && (++fields_read > r->server->limit_req_fields)) {
+            r->status = HTTP_BAD_REQUEST;
+            apr_table_setn(r->notes, "error-notes",
+                           "The number of request header fields exceeds "
+                           "this server's limit.");
+            return;
+        }
+
+        if (!(value = strchr(field, ':'))) {    /* Find the colon separator */
+            r->status = HTTP_BAD_REQUEST;       /* or abort the bad request */
+            apr_table_setn(r->notes, "error-notes",
+                           apr_pstrcat(r->pool,
+                                       "Request header field is missing "
+                                       "colon separator.<br />\n"
+                                       "<pre>\n",
+                                       ap_escape_html(r->pool, field),
+                                       "</pre>\n", NULL));
+            return;
+        }
+
+        *value = '\0';
+        ++value;
+        while (*value == ' ' || *value == '\t') {
+            ++value;            /* Skip to start of value   */
+        }
+
+        apr_table_addn(tmp_headers, field, value);
+    }
+
+    apr_table_overlap(r->headers_in, tmp_headers, APR_OVERLAP_TABLES_MERGE);
+}
 
 AP_DECLARE(int) ap_set_keepalive(request_rec *r)
 {
@@ -766,7 +950,8 @@
                 ctx->remaining = get_chunk_size(line);
 
                 if (!ctx->remaining) {
-                    /* Handle trailers by calling get_mime_headers again! */
+                    /* Handle trailers by calling ap_get_mime_headers again! */
+                    ap_get_mime_headers(f->r);
                     e = apr_bucket_eos_create(c->bucket_alloc);
                     APR_BRIGADE_INSERT_TAIL(b, e);
                     return APR_SUCCESS;
Index: server/protocol.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/protocol.c,v
retrieving revision 1.95
diff -u -r1.95 protocol.c
--- server/protocol.c   5 Apr 2002 20:54:59 -0000       1.95
+++ server/protocol.c   13 Apr 2002 03:20:12 -0000
@@ -716,90 +716,6 @@
     return 1;
 }
 
-static void get_mime_headers(request_rec *r)
-{
-    char* field;
-    char *value;
-    apr_size_t len;
-    int fields_read = 0;
-    apr_table_t *tmp_headers;
-
-    /* We'll use apr_table_overlap later to merge these into r->headers_in. */
-    tmp_headers = apr_table_make(r->pool, 50);
-
-    /*
-     * Read header lines until we get the empty separator line, a read error,
-     * the connection closes (EOF), reach the server limit, or we timeout.
-     */
-    while(1) {
-        apr_status_t rv;
-
-        field = NULL;
-        rv = ap_rgetline(&field, DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2,
-                         &len, r, 1);
-
-        /* ap_rgetline returns APR_ENOSPC if it fills up the buffer before
-         * finding the end-of-line.  This is only going to happen if it
-         * exceeds the configured limit for a field size.
-         * The cast is safe, limit_req_fieldsize cannot be negative
-         */
-        if (rv == APR_ENOSPC
-            || (rv == APR_SUCCESS 
-                && len > (apr_size_t)r->server->limit_req_fieldsize)) {
-            r->status = HTTP_BAD_REQUEST;
-            apr_table_setn(r->notes, "error-notes",
-                           apr_pstrcat(r->pool,
-                                       "Size of a request header field "
-                                       "exceeds server limit.<br />\n"
-                                       "<pre>\n",
-                                       ap_escape_html(r->pool, field),
-                                       "</pre>\n", NULL));
-            return;
-        }
-
-        if (rv != APR_SUCCESS) {
-            r->status = HTTP_BAD_REQUEST;
-            return;
-        }
-
-        /* Found a blank line, stop. */
-        if (len == 0) {
-            break;
-        }
-
-        if (r->server->limit_req_fields
-            && (++fields_read > r->server->limit_req_fields)) {
-            r->status = HTTP_BAD_REQUEST;
-            apr_table_setn(r->notes, "error-notes",
-                           "The number of request header fields exceeds "
-                           "this server's limit.");
-            return;
-        }
-
-        if (!(value = strchr(field, ':'))) {    /* Find the colon separator */
-            r->status = HTTP_BAD_REQUEST;       /* or abort the bad request */
-            apr_table_setn(r->notes, "error-notes",
-                           apr_pstrcat(r->pool,
-                                       "Request header field is missing "
-                                       "colon separator.<br />\n"
-                                       "<pre>\n",
-                                       ap_escape_html(r->pool, field),
-                                       "</pre>\n", NULL));
-            return;
-        }
-
-        *value = '\0';
-        ++value;
-        while (*value == ' ' || *value == '\t') {
-            ++value;            /* Skip to start of value   */
-        }
-
-        apr_table_addn(tmp_headers, field, value);
-    }
-
-    apr_table_overlap(r->headers_in, tmp_headers, APR_OVERLAP_TABLES_MERGE);
-}
-
 request_rec *ap_read_request(conn_rec *conn)
 {
     request_rec *r;
@@ -856,7 +772,7 @@
     }
 
     if (!r->assbackwards) {
-        get_mime_headers(r);
+        ap_get_mime_headers(r);
         if (r->status != HTTP_REQUEST_TIME_OUT) {
             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
                           "request failed: error reading the headers");

Reply via email to