Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

[PATCH] Connection: support and HTTP/1.1

From: Graham Leggett <minfrin(at)sharp.fm>
Date: Tue Mar 13 2001 - 11:21:07 EST


Hi all,

This patch pulls in the Connection: header handling and the hop-by-hop header stripping from the v1.3 HTTP/1.1 patch. It changes the client level to HTTP/1.1, and adds some comments.

I'll apply it once the auth patch is sorted out, unless there are objections.

Regards,
Graham

-- 
-----------------------------------------
minfrin@sharp.fm		"There's a moon
					over Bourbon Street
						tonight..."

diff -c -r --exclude CVS tmp/CHANGES httpd-proxy/CHANGES
*** tmp/CHANGES Tue Mar 13 01:03:46 2001
--- httpd-proxy/CHANGES Tue Mar 13 16:25:25 2001 ***************
*** 1,5 ****
! ======= ! Last modified at [$Date: 2001/03/13 00:03:46 $] mod_proxy changes for 2.0build14 --- 1,11 ---- ! ! *) Some small changes: ! - Ensured hop-by-hop headers were stripped as per ! RFC2616 13.5.1. ! - Upgraded version code to HTTP/1.1. ! - Added Connection: close until Keepalives come. ! - Some cosmetic fixes and commenting. ! [Graham Leggett <minfrin@sharp.fm>] mod_proxy changes for 2.0build14 diff -c -r --exclude CVS tmp/module-2.0/proxy_http.c httpd-proxy/module-2.0/proxy_http.c
*** tmp/module-2.0/proxy_http.c Mon Mar 12 00:33:14 2001
--- httpd-proxy/module-2.0/proxy_http.c Tue Mar 13 16:07:52 2001 ***************
*** 119,125 ****
return OK; } ! static const char *proxy_location_reverse_map(request_rec *r, const char *url) { void *sconf; proxy_server_conf *conf; --- 119,125 ---- return OK; } ! static const char *ap_proxy_location_reverse_map(request_rec *r, const char *url) { void *sconf; proxy_server_conf *conf; ***************
*** 127,132 ****
--- 127,135 ---- 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,148 ****
} /* Clear all connection-based headers from the incoming headers table */ ! static void clear_connection(apr_pool_t *p, apr_table_t *headers) { const char *name; char *next = apr_pstrdup(p, apr_table_get(headers, "Connection")); --- 145,151 ---- } /* Clear all connection-based headers from the incoming headers table */ ! 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,190 ****
--- 188,194 ---- 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]; ***************
*** 210,216 ****
memset(&server, '\0', sizeof(server)); server.sin_family = AF_INET; ! /* We break the URL into host, port, path-search */ urlptr = strstr(url, "://"); if (urlptr == NULL) --- 214,220 ---- memset(&server, '\0', sizeof(server)); server.sin_family = AF_INET; ! /* We break the URL into host, port, path-search */ urlptr = strstr(url, "://"); if (urlptr == NULL) ***************
*** 239,245 ****
} } ! /* check if ProxyBlock directive on this host */ destaddr.s_addr = apr_inet_addr(desthost); for (i = 0; i < conf->noproxies->nelts; i++) { if ((npent[i].name != NULL --- 243,249 ---- } } ! /* check if ProxyBlock directive on this host */ destaddr.s_addr = apr_inet_addr(desthost); for (i = 0; i < conf->noproxies->nelts; i++) { if ((npent[i].name != NULL ***************
*** 285,298 ****
/* the peer reset the connection already; ap_new_connection() * closed the socket */ /* XXX somebody that knows what they're doing add an error path */ } ap_add_output_filter("CORE", NULL, NULL, origin); ! clear_connection(r->pool, r->headers_in); /* Strip connection-based headers */ buf = apr_pstrcat(r->pool, r->method, " ", proxyhost ? url : urlptr, ! " HTTP/1.0" 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) { --- 289,307 ---- /* 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); ! /* 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.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,311 ****
--- 315,321 ---- 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,324 ****
apr_snprintf(portstr, sizeof portstr, ":%d", i); } /* Generate outgoing Via: header with/without server comment: */ ! ap_table_mergen(r->headers_in, "Via", (conf->viaopt == via_full) ? apr_psprintf(p, "%d.%d %s%s (%s)", HTTP_VERSION_MAJOR(r->proto_num), --- 328,334 ---- apr_snprintf(portstr, sizeof portstr, ":%d", i); } /* Generate outgoing Via: header with/without server comment: */ ! 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,363 ****
); } 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 */ || !strcasecmp(reqhdrs[i].key, "Host") /* Already sent */ /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be * suppressed if THIS server requested the authentication, * not when a frontend proxy requested it! */ ! || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization")) 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); } 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. */ 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); --- 342,396 ---- ); } + /* 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 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-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. */ 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); ***************
*** 396,410 ****
APR_BUCKET_REMOVE(e); apr_bucket_destroy(e); ! /* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */ if (ap_checkmask(buffer2, "HTTP/#.# ###*")) { int major, minor; if (2 != sscanf(buffer2, "HTTP/%u.%u", &major, &minor)) { major = 1; ! minor = 0; } ! /* If not an HTTP/1 message or if the status line was > 8192 bytes */ if (buffer2[5] != '1' || buffer2[len - 1] != '\n') { apr_socket_close(sock); return HTTP_BAD_GATEWAY; --- 429,443 ---- APR_BUCKET_REMOVE(e); apr_bucket_destroy(e); ! /* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */ if (ap_checkmask(buffer2, "HTTP/#.# ###*")) { int major, minor; if (2 != sscanf(buffer2, "HTTP/%u.%u", &major, &minor)) { major = 1; ! minor = 1; } ! /* If not an HTTP/1 message or if the status line was > 8192 bytes */ if (buffer2[5] != '1' || buffer2[len - 1] != '\n') { apr_socket_close(sock); return HTTP_BAD_GATEWAY; ***************
*** 418,426 ****
buffer2[12] = ' '; r->status_line = apr_pstrdup(p, &buffer2[9]); ! /* read the headers. */ ! /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */ ! /* Also, take care with headers with multiple occurences. */ resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, origin); if (resp_hdrs == NULL) { --- 451,459 ---- buffer2[12] = ' '; r->status_line = apr_pstrdup(p, &buffer2[9]); ! /* read the headers. */ ! /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */ ! /* Also, take care with headers with multiple occurences. */ resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, origin); if (resp_hdrs == NULL) { ***************
*** 431,442 ****
} else { ! clear_connection(p, resp_hdrs); /* Strip Connection hdrs */ if (apr_table_get(resp_hdrs, "Content-type")) { r->content_type = apr_pstrdup(r->pool, apr_table_get(resp_hdrs, "Content-type")); } } if (conf->viaopt != via_off && conf->viaopt != via_block) { /* Create a "Via:" response header entry and merge it */ i = ap_get_server_port(r); --- 464,477 ---- } else { ! /* 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); ***************
*** 448,470 ****
} } else { ! /* an http/0.9 response */ backasswards = 1; r->status = 200; r->status_line = "200 OK"; } ! /* ! * HTTP/1.0 requires us to accept 3 types of dates, but only generate ! * one type ! */ /* if (!r->assbackwards) ap_rputs(CRLF, r); */ r->sent_bodyct = 1; ! /* Is it an HTTP/0.9 response? If so, send the extra data */ if (backasswards) { cntr = len; e = apr_bucket_heap_create(buffer, cntr, 0, NULL); --- 483,508 ---- } } else { ! /* an http/0.9 response */ backasswards = 1; r->status = 200; r->status_line = "200 OK"; } ! /* 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) ap_rputs(CRLF, r); */ r->sent_bodyct = 1; ! /* Is it an HTTP/0.9 response? If so, send the extra data */ if (backasswards) { cntr = len; e = apr_bucket_heap_create(buffer, cntr, 0, NULL); diff -c -r --exclude CVS tmp/module-2.0/proxy_util.c httpd-proxy/module-2.0/proxy_util.c
*** tmp/module-2.0/proxy_util.c Mon Mar 12 00:33:24 2001
--- httpd-proxy/module-2.0/proxy_util.c Tue Mar 13 16:08:37 2001 ***************
*** 450,456 ****
for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end) *end = '\0'; ! ap_table_add(resp_hdrs, buffer, value); /* the header was too long; at the least we should skip extra data */ if (len >= size - 1) { --- 450,456 ---- for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end) *end = '\0'; ! 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,488 ****
apr_size_t len = strlen(temp); apr_send(fp, temp, &len); ! for (i = 0; i < ap_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); --- 482,488 ---- apr_size_t len = strlen(temp); apr_send(fp, temp, &len); ! 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,1052 ****
return rv; } ! /* This function is called by ap_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) --- 1046,1052 ---- return rv; } ! /* 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,1062 ****
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 */ } #if defined WIN32 --- 1056,1062 ---- return 1; if (!r->assbackwards) ap_rvputs(r, key, ": ", value, CRLF, NULL); ! return 1; /* tell apr_table_do() to continue calling us for more headers */ } #if defined WIN32 Received on Tue Mar 13 15:24:47 2001

This archive was generated by hypermail 2.1.8 : Thu Aug 24 2006 - 14:53:14 EDT


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library