summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoy T. Fielding <fielding@apache.org>1997-07-19 20:17:41 +0000
committerRoy T. Fielding <fielding@apache.org>1997-07-19 20:17:41 +0000
commit450b8179a9c7d08329fa9553483f280f10a1183a (patch)
tree5d912e524055088ba3d5b2b7229b905c061a173c
parent16b77dd4c68bd5c94b39782794d82bbc2425d379 (diff)
downloadhttpd-450b8179a9c7d08329fa9553483f280f10a1183a.tar.gz
In HTTP/1.1, whether or not a request message contains a body
is independent of the request method and based solely on the presence of a Content-Length or Transfer-Encoding. Therefore, our default handlers need to be prepared to read a body even if they don't know what to do with it; otherwise, the body would be mistaken for the next request on a persistent connection. discard_request_body() has been added to take care of that. PR: 378 Reviewed by: Dean Gaudet git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/1.3@78677 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--APACHE_1_2_X/src/CHANGES8
-rw-r--r--APACHE_1_2_X/src/include/http_protocol.h1
-rw-r--r--APACHE_1_2_X/src/main/http_core.c9
-rw-r--r--APACHE_1_2_X/src/main/http_protocol.c72
-rw-r--r--APACHE_1_2_X/src/main/http_request.c6
5 files changed, 73 insertions, 23 deletions
diff --git a/APACHE_1_2_X/src/CHANGES b/APACHE_1_2_X/src/CHANGES
index 999452f5d7..f9f4ba6280 100644
--- a/APACHE_1_2_X/src/CHANGES
+++ b/APACHE_1_2_X/src/CHANGES
@@ -1,5 +1,13 @@
Changes with Apache 1.2.2
+ *) API: In HTTP/1.1, whether or not a request message contains a body
+ is independent of the request method and based solely on the presence
+ of a Content-Length or Transfer-Encoding. Therefore, our default
+ handlers need to be prepared to read a body even if they don't know
+ what to do with it; otherwise, the body would be mistaken for the
+ next request on a persistent connection. discard_request_body()
+ has been added to take care of that. [Roy Fielding] PR#378
+
*) API: Symbol APACHE_RELEASE provides a numeric form of the Apache
release version number, such that it always increases along the
same lines as our source code branching. [Roy Fielding]
diff --git a/APACHE_1_2_X/src/include/http_protocol.h b/APACHE_1_2_X/src/include/http_protocol.h
index 85687b48a3..db608c253e 100644
--- a/APACHE_1_2_X/src/include/http_protocol.h
+++ b/APACHE_1_2_X/src/include/http_protocol.h
@@ -134,6 +134,7 @@ int index_of_response (int status);
int setup_client_block (request_rec *r, int read_policy);
int should_client_block (request_rec *r);
long get_client_block (request_rec *r, char *buffer, int bufsiz);
+int discard_request_body (request_rec *r);
/* Sending a byterange */
diff --git a/APACHE_1_2_X/src/main/http_core.c b/APACHE_1_2_X/src/main/http_core.c
index 39a6e6bc8f..6a9edf12c9 100644
--- a/APACHE_1_2_X/src/main/http_core.c
+++ b/APACHE_1_2_X/src/main/http_core.c
@@ -1324,9 +1324,14 @@ int default_handler (request_rec *r)
(core_dir_config *)get_module_config(r->per_dir_config, &core_module);
int rangestatus, errstatus;
FILE *f;
-
+
+ /* This handler has no use for a request body (yet), but we still
+ * need to read and discard it if the client sent one.
+ */
+ if ((errstatus = discard_request_body(r)) != OK)
+ return errstatus;
+
r->allowed |= (1 << M_GET);
- r->allowed |= (1 << M_TRACE);
r->allowed |= (1 << M_OPTIONS);
if (r->method_number == M_INVALID) {
diff --git a/APACHE_1_2_X/src/main/http_protocol.c b/APACHE_1_2_X/src/main/http_protocol.c
index ac143b0345..822ad68c6c 100644
--- a/APACHE_1_2_X/src/main/http_protocol.c
+++ b/APACHE_1_2_X/src/main/http_protocol.c
@@ -1087,34 +1087,31 @@ static void terminate_header (BUFF *client)
bputs("\015\012", client); /* Send the terminating empty line */
}
+/* Build the Allow field-value from the request handler method mask.
+ * Note that we always allow TRACE, since it is handled below.
+ */
static char *make_allow(request_rec *r)
{
- int allowed = r->allowed;
-
- if( allowed == 0 ) {
- /* RFC2068 #14.7, Allow must contain at least one method. So rather
- * than deal with the possibility of trying not to emit an Allow:
- * header, i.e. #10.4.6 says 405 Method Not Allowed MUST include
- * an Allow header, we'll just say TRACE is valid.
- */
- return( "TRACE" );
- }
-
- return 2 + pstrcat(r->pool, (allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
- (allowed & (1 << M_POST)) ? ", POST" : "",
- (allowed & (1 << M_PUT)) ? ", PUT" : "",
- (allowed & (1 << M_DELETE)) ? ", DELETE" : "",
- (allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
- (allowed & (1 << M_TRACE)) ? ", TRACE" : "",
- NULL);
-
+ return 2 + pstrcat(r->pool,
+ (r->allowed & (1 << M_GET)) ? ", GET, HEAD" : "",
+ (r->allowed & (1 << M_POST)) ? ", POST" : "",
+ (r->allowed & (1 << M_PUT)) ? ", PUT" : "",
+ (r->allowed & (1 << M_DELETE)) ? ", DELETE" : "",
+ (r->allowed & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
+ ", TRACE",
+ NULL);
}
int send_http_trace (request_rec *r)
{
+ int rv;
+
/* Get the original request */
while (r->prev) r = r->prev;
+ if ((rv = setup_client_block(r, REQUEST_NO_BODY)))
+ return rv;
+
hard_timeout("send TRACE", r);
r->content_type = "message/http";
@@ -1514,6 +1511,43 @@ long get_client_block (request_rec *r, char *buffer, int bufsiz)
return (chunk_start + len_read);
}
+/* In HTTP/1.1, any method can have a body. However, most GET handlers
+ * wouldn't know what to do with a request body if they received one.
+ * This helper routine tests for and reads any message body in the request,
+ * simply discarding whatever it receives. We need to do this because
+ * failing to read the request body would cause it to be interpreted
+ * as the next request on a persistent connection.
+ *
+ * Since we return an error status if the request is malformed, this
+ * routine should be called at the beginning of a no-body handler, e.g.,
+ *
+ * if ((retval = discard_request_body(r)) != OK)
+ * return retval;
+ */
+int discard_request_body(request_rec *r)
+{
+ int rv;
+
+ if ((rv = setup_client_block(r, REQUEST_CHUNKED_PASS)))
+ return rv;
+
+ if (should_client_block(r)) {
+ char dumpbuf[HUGE_STRING_LEN];
+
+ hard_timeout("reading request body", r);
+ while ((rv = get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
+ continue;
+ kill_timeout(r);
+
+ if (rv < 0)
+ return HTTP_BAD_REQUEST;
+ }
+ return OK;
+}
+
+/*
+ * Send the body of a response to the client.
+ */
long send_fd(FILE *f, request_rec *r) { return send_fd_length(f, r, -1); }
long send_fd_length(FILE *f, request_rec *r, long length)
diff --git a/APACHE_1_2_X/src/main/http_request.c b/APACHE_1_2_X/src/main/http_request.c
index c2d4884280..047a6c36ff 100644
--- a/APACHE_1_2_X/src/main/http_request.c
+++ b/APACHE_1_2_X/src/main/http_request.c
@@ -910,8 +910,10 @@ void process_request_internal (request_rec *r)
* we handle it specially.
*/
if (r->method_number == M_TRACE) {
- send_http_trace(r);
- finalize_request_protocol(r);
+ if ((access_status = send_http_trace(r)))
+ die(access_status, r);
+ else
+ finalize_request_protocol(r);
return;
}