httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dean Gaudet <dgau...@arctic.org>
Subject [PATCH] rfc2068 fixes
Date Tue, 11 Feb 1997 07:22:59 GMT
I've been reading rfc2068.  A few bug/compliance fixes. 

#10.2.5 204 No Content -- MUST NOT include a message-body, so we can
keepalive just like we do on 304s.  (Ok, so this is a feature :)

In some cases it is possible that r->allowed is 0, and then make_allow()
returns bogosity.  Correct it to return NULL.  This affects OPTIONS
requests and 405 Method Not Allowed responses.  You can cause this,
for example, by issuing a request like:

    telnet foobar 80
    GET http://blahblah/ HTTP/1.1
    Host: blahblah

Allow must contain at least one method (#14.7), so we have to exclude the
header entirely if r->allowed is 0.  Responses to OPTIONS do not require
an Allow header (#9.2).  Method Not Allowed responses MUST have an Allow
header (#10.4.6), so convert a 405 to a 500 if for some reason no methods
are allowed.

#9.8 TRACE -- "The final recipient of the request SHOULD reflect the
message received back to the client as the entity-body of a 200 (OK) 
response".  On a request that includes the absolute-uri Apache does not
quite return the message received, it will return the absolute-path but
not the host.  i.e. 

    telnet foobar 80
    GET http://foobar/ HTTP/1.1
    Host: foobar

Returns "GET /foobar/ HTTP/1.1".  Correct send_http_trace() to use
r->the_request instead of constructing the request from its parsed
components.

Dean

*** http_protocol.c.orig	Mon Feb 10 23:03:40 1997
--- http_protocol.c	Mon Feb 10 23:05:02 1997
***************
*** 265,271 ****
      else if (r->server->keep_alive && (!r->server->keep_alive_max ||
  	(r->server->keep_alive_max > r->connection->keepalives)) &&
  	(r->server->keep_alive_timeout > 0) &&
! 	(r->status == USE_LOCAL_COPY || r->header_only || length || tenc ||
  	 ((r->proto_num >= 1001) && (r->chunked = 1))) &&
  	(!find_token(r->pool, conn, "close")) &&
  	((ka_sent = find_token(r->pool, conn, "keep-alive")) ||
--- 265,272 ----
      else if (r->server->keep_alive && (!r->server->keep_alive_max ||
  	(r->server->keep_alive_max > r->connection->keepalives)) &&
  	(r->server->keep_alive_timeout > 0) &&
! 	(r->status == HTTP_NOT_MODIFIED || r->status == HTTP_NO_CONTENT
! 	 || r->header_only || length || tenc ||
  	 ((r->proto_num >= 1001) && (r->chunked = 1))) &&
  	(!find_token(r->pool, conn, "close")) &&
  	((ka_sent = find_token(r->pool, conn, "keep-alive")) ||
***************
*** 991,1000 ****
  #endif
  }
  
! char *make_allow(request_rec *r)
  {
      int allowed = r->allowed;
  
      return 2 + pstrcat(r->pool, (allowed & (1 << M_GET)) ? ", GET, HEAD" :
"",
  		       (allowed & (1 << M_POST)) ? ", POST" : "",
  		       (allowed & (1 << M_PUT)) ? ", PUT" : "",
--- 992,1005 ----
  #endif
  }
  
! static char *make_allow(request_rec *r)
  {
      int allowed = r->allowed;
  
+     if( allowed == 0 ) {
+ 	return( NULL );
+     }
+ 
      return 2 + pstrcat(r->pool, (allowed & (1 << M_GET)) ? ", GET, HEAD" :
"",
  		       (allowed & (1 << M_POST)) ? ", POST" : "",
  		       (allowed & (1 << M_PUT)) ? ", PUT" : "",
***************
*** 1021,1027 ****
      
      /* Now we recreate the request, and echo it back */
  
!     rvputs(r, r->method, " ", r->uri, " ", r->protocol, "\015\012", NULL);
  
      for (i = 0; i < hdrs_arr->nelts; ++i) {
        if (!hdrs[i].key) continue;
--- 1026,1032 ----
      
      /* Now we recreate the request, and echo it back */
  
!     rvputs( r, r->the_request, "\015\012", NULL );
  
      for (i = 0; i < hdrs_arr->nelts; ++i) {
        if (!hdrs[i].key) continue;
***************
*** 1036,1041 ****
--- 1041,1047 ----
  {
      BUFF *fd = r->connection->client;
      const long int zero=0L;
+     char *allow;
  
      if (r->assbackwards) return DECLINED;
  
***************
*** 1043,1049 ****
  
      basic_http_header(r);
      bputs("Connection: close\015\012", fd);
!     bvputs(fd, "Allow: ", make_allow(r), "\015\012", NULL);
      bputs("\015\012", fd);
  
      bsetopt(fd, BO_BYTECT, &zero);
--- 1049,1063 ----
  
      basic_http_header(r);
      bputs("Connection: close\015\012", fd);
!     /* rfc2068 #9.2 A 200 response SHOULD include any header fields
!      * which indicate optional features implemented by the server and
!      * applicable to that resource (e.g. Allow).   --- so we're free to
!      * not include the allow if for some reason r->allowed == 0.
!      */
!     allow = make_allow(r);
!     if( allow ) {
! 	bvputs(fd, "Allow: ", make_allow(r), "\015\012", NULL);
!     }
      bputs("\015\012", fd);
  
      bsetopt(fd, BO_BYTECT, &zero);
***************
*** 1540,1545 ****
--- 1554,1567 ----
  	table *hdrs_arr = r->headers_out;
  	table_entry *hdrs = (table_entry *)hdrs_arr->elts;
    
+ 	if( status == HTTP_METHOD_NOT_ALLOWED && r->allowed == 0 ) {
+ 	    /* there's really nothing else we can do since rfc2068
+ 	     * #10.4.6 says we MUST send an Allow: header, but we don't
+ 	     * have any methods to allow, and Allow has to have at least
+ 	     * one method to be valid.
+ 	     */
+ 	    status = r->status = HTTP_INTERNAL_SERVER_ERROR;
+ 	}
          basic_http_header (r);
  	
  	/* For non-error statuses (2xx and 3xx), send out all the normal
***************
*** 1579,1586 ****
  	 */
  	bputs("Connection: close\015\012", c->client);
  
! 	if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED))
  	    bvputs(c->client, "Allow: ", make_allow(r), "\015\012", NULL);
  	
  	for (i = 0; i < err_hdrs_arr->nelts; ++i) {
  	    if (!err_hdrs[i].key) continue;
--- 1601,1610 ----
  	 */
  	bputs("Connection: close\015\012", c->client);
  
! 	if( r->allowed && ( status == HTTP_METHOD_NOT_ALLOWED
! 			    || status == HTTP_NOT_IMPLEMENTED ) ) {
  	    bvputs(c->client, "Allow: ", make_allow(r), "\015\012", NULL);
+ 	}
  	
  	for (i = 0; i < err_hdrs_arr->nelts; ++i) {
  	    if (!err_hdrs[i].key) continue;


Mime
View raw message