diff options
author | Roy T. Fielding <fielding@apache.org> | 1997-07-19 20:17:41 +0000 |
---|---|---|
committer | Roy T. Fielding <fielding@apache.org> | 1997-07-19 20:17:41 +0000 |
commit | 450b8179a9c7d08329fa9553483f280f10a1183a (patch) | |
tree | 5d912e524055088ba3d5b2b7229b905c061a173c | |
parent | 16b77dd4c68bd5c94b39782794d82bbc2425d379 (diff) | |
download | httpd-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/CHANGES | 8 | ||||
-rw-r--r-- | APACHE_1_2_X/src/include/http_protocol.h | 1 | ||||
-rw-r--r-- | APACHE_1_2_X/src/main/http_core.c | 9 | ||||
-rw-r--r-- | APACHE_1_2_X/src/main/http_protocol.c | 72 | ||||
-rw-r--r-- | APACHE_1_2_X/src/main/http_request.c | 6 |
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; } |