Sets response headers for a negotiated response. * neg->is_transparent determines whether a transparently negotiated * response or a plain `server driven negotiation' response is * created. Applicable headers are Alternates, Vary, and TCN. * * The Vary header we create is sometimes longer than is required for * the correct caching of negotiated results by HTTP/1.1 caches. For * example i
| 2431 | * twiddles in the server-side negotiation algorithms into account. |
| 2432 | */ |
| 2433 | static void set_neg_headers(request_rec *r, negotiation_state *neg, |
| 2434 | int alg_result) |
| 2435 | { |
| 2436 | apr_table_t *hdrs; |
| 2437 | var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; |
| 2438 | const char *sample_type = NULL; |
| 2439 | const char *sample_language = NULL; |
| 2440 | const char *sample_encoding = NULL; |
| 2441 | const char *sample_charset = NULL; |
| 2442 | char *lang; |
| 2443 | char *qstr; |
| 2444 | apr_off_t len; |
| 2445 | apr_array_header_t *arr; |
| 2446 | int max_vlist_array = (neg->avail_vars->nelts * 21); |
| 2447 | int first_variant = 1; |
| 2448 | int vary_by_type = 0; |
| 2449 | int vary_by_language = 0; |
| 2450 | int vary_by_charset = 0; |
| 2451 | int vary_by_encoding = 0; |
| 2452 | int j; |
| 2453 | |
| 2454 | /* In order to avoid O(n^2) memory copies in building Alternates, |
| 2455 | * we preallocate a apr_table_t with the maximum substrings possible, |
| 2456 | * fill it with the variant list, and then concatenate the entire array. |
| 2457 | * Note that if you change the number of substrings pushed, you also |
| 2458 | * need to change the calculation of max_vlist_array above. |
| 2459 | */ |
| 2460 | if (neg->send_alternates && neg->avail_vars->nelts) |
| 2461 | arr = apr_array_make(r->pool, max_vlist_array, sizeof(char *)); |
| 2462 | else |
| 2463 | arr = NULL; |
| 2464 | |
| 2465 | /* Put headers into err_headers_out, since send_http_header() |
| 2466 | * outputs both headers_out and err_headers_out. |
| 2467 | */ |
| 2468 | hdrs = r->err_headers_out; |
| 2469 | |
| 2470 | for (j = 0; j < neg->avail_vars->nelts; ++j) { |
| 2471 | var_rec *variant = &avail_recs[j]; |
| 2472 | |
| 2473 | if (variant->content_languages && variant->content_languages->nelts) { |
| 2474 | lang = apr_array_pstrcat(r->pool, variant->content_languages, ','); |
| 2475 | } |
| 2476 | else { |
| 2477 | lang = NULL; |
| 2478 | } |
| 2479 | |
| 2480 | /* Calculate Vary by looking for any difference between variants */ |
| 2481 | |
| 2482 | if (first_variant) { |
| 2483 | sample_type = variant->mime_type; |
| 2484 | sample_charset = variant->content_charset; |
| 2485 | sample_language = lang; |
| 2486 | sample_encoding = variant->content_encoding; |
| 2487 | } |
| 2488 | else { |
| 2489 | if (!vary_by_type && |
| 2490 | strcmp(sample_type ? sample_type : "", |
no test coverage detected