Merge pull request #670 from pagespeed/oschaaf-downstream-cache-headers
downstream-caching-headers: make nginx 1.5.9+ pass tests as well
This commit is contained in:
+46
-46
@@ -205,6 +205,45 @@ ngx_int_t string_piece_to_buffer_chain(
|
||||
// modified from NgxBaseFetch::CopyHeadersFromTable()
|
||||
namespace {
|
||||
|
||||
// Based on ngx_http_add_cache_control.
|
||||
ngx_int_t ps_set_cache_control(ngx_http_request_t* r, char* cache_control) {
|
||||
// First strip existing cache-control headers.
|
||||
ngx_table_elt_t* header;
|
||||
NgxListIterator it(&(r->headers_out.headers.part));
|
||||
while ((header = it.Next()) != NULL) {
|
||||
if (STR_CASE_EQ_LITERAL(header->key, "Cache-Control")) {
|
||||
// Response headers with hash of 0 are excluded from the response.
|
||||
header->hash = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Now add our new cache control header.
|
||||
if (r->headers_out.cache_control.elts == NULL) {
|
||||
ngx_int_t rc = ngx_array_init(&r->headers_out.cache_control, r->pool,
|
||||
1, sizeof(ngx_table_elt_t *));
|
||||
if (rc != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
ngx_table_elt_t** cache_control_headers = static_cast<ngx_table_elt_t**>(
|
||||
ngx_array_push(&r->headers_out.cache_control));
|
||||
if (cache_control_headers == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
cache_control_headers[0] = static_cast<ngx_table_elt_t*>(
|
||||
ngx_list_push(&r->headers_out.headers));
|
||||
if (cache_control_headers[0] == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
cache_control_headers[0]->hash = 1;
|
||||
ngx_str_set(&cache_control_headers[0]->key, "Cache-Control");
|
||||
cache_control_headers[0]->value.len = strlen(cache_control);
|
||||
cache_control_headers[0]->value.data =
|
||||
reinterpret_cast<u_char*>(cache_control);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
template<class Headers>
|
||||
void copy_headers_from_table(const ngx_list_t &from, Headers* to) {
|
||||
// Standard nginx idiom for iterating over a list. See ngx_list.h
|
||||
@@ -290,16 +329,13 @@ ngx_int_t copy_response_headers_to_ngx(
|
||||
StringCaseEqual(name_gs, "Last-Modified") ||
|
||||
StringCaseEqual(name_gs, "Cache-Control")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (preserve_caching_headers == kPreserveOnlyCacheControl) {
|
||||
// Retain the original Cache-Control header, but send the recomputed
|
||||
// values for all other cache-related headers.
|
||||
if (StringCaseEqual(name_gs, "ETag") ||
|
||||
StringCaseEqual(name_gs, "Expires") ||
|
||||
StringCaseEqual(name_gs, "Date") ||
|
||||
StringCaseEqual(name_gs, "Last-Modified")) {
|
||||
if (StringCaseEqual(name_gs, "Cache-Control")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} // else we don't preserve any headers
|
||||
|
||||
ngx_str_t name, value;
|
||||
@@ -334,7 +370,10 @@ ngx_int_t copy_response_headers_to_ngx(
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (STR_EQ_LITERAL(name, "Content-Type")) {
|
||||
if (STR_EQ_LITERAL(name, "Cache-Control")) {
|
||||
ps_set_cache_control(r, const_cast<char*>(value_gs.c_str()));
|
||||
continue;
|
||||
} else if (STR_EQ_LITERAL(name, "Content-Type")) {
|
||||
// Unlike all the other headers, content_type is just a string.
|
||||
headers_out->content_type.data = value_s;
|
||||
headers_out->content_type.len = value.len;
|
||||
@@ -1937,45 +1976,6 @@ void ps_send_to_pagespeed(ngx_http_request_t* r,
|
||||
}
|
||||
#endif
|
||||
|
||||
// Based on ngx_http_add_cache_control.
|
||||
ngx_int_t ps_set_cache_control(ngx_http_request_t* r, char* cache_control) {
|
||||
// First strip existing cache-control headers.
|
||||
ngx_table_elt_t* header;
|
||||
NgxListIterator it(&(r->headers_out.headers.part));
|
||||
while ((header = it.Next()) != NULL) {
|
||||
if (STR_CASE_EQ_LITERAL(header->key, "Cache-Control")) {
|
||||
// Response headers with hash of 0 are excluded from the response.
|
||||
header->hash = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Now add our new cache control header.
|
||||
if (r->headers_out.cache_control.elts == NULL) {
|
||||
ngx_int_t rc = ngx_array_init(&r->headers_out.cache_control, r->pool,
|
||||
1, sizeof(ngx_table_elt_t *));
|
||||
if (rc != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
ngx_table_elt_t** cache_control_headers = static_cast<ngx_table_elt_t**>(
|
||||
ngx_array_push(&r->headers_out.cache_control));
|
||||
if (cache_control_headers == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
cache_control_headers[0] = static_cast<ngx_table_elt_t*>(
|
||||
ngx_list_push(&r->headers_out.headers));
|
||||
if (cache_control_headers[0] == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
cache_control_headers[0]->hash = 1;
|
||||
ngx_str_set(&cache_control_headers[0]->key, "Cache-Control");
|
||||
cache_control_headers[0]->value.len = strlen(cache_control);
|
||||
cache_control_headers[0]->value.data =
|
||||
reinterpret_cast<u_char*>(cache_control);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
void ps_strip_html_headers(ngx_http_request_t* r) {
|
||||
// We're modifying content, so switch to 'Transfer-Encoding: chunked' and
|
||||
// calculate on the fly.
|
||||
|
||||
+10
-13
@@ -93,6 +93,11 @@ function keepalive_test() {
|
||||
| grep -v "^} \\[data not shown"\
|
||||
| grep -v "^\\* upload completely sent off"\
|
||||
| grep -v "^\\* connected"\
|
||||
| grep -v "^\\* Found bundle for host"\
|
||||
| grep -v "^\\* Adding handle"\
|
||||
| grep -v "^\\* Curl_addHandleToPipeline"\
|
||||
| grep -v "^\\* - Conn "\
|
||||
| grep -v "^\\* Server "\
|
||||
| grep -v "^\\* Trying.*\\.\\.\\.")
|
||||
|
||||
# Nothing should remain after that.
|
||||
@@ -348,29 +353,20 @@ else
|
||||
|
||||
# The 1st request results in a cache miss, non-rewritten response
|
||||
# produced by pagespeed code and a subsequent purge request.
|
||||
# Because of the random bypassing of the cache (required for beaconing
|
||||
# integration), this request could result in a BYPASS as well.
|
||||
start_test Check for case where rewritten cache should get purged.
|
||||
check_for_no_rewriting "--header=Host:proxy_cache.example.com"
|
||||
check egrep -q "X-Cache: MISS|BYPASS" $OUT_HEADERS_FILE
|
||||
check egrep -q "X-Cache: MISS" $OUT_HEADERS_FILE
|
||||
fetch_until $STATISTICS_URL \
|
||||
'grep -c downstream_cache_purge_attempts:[[:space:]]*1' 1
|
||||
|
||||
while [ x"$(grep "$PURGE_REQUEST_IN_ACCESS_LOG" $ACCESS_LOG)" == x"" ] ; do
|
||||
echo "waiting for purge request to show up in access log"
|
||||
sleep .2
|
||||
done
|
||||
'grep -c successful_downstream_cache_purges:[[:space:]]*1' 1
|
||||
|
||||
check [ $(grep -ce "$PURGE_REQUEST_IN_ACCESS_LOG" $ACCESS_LOG) = 1 ];
|
||||
|
||||
# The 2nd request results in a cache miss (because of the previous purge),
|
||||
# rewritten response produced by pagespeed code and no new purge requests.
|
||||
# Because of the random bypassing of the cache (required for beaconing
|
||||
# integration), this request could result in a BYPASS as well.
|
||||
start_test Check for case where rewritten cache should not get purged.
|
||||
check_for_rewriting "--header=Host:proxy_cache.example.com \
|
||||
--header=X-PSA-Blocking-Rewrite:psatest"
|
||||
check egrep -q "X-Cache: MISS|BYPASS" $OUT_HEADERS_FILE
|
||||
check egrep -q "X-Cache: MISS" $OUT_HEADERS_FILE
|
||||
CURRENT_STATS=$($WGET_DUMP $STATISTICS_URL)
|
||||
check_from "$CURRENT_STATS" egrep -q \
|
||||
"downstream_cache_purge_attempts:[[:space:]]*1"
|
||||
@@ -392,7 +388,8 @@ else
|
||||
# output is also marked as a cache-miss, indicating that the instrumentation
|
||||
# was done by the backend.
|
||||
start_test Check whether beaconing is accompanied by a BYPASS always.
|
||||
WGET_ARGS="-S --header=Host:proxy_cache.example.com"
|
||||
WGET_ARGS="-S --header=Host:proxy_cache.example.com \
|
||||
--header=X-Allow-Beacon:yes"
|
||||
CACHABLE_HTML_LOC+="?PageSpeedFilters=lazyload_images"
|
||||
fetch_until -gzip $CACHABLE_HTML_LOC \
|
||||
"zgrep -c \"pagespeed\.CriticalImages\.Run\"" 1
|
||||
|
||||
@@ -150,7 +150,15 @@ http {
|
||||
set $bypass_cache "1";
|
||||
}
|
||||
|
||||
set_random $rand 0 100;
|
||||
# For testing purposes, we never generate values that will result in a beacon
|
||||
# unless a test request it via "X-Allow-Beacon: yes" in its request header.
|
||||
# This is for testing purposes, note that in a production environment,
|
||||
# you want 'set_random $rand 0 100;' unconditionally!
|
||||
set $rand 5;
|
||||
|
||||
if ($http_x_allow_beacon ~ "yes") {
|
||||
set_random $rand 0 100;
|
||||
}
|
||||
set $should_beacon_header_val "";
|
||||
if ($rand ~* "^[0-4]$") {
|
||||
set $should_beacon_header_val "random_rebeaconing_key";
|
||||
|
||||
Reference in New Issue
Block a user