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");