httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jerenkra...@apache.org
Subject cvs commit: httpd-2.0/modules/http http_protocol.c
Date Fri, 31 May 2002 07:19:05 GMT
jerenkrantz    2002/05/31 00:19:05

  Modified:    modules/http http_protocol.c
  Log:
  Fix the case where if there is no ErrorDocument specified for an error,
  the error would be sent to the client *twice* because both the filter
  and the core would trigger error responses.
  
  The problem is that the filters have already handled some errors (say 413)
  and due to the ap_get_client_block API, the error was morphed into 400.
  Therefore, ap_discard_request_body must use brigades directly rather than
  the ap_get_client_block API so that any potential errors are not dropped.
  
  The special value AP_FILTER_ERROR indicates that the lower level has
  already dealt with this problem (ap_die() will realize this).  Otherwise,
  we'll error with HTTP_BAD_REQUEST and ap_die() will take it from there.
  
  This also prevents needless memory copies when we are just going to
  discard it anyway.
  
  Thanks to Cliff Woolley who found this wacky problem.
  
  Revision  Changes    Path
  1.431     +47 -24    httpd-2.0/modules/http/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/http/http_protocol.c,v
  retrieving revision 1.430
  retrieving revision 1.431
  diff -u -r1.430 -r1.431
  --- http_protocol.c	31 May 2002 00:23:34 -0000	1.430
  +++ http_protocol.c	31 May 2002 07:19:04 -0000	1.431
  @@ -1851,7 +1851,8 @@
    */
   AP_DECLARE(int) ap_discard_request_body(request_rec *r)
   {
  -    int rv;
  +    apr_bucket_brigade *bb;
  +    int rv, seen_eos;
   
       /* Sometimes we'll get in a state where the input handling has
        * detected an error where we want to drop the connection, so if
  @@ -1864,33 +1865,55 @@
           return OK;
       }
   
  -    if (r->read_length == 0) {  /* if not read already */
  -        if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) {
  -            return rv;
  +    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
  +    seen_eos = 0;
  +    do {
  +        apr_bucket *bucket;
  +
  +        rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
  +                            APR_BLOCK_READ, HUGE_STRING_LEN);
  +
  +        if (rv != APR_SUCCESS) {
  +            /* FIXME: If we ever have a mapping from filters (apr_status_t)
  +             * to HTTP error codes, this would be a good place for them.
  +             * 
  +             * If we received the special case AP_FILTER_ERROR, it means
  +             * that the filters have already handled this error.
  +             * Otherwise, we should assume we have a bad request.
  +             */
  +            if (rv == AP_FILTER_ERROR) {
  +                return rv;
  +            }
  +            else {
  +                return HTTP_BAD_REQUEST;
  +            }
           }
  -    }
  -
  -    /* In order to avoid sending 100 Continue when we already know the
  -     * final response status, and yet not kill the connection if there is
  -     * no request body to be read, we need to duplicate the test from
  -     * ap_should_client_block() here negated rather than call it directly.
  -     */
  -    if ((r->read_length == 0) && (r->read_chunked || (r->remaining >
0))) {
  -        char dumpbuf[HUGE_STRING_LEN];
   
  -        if (r->expecting_100) {
  -            r->connection->keepalive = -1;
  -            return OK;
  +        APR_BRIGADE_FOREACH(bucket, bb) {
  +            const char *data;
  +            apr_size_t len;
  +
  +            if (APR_BUCKET_IS_EOS(bucket)) {
  +                seen_eos = 1;
  +                break;
  +            }
  +
  +            /* These are metadata buckets. */
  +            if (bucket->length == 0) {
  +                continue;
  +            }
  +
  +            /* We MUST read because in case we have an unknown-length
  +             * bucket or one that morphs, we want to exhaust it.
  +             */
  +            rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
  +            if (rv != APR_SUCCESS) {
  +                return HTTP_BAD_REQUEST;
  +            }
           }
  +        apr_brigade_cleanup(bb);
  +    } while (!seen_eos);
   
  -        while ((rv = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0) {
  -            continue;
  -        }
  -
  -        if (rv < 0) {
  -            return HTTP_BAD_REQUEST;
  -        }
  -    }
       return OK;
   }
   
  
  
  

Mime
View raw message