You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by Roy Fielding <fi...@hyperreal.org> on 1997/07/19 22:27:57 UTC
cvs commit: apache/src CHANGES http_core.c http_protocol.c http_protocol.h http_request.c http_config.h
fielding 97/07/19 13:27:56
Modified: src CHANGES http_core.c http_protocol.c
http_protocol.h http_request.c http_config.h
Log:
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 the API to make this easier for modules.
PR: 378
Reviewed by: Dean Gaudet
Revision Changes Path
1.352 +8 -0 apache/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /export/home/cvs/apache/src/CHANGES,v
retrieving revision 1.351
retrieving revision 1.352
diff -C3 -r1.351 -r1.352
*** CHANGES 1997/07/19 19:42:17 1.351
--- CHANGES 1997/07/19 20:27:50 1.352
***************
*** 177,182 ****
--- 177,190 ----
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]
1.98 +7 -2 apache/src/http_core.c
Index: http_core.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_core.c,v
retrieving revision 1.97
retrieving revision 1.98
diff -C3 -r1.97 -r1.98
*** http_core.c 1997/07/17 22:27:29 1.97
--- http_core.c 1997/07/19 20:27:51 1.98
***************
*** 1368,1376 ****
(core_dir_config *)get_module_config(r->per_dir_config, &core_module);
int rangestatus, errstatus;
FILE *f;
!
r->allowed |= (1 << M_GET);
- r->allowed |= (1 << M_TRACE);
r->allowed |= (1 << M_OPTIONS);
if (r->method_number == M_INVALID) {
--- 1368,1381 ----
(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_OPTIONS);
if (r->method_number == M_INVALID) {
1.143 +53 -19 apache/src/http_protocol.c
Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.c,v
retrieving revision 1.142
retrieving revision 1.143
diff -C3 -r1.142 -r1.143
*** http_protocol.c 1997/07/19 10:20:50 1.142
--- http_protocol.c 1997/07/19 20:27:52 1.143
***************
*** 1094,1127 ****
bputs("\015\012", client); /* Send the terminating empty line */
}
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);
!
}
int send_http_trace (request_rec *r)
{
/* Get the original request */
while (r->prev) r = r->prev;
hard_timeout("send TRACE", r);
r->content_type = "message/http";
--- 1094,1124 ----
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)
{
! 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";
***************
*** 1533,1538 ****
--- 1530,1572 ----
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;
+ */
+ API_EXPORT(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.
+ */
API_EXPORT(long) send_fd(FILE *f, request_rec *r) {
return send_fd_length(f, r, -1);
}
1.24 +1 -0 apache/src/http_protocol.h
Index: http_protocol.h
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -C3 -r1.23 -r1.24
*** http_protocol.h 1997/07/15 21:39:56 1.23
--- http_protocol.h 1997/07/19 20:27:52 1.24
***************
*** 134,139 ****
--- 134,140 ----
API_EXPORT(int) setup_client_block (request_rec *r, int read_policy);
API_EXPORT(int) should_client_block (request_rec *r);
API_EXPORT(long) get_client_block (request_rec *r, char *buffer, int bufsiz);
+ API_EXPORT(int) discard_request_body (request_rec *r);
/* Sending a byterange */
1.65 +4 -2 apache/src/http_request.c
Index: http_request.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_request.c,v
retrieving revision 1.64
retrieving revision 1.65
diff -C3 -r1.64 -r1.65
*** http_request.c 1997/07/19 08:03:53 1.64
--- http_request.c 1997/07/19 20:27:53 1.65
***************
*** 930,937 ****
* we handle it specially.
*/
if (r->method_number == M_TRACE) {
! send_http_trace(r);
! finalize_request_protocol(r);
return;
}
--- 930,939 ----
* we handle it specially.
*/
if (r->method_number == M_TRACE) {
! if ((access_status = send_http_trace(r)))
! die(access_status, r);
! else
! finalize_request_protocol(r);
return;
}
1.38 +1 -1 apache/src/http_config.h
Index: http_config.h
===================================================================
RCS file: /export/home/cvs/apache/src/http_config.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -C3 -r1.37 -r1.38
*** http_config.h 1997/07/17 23:30:07 1.37
--- http_config.h 1997/07/19 20:27:53 1.38
***************
*** 238,244 ****
* handle it back-compatibly, or at least signal an error).
*/
! #define MODULE_MAGIC_NUMBER 19970717
#define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL
/* Generic accessors for other modules to get at their own module-specific
--- 238,244 ----
* handle it back-compatibly, or at least signal an error).
*/
! #define MODULE_MAGIC_NUMBER 19970719
#define STANDARD_MODULE_STUFF MODULE_MAGIC_NUMBER, -1, __FILE__, NULL
/* Generic accessors for other modules to get at their own module-specific