Commit f8fd9511 authored by Jim Jagielski's avatar Jim Jagielski
Browse files

Better handle the case where ProxyBadHeader StartBody is

in effect and we think we've started reading in the
response body. Take advantage of the fact that the
line read is still in buffer (and document that)
to allow us to add to the bb.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@151722 13f79535-47bb-0310-9956-ffa450edef68
parent 17c76b3e
Loading
Loading
Loading
Loading
+28 −9
Changes for modules/proxy/mod_proxy_http.c: 28 added lines, 9 removed lines.
Original line number Diff line number Diff line
@@ -873,7 +873,17 @@ static void process_proxy_header(request_rec* r, proxy_server_conf* c,
    return ;
}

static void ap_proxy_read_headers(request_rec *r, request_rec *rr, char *buffer, int size, conn_rec *c)
/*
 * Note: pread_len is the length of the response that we've  mistakenly
 * read (assuming that we don't consider that an  error via
 * ProxyBadHeader StartBody). This depends on buffer actually being
 * local storage to the calling code in order for pread_len to make
 * any sense at all, since we depend on buffer still containing
 * what was read by ap_getline() upon return.
 */
static void ap_proxy_read_headers(request_rec *r, request_rec *rr,
                                  char *buffer, int size,
                                  conn_rec *c, int *pread_len)
{
    int len;
    char *value, *end;
@@ -885,6 +895,7 @@ static void ap_proxy_read_headers(request_rec *r, request_rec *rr, char *buffer,
    psc = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);

    r->headers_out = apr_table_make(r->pool, 20);
    *pread_len = 0;

    /*
     * Read header lines until we get the empty separator line, a read error,
@@ -913,16 +924,14 @@ static void ap_proxy_read_headers(request_rec *r, request_rec *rr, char *buffer,
                else if (psc->badopt == bad_body) {
                    /* if we've already started loading headers_out, then
                     * return what we've accumulated so far, in the hopes
                     * that they are useful. Otherwise, we completely bail.
                     */
                    /* FIXME: We've already scarfed the supposed 1st line of
                     * the body, so the actual content may end up being bogus
                     * as well. If the content is HTML, we may be lucky.
                     * that they are useful; also note that we likely pre-read
                     * the first line of the response.
                     */
                    if (saw_headers) {
                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,
                         "proxy: Starting body due to bogus non-header in headers "
                         "returned by %s (%s)", r->uri, r->method);
                        *pread_len = len;
                        return ;
                    } else {
                         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,
@@ -994,6 +1003,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
    int len, backasswards;
    int interim_response; /* non-zero whilst interim 1xx responses
                           * are being read. */
    int pread_len = 0;
    apr_table_t *save_table;

    bb = apr_brigade_create(p, c->bucket_alloc);
@@ -1073,7 +1083,8 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                         "Set-Cookie", NULL);

        /* shove the headers direct into r->headers_out */
            ap_proxy_read_headers(r, rp, buffer, sizeof(buffer), origin);
            ap_proxy_read_headers(r, rp, buffer, sizeof(buffer), origin,
                                  &pread_len);

            if (r->headers_out == NULL) {
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
@@ -1179,9 +1190,15 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
        }

        r->sent_bodyct = 1;
        /* Is it an HTTP/0.9 response? If so, send the extra data */
        /*
         * Is it an HTTP/0.9 response or did we maybe preread the 1st line of
         * the response? If so, load the extra data. These are 2 mutually
         * exclusive possibilities, that just happen to require very
         * similar behavior.
         */
        if (backasswards || pread_len) {
            apr_ssize_t cntr = (apr_ssize_t)pread_len;
            if (backasswards) {
            apr_ssize_t cntr = len;
                /*@@@FIXME:
                 * At this point in response processing of a 0.9 response,
                 * we don't know yet whether data is binary or not.
@@ -1192,6 +1209,8 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                 * the best guess IMHO is to always treat the buffer as "text/x":
                 */
                ap_xlate_proto_to_ascii(buffer, len);
                cntr = (apr_ssize_t)len;
            }
            e = apr_bucket_heap_create(buffer, cntr, NULL, c->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(bb, e);
        }