Commit 999a6a3e authored by Graham Leggett's avatar Graham Leggett
Browse files

Pull in the Connection handling part of the v1.3 patch for HTTP/1.1.

Some preliminary HTTP/1.1 work
Some comments and fixes
PR:
Obtained from:
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88518 13f79535-47bb-0310-9956-ffa450edef68
parent 995b3eb1
Loading
Loading
Loading
Loading
+61 −23
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_p
    return OK;
}
 
static const char *proxy_location_reverse_map(request_rec *r, const char *url)
static const char *ap_proxy_location_reverse_map(request_rec *r, const char *url)
{
    void *sconf;
    proxy_server_conf *conf;
@@ -127,6 +127,9 @@ static const char *proxy_location_reverse_map(request_rec *r, const char *url)
    int i, l1, l2;
    char *u;

    /* XXX FIXME: Make sure this handled the ambiguous case of the :80
     * after the hostname */

    sconf = r->server->module_config;
    conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
    l1 = strlen(url);
@@ -142,7 +145,7 @@ static const char *proxy_location_reverse_map(request_rec *r, const char *url)
}

/* Clear all connection-based headers from the incoming headers table */
static void clear_connection(apr_pool_t *p, apr_table_t *headers)
static void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers)
{
    const char *name;
    char *next = apr_pstrdup(p, apr_table_get(headers, "Connection"));
@@ -185,6 +188,7 @@ int ap_proxy_http_handler(request_rec *r, char *url,
    apr_array_header_t *reqhdrs_arr;
    apr_table_t *resp_hdrs = NULL;
    apr_table_entry_t *reqhdrs;
    const char *table_buf;
    struct sockaddr_in server;
    struct in_addr destaddr;
    char buffer[HUGE_STRING_LEN];
@@ -285,14 +289,19 @@ int ap_proxy_http_handler(request_rec *r, char *url,
        /* the peer reset the connection already; ap_new_connection() 
         * closed the socket */
        /* XXX somebody that knows what they're doing add an error path */
	/* XXX how's this? */
	return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(r->pool,
			     "Connection reset by peer: ",
			     desthost, NULL));
    }

    ap_add_output_filter("CORE", NULL, NULL, origin);

    clear_connection(r->pool, r->headers_in);	/* Strip connection-based headers */
    /* strip connection listed hop-by-hop headers from the request */
    ap_proxy_clear_connection(r->pool, r->headers_in);

    buf = apr_pstrcat(r->pool, r->method, " ", proxyhost ? url : urlptr,
                      " HTTP/1.0" CRLF, NULL);
                      " HTTP/1.1" CRLF, NULL);
    e = apr_bucket_pool_create(buf, strlen(buf), r->pool);
    APR_BRIGADE_INSERT_TAIL(bb, e);
    if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) {
@@ -306,6 +315,7 @@ int ap_proxy_http_handler(request_rec *r, char *url,
        APR_BRIGADE_INSERT_TAIL(bb, e);
    }

    /* handle Via */
    if (conf->viaopt == via_block) {
	/* Block all outgoing Via: headers */
	apr_table_unset(r->headers_in, "Via");
@@ -318,7 +328,7 @@ int ap_proxy_http_handler(request_rec *r, char *url,
	    apr_snprintf(portstr, sizeof portstr, ":%d", i);
	}
	/* Generate outgoing Via: header with/without server comment: */
	ap_table_mergen(r->headers_in, "Via",
	apr_table_mergen(r->headers_in, "Via",
		    (conf->viaopt == via_full)
			? apr_psprintf(p, "%d.%d %s%s (%s)",
				HTTP_VERSION_MAJOR(r->proto_num),
@@ -332,32 +342,55 @@ int ap_proxy_http_handler(request_rec *r, char *url,
			);
    }

    /* send request headers */
    reqhdrs_arr = apr_table_elts(r->headers_in);
    reqhdrs = (apr_table_entry_t *) reqhdrs_arr->elts;
    for (i = 0; i < reqhdrs_arr->nelts; i++) {
	if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL
	/* Clear out headers not to send */

	/* Clear out hop-by-hop request headers not to send
	 * RFC2616 13.5.1 says we should strip these headers
	 */
	    || !strcasecmp(reqhdrs[i].key, "Host")	/* Already sent */
            || !strcasecmp(reqhdrs[i].key, "Keep-Alive")
            || !strcasecmp(reqhdrs[i].key, "TE")
            || !strcasecmp(reqhdrs[i].key, "Trailer")
            || !strcasecmp(reqhdrs[i].key, "Transfer-Encoding")
            || !strcasecmp(reqhdrs[i].key, "Upgrade")

	    /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be 
	     * suppressed if THIS server requested the authentication,
	     * not when a frontend proxy requested it!
             *
             * The solution to this problem is probably to strip out
             * the Proxy-Authorisation header in the authorisation
             * code itself, not here. This saves us having to signal
             * somehow whether this request was authenticated or not.
	     */
	    || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
	    || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization")
	    || !strcasecmp(reqhdrs[i].key, "Proxy-Authenticate"))
	    continue;

        buf = apr_pstrcat(r->pool, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL);
        e = apr_bucket_pool_create(buf, strlen(buf), r->pool);
        APR_BRIGADE_INSERT_TAIL(bb, e);

    }

    /* we don't yet support keepalives - but we will soon, I promise! */
    buf = apr_pstrcat(r->pool, "Connection: close", CRLF, NULL);
    e = apr_bucket_pool_create(buf, strlen(buf), r->pool);
    APR_BRIGADE_INSERT_TAIL(bb, e);

    /* add empty line at the end of the headers */
    e = apr_bucket_pool_create(CRLF, strlen(CRLF), r->pool);
    APR_BRIGADE_INSERT_TAIL(bb, e);
    e = apr_bucket_flush_create();
    APR_BRIGADE_INSERT_TAIL(bb, e);

    ap_pass_brigade(origin->output_filters, bb);
/* send the request data, if any. */

    /* send the request data, if any. */
    if (ap_should_client_block(r)) {
	while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
            e = apr_bucket_pool_create(buffer, i, r->pool);
@@ -401,7 +434,7 @@ int ap_proxy_http_handler(request_rec *r, char *url,
	int major, minor;
	if (2 != sscanf(buffer2, "HTTP/%u.%u", &major, &minor)) {
	    major = 1;
	    minor = 0;
	    minor = 1;
	}

        /* If not an HTTP/1 message or if the status line was > 8192 bytes */
@@ -431,12 +464,14 @@ int ap_proxy_http_handler(request_rec *r, char *url,
	}
        else
        {
            clear_connection(p, resp_hdrs);    /* Strip Connection hdrs */
	    /* strip connection listed hop-by-hop headers from response */
            ap_proxy_clear_connection(p, resp_hdrs);
            if (apr_table_get(resp_hdrs, "Content-type")) {
                r->content_type = apr_pstrdup(r->pool, apr_table_get(resp_hdrs, "Content-type"));
            }
        }

        /* handle Via header in response */
	if (conf->viaopt != via_off && conf->viaopt != via_block) {
	    /* Create a "Via:" response header entry and merge it */
	    i = ap_get_server_port(r);
@@ -454,10 +489,13 @@ int ap_proxy_http_handler(request_rec *r, char *url,
	r->status_line = "200 OK";
    }

/*
 * HTTP/1.0 requires us to accept 3 types of dates, but only generate
 * one type
 */
    /* munge the Location and URI response headers according to ProxyPassReverse */
    if ((table_buf = apr_table_get(resp_hdrs, "Location")) != NULL)
        apr_table_set(resp_hdrs, "Location", ap_proxy_location_reverse_map(r, buf));
    if ((table_buf = apr_table_get(resp_hdrs, "Content-Location")) != NULL)
        apr_table_set(resp_hdrs, "Content-Location", ap_proxy_location_reverse_map(r, buf));
    if ((table_buf = apr_table_get(resp_hdrs, "URI")) != NULL)
        apr_table_set(resp_hdrs, "URI", ap_proxy_location_reverse_map(r, buf));

/*
    if (!r->assbackwards)
+4 −4
Original line number Diff line number Diff line
@@ -450,7 +450,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, conn_
	for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
	    *end = '\0';

        ap_table_add(resp_hdrs, buffer, value);
        apr_table_add(resp_hdrs, buffer, value);

	/* the header was too long; at the least we should skip extra data */
	if (len >= size - 1) { 
@@ -482,7 +482,7 @@ void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *t)
	apr_size_t len = strlen(temp);
	apr_send(fp, temp, &len);

	for (i = 0; i < ap_table_elts(t)->nelts; ++i) {
	for (i = 0; i < apr_table_elts(t)->nelts; ++i) {
            if (elts[i].key != NULL) {
                temp = apr_pstrcat(r->pool, elts[i].key, ": ", elts[i].val, CRLF, NULL);
                apr_send(fp, temp, &len);
@@ -1046,7 +1046,7 @@ apr_status_t ap_proxy_doconnect(apr_socket_t *sock, char *host, apr_uint32_t por
    return rv;
}

/* This function is called by ap_table_do() for all header lines */
/* This function is called by apr_table_do() for all header lines */
/* (from proxy_http.c and proxy_ftp.c) */
/* It is passed a table_do_args struct pointer and a MIME field and value pair */
int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
@@ -1056,7 +1056,7 @@ int ap_proxy_send_hdr_line(void *p, const char *key, const char *value)
        return 1;
    if (!r->assbackwards)
        ap_rvputs(r, key, ": ", value, CRLF, NULL);
    return 1; /* tell ap_table_do() to continue calling us for more headers */
    return 1; /* tell apr_table_do() to continue calling us for more headers */
}

#if defined WIN32