| 3218 |
typedef struct header_connection { |
typedef struct header_connection { |
| 3219 |
apr_pool_t *pool; |
apr_pool_t *pool; |
| 3220 |
apr_array_header_t *array; |
apr_array_header_t *array; |
| 3221 |
const char *first; |
const char *error; |
| 3222 |
unsigned int closed:1; |
int is_req; |
| 3223 |
} header_connection; |
} header_connection; |
| 3224 |
|
|
| 3225 |
static int find_conn_headers(void *data, const char *key, const char *val) |
static int find_conn_headers(void *data, const char *key, const char *val) |
| 3226 |
{ |
{ |
| 3227 |
header_connection *x = data; |
header_connection *x = data; |
| 3228 |
const char *name; |
x->error = ap_parse_token_list_strict(x->pool, val, &x->array, !x->is_req); |
| 3229 |
|
return !x->error; |
|
do { |
|
|
while (*val == ',') { |
|
|
val++; |
|
|
} |
|
|
name = ap_get_token(x->pool, &val, 0); |
|
|
if (!strcasecmp(name, "close")) { |
|
|
x->closed = 1; |
|
|
} |
|
|
if (!x->first) { |
|
|
x->first = name; |
|
|
} |
|
|
else { |
|
|
const char **elt; |
|
|
if (!x->array) { |
|
|
x->array = apr_array_make(x->pool, 4, sizeof(char *)); |
|
|
} |
|
|
elt = apr_array_push(x->array); |
|
|
*elt = name; |
|
|
} |
|
|
} while (*val); |
|
|
|
|
|
return 1; |
|
| 3230 |
} |
} |
| 3231 |
|
|
| 3232 |
/** |
/** |
| 3233 |
* Remove all headers referred to by the Connection header. |
* Remove all headers referred to by the Connection header. |
| 3234 |
|
* Returns -1 on error. Otherwise, returns 1 if 'Close' was seen in |
| 3235 |
|
* the Connection header tokens, and 0 if not. |
| 3236 |
*/ |
*/ |
| 3237 |
static int ap_proxy_clear_connection(request_rec *r, apr_table_t *headers) |
static int ap_proxy_clear_connection(request_rec *r, apr_table_t *headers) |
| 3238 |
{ |
{ |
| 3239 |
const char **name; |
int closed = 0; |
| 3240 |
header_connection x; |
header_connection x; |
| 3241 |
|
|
| 3242 |
x.pool = r->pool; |
x.pool = r->pool; |
| 3243 |
x.array = NULL; |
x.array = NULL; |
| 3244 |
x.first = NULL; |
x.error = NULL; |
| 3245 |
x.closed = 0; |
x.is_req = (headers == r->headers_in); |
| 3246 |
|
|
| 3247 |
apr_table_unset(headers, "Proxy-Connection"); |
apr_table_unset(headers, "Proxy-Connection"); |
| 3248 |
|
|
| 3249 |
apr_table_do(find_conn_headers, &x, headers, "Connection", NULL); |
apr_table_do(find_conn_headers, &x, headers, "Connection", NULL); |
|
if (x.first) { |
|
|
/* fast path - no memory allocated for one header */ |
|
| 3250 |
apr_table_unset(headers, "Connection"); |
apr_table_unset(headers, "Connection"); |
| 3251 |
apr_table_unset(headers, x.first); |
|
| 3252 |
|
if (x.error) { |
| 3253 |
|
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, APLOGNO() |
| 3254 |
|
"Error parsing Connection header: %s", x.error); |
| 3255 |
|
return -1; |
| 3256 |
} |
} |
| 3257 |
|
|
| 3258 |
if (x.array) { |
if (x.array) { |
| 3259 |
/* two or more headers */ |
int i; |
| 3260 |
while ((name = apr_array_pop(x.array))) { |
for (i = 0; i < x.array->nelts; i++) { |
| 3261 |
apr_table_unset(headers, *name); |
const char *name = APR_ARRAY_IDX(x.array, i, const char *); |
| 3262 |
|
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO() |
| 3263 |
|
"Removing header '%s' listed in Connection header", |
| 3264 |
|
name); |
| 3265 |
|
if (!strcasecmp(name, "close")) { |
| 3266 |
|
closed = 1; |
| 3267 |
|
} |
| 3268 |
|
apr_table_unset(headers, name); |
| 3269 |
} |
} |
| 3270 |
} |
} |
| 3271 |
|
|
| 3272 |
return x.closed; |
return closed; |
| 3273 |
} |
} |
| 3274 |
|
|
| 3275 |
PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, |
PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_pool_t *p, |
| 3477 |
} |
} |
| 3478 |
|
|
| 3479 |
proxy_run_fixups(r); |
proxy_run_fixups(r); |
| 3480 |
ap_proxy_clear_connection(r, r->headers_in); |
if (ap_proxy_clear_connection(r, r->headers_in) < 0) { |
| 3481 |
|
return HTTP_BAD_REQUEST; |
| 3482 |
|
} |
| 3483 |
|
|
| 3484 |
/* send request headers */ |
/* send request headers */ |
| 3485 |
headers_in_array = apr_table_elts(r->headers_in); |
headers_in_array = apr_table_elts(r->headers_in); |