You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Justin Erenkrantz <je...@apache.org> on 2002/04/13 05:29:22 UTC

[Take 2] [PATCH] Move 100-Continue into HTTP_IN

On Fri, Apr 12, 2002 at 05:34:27PM -0700, Roy T. Fielding wrote:
> We have to do more work than this.  The 100 has to be sent before 
> attempting
> to read the first chunk (if chunked) or only if C-L > 0 (if length).

This version of the patch should resolve this concern.  

Add 100-Continue logic to HTTP_IN

- Move status_lines higher so that ap_http_filter can use it.
- Don't read chunk size until after 100-Continue is sent.

Is this better?  -- justin

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
@@ -99,6 +99,83 @@
 #include <unistd.h>
 #endif
 
+/* New Apache routine to map status codes into array indicies
+ *  e.g.  100 -> 0,  101 -> 1,  200 -> 2 ...
+ * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
+ * and must be listed in order.
+ */
+
+#ifdef UTS21
+/* The second const triggers an assembler bug on UTS 2.1.
+ * Another workaround is to move some code out of this file into another,
+ *   but this is easier.  Dave Dykstra, 3/31/99
+ */
+static const char * status_lines[RESPONSE_CODES] =
+#else
+static const char * const status_lines[RESPONSE_CODES] =
+#endif
+{
+    "100 Continue",
+    "101 Switching Protocols",
+    "102 Processing",
+#define LEVEL_200  3
+    "200 OK",
+    "201 Created",
+    "202 Accepted",
+    "203 Non-Authoritative Information",
+    "204 No Content",
+    "205 Reset Content",
+    "206 Partial Content",
+    "207 Multi-Status",
+#define LEVEL_300 11
+    "300 Multiple Choices",
+    "301 Moved Permanently",
+    "302 Found",
+    "303 See Other",
+    "304 Not Modified",
+    "305 Use Proxy",
+    "306 unused",
+    "307 Temporary Redirect",
+#define LEVEL_400 19
+    "400 Bad Request",
+    "401 Authorization Required",
+    "402 Payment Required",
+    "403 Forbidden",
+    "404 Not Found",
+    "405 Method Not Allowed",
+    "406 Not Acceptable",
+    "407 Proxy Authentication Required",
+    "408 Request Time-out",
+    "409 Conflict",
+    "410 Gone",
+    "411 Length Required",
+    "412 Precondition Failed",
+    "413 Request Entity Too Large",
+    "414 Request-URI Too Large",
+    "415 Unsupported Media Type",
+    "416 Requested Range Not Satisfiable",
+    "417 Expectation Failed",
+    "418 unused",
+    "419 unused",
+    "420 unused",
+    "421 unused",
+    "422 Unprocessable Entity",
+    "423 Locked",
+    "424 Failed Dependency",
+#define LEVEL_500 44
+    "500 Internal Server Error",
+    "501 Method Not Implemented",
+    "502 Bad Gateway",
+    "503 Service Temporarily Unavailable",
+    "504 Gateway Time-out",
+    "505 HTTP Version Not Supported",
+    "506 Variant Also Negotiates",
+    "507 Insufficient Storage",
+    "508 unused",
+    "509 unused",
+    "510 Not Extended"
+};
+
 
 /* The index of the first bit field that is used to index into a limit
  * bitmask. M_INVALID + 1 to METHOD_NUMBER_LAST.
@@ -703,13 +863,7 @@
 
         if (tenc) {
             if (!strcasecmp(tenc, "chunked")) {
-                char line[30];
-
-                if ((rv = ap_getline(line, sizeof(line), f->r, 0)) < 0) {
-                    return rv;
-                }
                 ctx->state = BODY_CHUNK;
-                ctx->remaining = get_chunk_size(line);
             }
         }
         else if (lenp) {
@@ -736,6 +890,36 @@
                 return APR_EGENERAL;
             }
         }
+
+        /* Since we're about to read data, send 100-Continue if needed.
+         * Only valid on chunked and C-L bodies where the C-L is > 0. */
+        if ((ctx->state == BODY_CHUNK || 
+            (ctx->state == BODY_LENGTH && ctx->remaining > 0)) &&
+            f->r->expecting_100 && f->r->proto_num >= HTTP_VERSION(1,1)) {
+            char *tmp;
+            apr_bucket_brigade *bb;
+
+            tmp = apr_pstrcat(f->r->pool, AP_SERVER_PROTOCOL, " ",
+                              status_lines[0], CRLF CRLF, NULL);
+            bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+            e = apr_bucket_pool_create(tmp, strlen(tmp), f->r->pool,
+                                       f->c->bucket_alloc);
+            APR_BRIGADE_INSERT_HEAD(bb, e);
+            e = apr_bucket_flush_create(f->c->bucket_alloc);
+            APR_BRIGADE_INSERT_TAIL(bb, e);
+
+            ap_pass_brigade(f->c->output_filters, bb);
+        }
+
+        /* We can't read the chunk until after sending 100 if required. */
+        if (ctx->state == BODY_CHUNK) {
+            char line[30];
+
+            if ((rv = ap_getline(line, sizeof(line), f->r, 0)) < 0) {
+                return rv;
+            }
+            ctx->remaining = get_chunk_size(line);
+        } 
     }
 
     if (!ctx->remaining) {
@@ -820,83 +1005,6 @@
     return APR_SUCCESS;
 }
 
-/* New Apache routine to map status codes into array indicies
- *  e.g.  100 -> 0,  101 -> 1,  200 -> 2 ...
- * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
- * and must be listed in order.
- */
-
-#ifdef UTS21
-/* The second const triggers an assembler bug on UTS 2.1.
- * Another workaround is to move some code out of this file into another,
- *   but this is easier.  Dave Dykstra, 3/31/99
- */
-static const char * status_lines[RESPONSE_CODES] =
-#else
-static const char * const status_lines[RESPONSE_CODES] =
-#endif
-{
-    "100 Continue",
-    "101 Switching Protocols",
-    "102 Processing",
-#define LEVEL_200  3
-    "200 OK",
-    "201 Created",
-    "202 Accepted",
-    "203 Non-Authoritative Information",
-    "204 No Content",
-    "205 Reset Content",
-    "206 Partial Content",
-    "207 Multi-Status",
-#define LEVEL_300 11
-    "300 Multiple Choices",
-    "301 Moved Permanently",
-    "302 Found",
-    "303 See Other",
-    "304 Not Modified",
-    "305 Use Proxy",
-    "306 unused",
-    "307 Temporary Redirect",
-#define LEVEL_400 19
-    "400 Bad Request",
-    "401 Authorization Required",
-    "402 Payment Required",
-    "403 Forbidden",
-    "404 Not Found",
-    "405 Method Not Allowed",
-    "406 Not Acceptable",
-    "407 Proxy Authentication Required",
-    "408 Request Time-out",
-    "409 Conflict",
-    "410 Gone",
-    "411 Length Required",
-    "412 Precondition Failed",
-    "413 Request Entity Too Large",
-    "414 Request-URI Too Large",
-    "415 Unsupported Media Type",
-    "416 Requested Range Not Satisfiable",
-    "417 Expectation Failed",
-    "418 unused",
-    "419 unused",
-    "420 unused",
-    "421 unused",
-    "422 Unprocessable Entity",
-    "423 Locked",
-    "424 Failed Dependency",
-#define LEVEL_500 44
-    "500 Internal Server Error",
-    "501 Method Not Implemented",
-    "502 Bad Gateway",
-    "503 Service Temporarily Unavailable",
-    "504 Gateway Time-out",
-    "505 HTTP Version Not Supported",
-    "506 Variant Also Negotiates",
-    "507 Insufficient Storage",
-    "508 unused",
-    "509 unused",
-    "510 Not Extended"
-};
-
 /* The index is found by its offset from the x00 code of each level.
  * Although this is fast, it will need to be replaced if some nutcase
  * decides to define a high-numbered code before the lower numbers.
@@ -1576,24 +1684,6 @@
 
     if (r->read_length || (!r->read_chunked && (r->remaining <= 0))) {
         return 0;
-    }
-
-    if (r->expecting_100 && r->proto_num >= HTTP_VERSION(1,1)) {
-        conn_rec *c = r->connection;
-        char *tmp;
-        apr_bucket *e;
-        apr_bucket_brigade *bb;
-
-        /* sending 100 Continue interim response */
-        tmp = apr_pstrcat(r->pool, AP_SERVER_PROTOCOL, " ", status_lines[0],
-                          CRLF CRLF, NULL);
-        bb = apr_brigade_create(r->pool, c->bucket_alloc);
-        e = apr_bucket_pool_create(tmp, strlen(tmp), r->pool, c->bucket_alloc);
-        APR_BRIGADE_INSERT_HEAD(bb, e);
-        e = apr_bucket_flush_create(c->bucket_alloc);
-        APR_BRIGADE_INSERT_TAIL(bb, e);
-
-        ap_pass_brigade(r->connection->output_filters, bb);
     }
 
     return 1;

Re: [Take 2] [PATCH] Move 100-Continue into HTTP_IN

Posted by Justin Erenkrantz <je...@apache.org>.
On Fri, Apr 12, 2002 at 08:32:34PM -0700, Ryan Bloom wrote:
> Again, there is a whole case that you are missing.  What are you going
> to do about modules that want to discard the request body?

The discard function is still there - that should still work for
now.  As Greg pointed out, we can modify the filter to throw away
the body (add another input mode?).  Or, we can clean up
discard_body to work with buckets/brigades correctly.

I'm trying to handle one thing at a time.  I'm not terribly
concerned about the discard case yet.  -- justin

RE: [Take 2] [PATCH] Move 100-Continue into HTTP_IN

Posted by Ryan Bloom <rb...@covalent.net>.
Again, there is a whole case that you are missing.  What are you going
to do about modules that want to discard the request body?

Ryan

----------------------------------------------
Ryan Bloom                  rbb@covalent.net
645 Howard St.              rbb@apache.org
San Francisco, CA