Compare commits

..

15 Commits

Author SHA1 Message Date
Jeff Kaufman ba78a8542b 1.10.33.5 -> 1.10.33.6 2016-03-03 15:02:43 -05:00
Otto van der Schaaf 306cdf358a IPRO: Copy the cache control value to ensure a correct lifetime
Fixes https://github.com/pagespeed/ngx_pagespeed/issues/1138
2016-03-03 15:02:05 -05:00
Otto van der Schaaf 8ff08ed7e9 Fix valgrind complaint caused by NgxBaseFetch
We should not use r->connection after we finalize the request.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/1100
2016-03-03 14:57:55 -05:00
Otto van der Schaaf fab4aac24e Eliminate CHECK that fails (rarely) during the IPRO lookup.
Fixes https://github.com/pagespeed/ngx_pagespeed/issues/1096
2016-03-03 14:57:49 -05:00
Otto van der Schaaf 88e3d48d23 Fix crasher on 404 .pagespeed. resources w/a custom location
- Fix nginx-side flow so we handle .pagespeed. resources ok
  when they will land on a customized 404 internal location.
- Additionally, check for a wiped request context and make sure
  we do not dereference a null pointer, which is what hurt in
  the flow we entered above as the IPRO lookup still was
  generating events while the nginx side request context was
  gone.
- Also, as a preliminary measure, do not check fail when we
  receive a stale event originating from a NgxBaseFetch that
  is no longer associated with our request context.
  Do log a warning so we'll hear about this happening either
  through system test failures or a bug report.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/1081
2016-03-03 14:57:40 -05:00
Otto van der Schaaf 4ec7afe5a8 Fix shutdown when ngx_pagespeed is completely disabled.
Fixes https://github.com/pagespeed/ngx_pagespeed/issues/1120
2016-02-17 10:19:21 -05:00
Jeffrey Crowell 751f532162 1.10.33.5 is released 2016-02-16 16:48:48 -05:00
Otto van der Schaaf fbde0ace7e Support building ngx_pagespeed as a dynamic module.
As of 1.9.11, nginx supports loading dynamic modules
This change makes us support building ngx_pagespeed.so

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/1116
2016-02-16 10:57:37 -05:00
Jeff Kaufman 13e99f631b Merge pull request #1112 from pra85/patch-1
Fix a typo
2016-02-11 13:17:03 -05:00
Jeff Kaufman 1c6c9f1a32 Merge pull request #1114 from PiotrSikora/nginx-1.9.11
Fix build with nginx-1.9.11+.
2016-02-10 15:03:00 -05:00
Piotr Sikora daa6031294 Fix build with nginx-1.9.11+.
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
2016-02-10 11:43:44 -08:00
Prayag Verma 5446303610 Fix a typo
`neet` → `need`
2016-02-09 11:30:05 +05:30
Jeffrey Crowell 6c3cc29def 1.10.33.4 is out 2016-02-05 13:11:31 -05:00
Jeffrey Crowell 17e8c7535a Merge pull request #1088 from pagespeed/crowell-reapply744
reapply:  location-header: tweak location header handling
2015-12-31 10:45:40 -05:00
Jeffrey Crowell 01e458ca0d reapply: location-header: tweak location header handling
- Fix potentially sending the location header into PSOL twice.
- Be more thorough when unsetting the location header

Attempts to fix #725

from oschaaf
2015-12-31 10:38:38 -05:00
5 changed files with 198 additions and 95 deletions
+119 -61
View File
@@ -29,8 +29,8 @@ if [ "$mod_pagespeed_dir" = "unset" ] ; then
echo " You need to separately download the pagespeed library:"
echo ""
echo " $ cd /path/to/ngx_pagespeed"
echo " $ wget https://dl.google.com/dl/page-speed/psol/1.10.33.4.tar.gz"
echo " $ tar -xzvf 1.10.33.4.tar.gz # expands to psol/"
echo " $ wget https://dl.google.com/dl/page-speed/psol/1.10.33.6.tar.gz"
echo " $ tar -xzvf 1.10.33.6.tar.gz # expands to psol/"
echo ""
echo " Or see the installation instructions:"
echo " https://github.com/pagespeed/ngx_pagespeed#how-to-build"
@@ -118,6 +118,13 @@ case "$NGX_GCC_VER" in
;;
esac
# workaround for a bug in nginx-1.9.11, see:
# http://hg.nginx.org/nginx/rev/ff1e625ae55b
NGX_VERSION=`grep nginx_version src/core/nginx.h | sed -e 's/^.* \(.*\)$/\1/'`
if [ "$NGX_VERSION" = "1009011" ]; then
CFLAGS="$CFLAGS -Wno-write-strings"
fi
if [ "$WNO_ERROR" = "YES" ]; then
CFLAGS="$CFLAGS -Wno-error"
fi
@@ -186,65 +193,7 @@ ngx_feature_test="
# Test whether we have pagespeed and can compile and link against it.
. "$ngx_addon_dir/cpp_feature"
if [ $ngx_found = yes ]; then
ps_src="$ngx_addon_dir/src"
ngx_addon_name=ngx_pagespeed
NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
$ps_src/log_message_handler.h \
$ps_src/ngx_base_fetch.h \
$ps_src/ngx_caching_headers.h \
$ps_src/ngx_event_connection.h \
$ps_src/ngx_fetch.h \
$ps_src/ngx_gzip_setter.h \
$ps_src/ngx_list_iterator.h \
$ps_src/ngx_message_handler.h \
$ps_src/ngx_pagespeed.h \
$ps_src/ngx_rewrite_driver_factory.h \
$ps_src/ngx_rewrite_options.h \
$ps_src/ngx_server_context.h \
$ps_src/ngx_url_async_fetcher.h \
$psol_binary"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
$ps_src/log_message_handler.cc \
$ps_src/ngx_base_fetch.cc \
$ps_src/ngx_caching_headers.cc \
$ps_src/ngx_event_connection.cc \
$ps_src/ngx_fetch.cc \
$ps_src/ngx_gzip_setter.cc \
$ps_src/ngx_list_iterator.cc \
$ps_src/ngx_message_handler.cc \
$ps_src/ngx_pagespeed.cc \
$ps_src/ngx_rewrite_driver_factory.cc \
$ps_src/ngx_rewrite_options.cc \
$ps_src/ngx_server_context.cc \
$ps_src/ngx_url_async_fetcher.cc"
# Save our sources in a separate var since we may need it in config.make
PS_NGX_SRCS="$NGX_ADDON_SRCS"
if [ "$position_aux" = "true" ] ; then
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
else
# Make pagespeed run immediately before gzip and Brotli.
if echo $HTTP_FILTER_MODULES | grep ngx_http_brotli_filter_module >/dev/null; then
module=ngx_http_brotli_filter_module
elif [ $HTTP_GZIP = YES ]; then
module=$HTTP_GZIP_FILTER_MODULE
else
module=$HTTP_RANGE_HEADER_FILTER_MODULE
fi
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES |\
sed "s/$module/$module $ngx_addon_name/")
fi
# Make the etag header filter run immediately before range header filter.
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES |\
sed "s/$HTTP_RANGE_HEADER_FILTER_MODULE/$HTTP_RANGE_HEADER_FILTER_MODULE ngx_pagespeed_etag_filter/")
CORE_LIBS="$CORE_LIBS $pagespeed_libs"
CORE_INCS="$CORE_INCS $pagespeed_include"
echo "List of modules (in reverse order of applicability): "$HTTP_FILTER_MODULES
else
if [ $ngx_found = no ]; then
cat << END
$0: error: module ngx_pagespeed requires the pagespeed optimization library.
Look in obj/autoconf.err for more details.
@@ -252,6 +201,115 @@ END
exit 1
fi
ps_src="$ngx_addon_dir/src"
ngx_addon_name=ngx_pagespeed
NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
$ps_src/log_message_handler.h \
$ps_src/ngx_base_fetch.h \
$ps_src/ngx_caching_headers.h \
$ps_src/ngx_event_connection.h \
$ps_src/ngx_fetch.h \
$ps_src/ngx_gzip_setter.h \
$ps_src/ngx_list_iterator.h \
$ps_src/ngx_message_handler.h \
$ps_src/ngx_pagespeed.h \
$ps_src/ngx_rewrite_driver_factory.h \
$ps_src/ngx_rewrite_options.h \
$ps_src/ngx_server_context.h \
$ps_src/ngx_url_async_fetcher.h \
$psol_binary"
NPS_SRCS=" \
$ps_src/log_message_handler.cc \
$ps_src/ngx_base_fetch.cc \
$ps_src/ngx_caching_headers.cc \
$ps_src/ngx_event_connection.cc \
$ps_src/ngx_fetch.cc \
$ps_src/ngx_gzip_setter.cc \
$ps_src/ngx_list_iterator.cc \
$ps_src/ngx_message_handler.cc \
$ps_src/ngx_pagespeed.cc \
$ps_src/ngx_rewrite_driver_factory.cc \
$ps_src/ngx_rewrite_options.cc \
$ps_src/ngx_server_context.cc \
$ps_src/ngx_url_async_fetcher.cc"
# Save our sources in a separate var since we may need it in config.make
PS_NGX_SRCS="$NGX_ADDON_SRCS \
$NPS_SRCS"
# Make pagespeed run immediately before gzip and Brotli.
if echo $HTTP_FILTER_MODULES | grep ngx_http_brotli_filter_module >/dev/null; then
next=ngx_http_brotli_filter_module
elif [ $HTTP_GZIP = YES ]; then
next=ngx_http_gzip_filter_module
else
next=ngx_http_range_header_filter_module
fi
if [ -n "$ngx_module_link" ]; then
# nginx-1.9.11+
ngx_module_type=HTTP_FILTER
ngx_module_name="ngx_pagespeed ngx_pagespeed_etag_filter"
ngx_module_incs="$ngx_feature_path"
ngx_module_deps=
ngx_module_srcs="$NPS_SRCS"
ngx_module_libs="$ngx_feature_libs"
ngx_module_order="ngx_http_range_header_filter_module\
ngx_pagespeed_etag_filter\
ngx_http_gzip_filter_module \
ngx_http_brotli_filter_module \
ngx_pagespeed \
ngx_http_postpone_filter_module \
ngx_http_ssi_filter_module \
ngx_http_charset_filter_module \
ngx_http_xslt_filter_module \
ngx_http_image_filter_module \
ngx_http_sub_filter_module \
ngx_http_addition_filter_module \
ngx_http_gunzip_filter_module \
ngx_http_userid_filter_module \
ngx_http_headers_filter_module"
. auto/module
if [ $ngx_module_link != DYNAMIC ]; then
# ngx_module_order doesn't work with static modules,
# so we must re-order filters here.
if [ "$position_aux" = "true" ] ; then
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
else
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES \
| sed "s/ngx_pagespeed//" \
| sed "s/$next/$next ngx_pagespeed/")
fi
# Make the etag header filter run immediately before range header filter.
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES \
| sed "s/ngx_pagespeed_etag_filter//" \
| sed "s/ngx_http_range_header_filter_module/ngx_http_range_header_filter_module ngx_pagespeed_etag_filter/")
else
# config.make is not executed for dynamic modules
CFLAGS="$CFLAGS -Wno-c++11-extensions"
if [ "$position_aux" = "true" ] ; then
ngx_module_type=HTTP_AUX_FILTER
ngx_module_order=""
fi
fi
else
CORE_LIBS="$CORE_LIBS $pagespeed_libs"
CORE_INCS="$CORE_INCS $pagespeed_include"
NGX_ADDON_SRCS="$PS_NGX_SRCS"
if [ "$position_aux" = "true" ] ; then
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
else
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES | sed "s/$next/$next $ngx_addon_name/")
fi
# Make the etag header filter run immediately before range header filter.
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES |\
sed "s/ngx_http_range_header_filter_module/ngx_http_range_header_filter_module ngx_pagespeed_etag_filter/")
fi
echo "List of modules (in reverse order of applicability): "$HTTP_FILTER_MODULES
# Test whether the compiler is compatible
ngx_feature="psol-compiler-compat"
ngx_feature_name=""
+31 -5
View File
@@ -118,6 +118,8 @@ const char* BaseFetchTypeToCStr(NgxBaseFetchType type) {
return "can't get here";
}
// TODO(oschaaf): replace the ngx_log_error with VLOGS or pass in a
// MessageHandler and use that.
void NgxBaseFetch::ReadCallback(const ps_event_data& data) {
NgxBaseFetch* base_fetch = reinterpret_cast<NgxBaseFetch*>(data.sender);
ngx_http_request_t* r = base_fetch->request();
@@ -138,19 +140,40 @@ void NgxBaseFetch::ReadCallback(const ps_event_data& data) {
if (refcount == 0 || detached) {
return;
}
ps_request_ctx_t* ctx = ps_get_request_context(r);
CHECK(data.sender == ctx->base_fetch);
CHECK(r->count > 0) << "r->count: " << r->count;
// If our request context was zeroed, skip this event.
// See https://github.com/pagespeed/ngx_pagespeed/issues/1081
if (ctx == NULL) {
// Should not happen normally, when it does this message will cause our
// system tests to fail.
ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0,
"pagespeed [%p] skipping event: request context gone", r);
return;
}
// Normally we expect the sender to equal the active NgxBaseFetch instance.
DCHECK(data.sender == ctx->base_fetch);
// If someone changed our request context or NgxBaseFetch, skip processing.
if (data.sender != ctx->base_fetch) {
ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0,
"pagespeed [%p] skipping event: event originating from disassociated"
" NgxBaseFetch instance.", r);
return;
}
int rc;
bool run_posted = true;
// If we are unlucky enough to have our connection finalized mid-ipro-lookup,
// we must enter a different flow. Also see ps_in_place_check_header_filter().
if ((ctx->base_fetch->base_fetch_type_ != kIproLookup)
&& r->connection->error) {
ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0,
"pagespeed [%p] request already finalized", r);
"pagespeed [%p] request already finalized %d", r, r->count);
rc = NGX_ERROR;
run_posted = false;
} else {
rc = ps_base_fetch::ps_base_fetch_handler(r);
}
@@ -163,8 +186,11 @@ void NgxBaseFetch::ReadCallback(const ps_event_data& data) {
ngx_connection_t* c = r->connection;
ngx_http_finalize_request(r, rc);
// See http://forum.nginx.org/read.php?2,253006,253061
ngx_http_run_posted_requests(c);
if (run_posted) {
// See http://forum.nginx.org/read.php?2,253006,253061
ngx_http_run_posted_requests(c);
}
}
void NgxBaseFetch::Lock() {
+32 -29
View File
@@ -284,7 +284,8 @@ ngx_int_t ps_base_fetch_handler(ngx_http_request_t* r) {
// modules running after us to manipulate those responses.
if (!status_ok && (ctx->base_fetch->base_fetch_type() != kHtmlTransform
&& ctx->base_fetch->base_fetch_type() != kIproLookup)) {
return status_code;
ps_release_base_fetch(ctx);
return ngx_http_filter_finalize_request(r, NULL, status_code);
}
if (ctx->preserve_caching_headers != kDontPreserveHeaders) {
@@ -302,6 +303,12 @@ ngx_int_t ps_base_fetch_handler(ngx_http_request_t* r) {
STR_CASE_EQ_LITERAL(header->key, "Last-Modified") ||
STR_CASE_EQ_LITERAL(header->key, "Expires"))))) {
header->hash = 0;
if (STR_CASE_EQ_LITERAL(header->key, "Location")) {
// There's a possible issue with the location header, where setting
// the hash to 0 is not enough. See:
// https://github.com/nginx/nginx/blob/master/src/http/ngx_http_header_filter_module.c#L314
r->headers_out.location = NULL;
}
}
}
} else {
@@ -452,11 +459,6 @@ void copy_response_headers_from_ngx(const ngx_http_request_t* r,
headers->set_status_code(r->headers_out.status);
if (r->headers_out.location != NULL) {
headers->Add(HttpAttributes::kLocation,
str_to_string_piece(r->headers_out.location->value));
}
// Manually copy over the content type because it's not included in
// request_->headers_out.headers.
headers->Add(HttpAttributes::kContentType,
@@ -490,6 +492,10 @@ ngx_int_t copy_response_headers_to_ngx(
ngx_int_t i;
for (i = 0 ; i < pagespeed_headers.NumAttributes() ; i++) {
// For IPRO cache misses, these gs_ variables may point to freed memory
// when nginx writes the headers to the output as the NgxBaseFetch instance
// that owns this memory gets released during request processing. So we
// copy these strings later on.
const GoogleString& name_gs = pagespeed_headers.Name(i);
const GoogleString& value_gs = pagespeed_headers.Value(i);
@@ -510,6 +516,9 @@ ngx_int_t copy_response_headers_to_ngx(
} // else we don't preserve any headers.
ngx_str_t name, value;
value.len = value_gs.size();
value.data = reinterpret_cast<u_char*>(
string_piece_to_pool_string(r->pool, value_gs.c_str()));
// To prevent the gzip module from clearing weak etags, we output them
// using a different name here. The etag header filter module runs behind
@@ -520,11 +529,15 @@ ngx_int_t copy_response_headers_to_ngx(
name.data = reinterpret_cast<u_char*>(
const_cast<char*>(kInternalEtagName));
} else {
name.len = name_gs.length();
name.data = reinterpret_cast<u_char*>(const_cast<char*>(name_gs.data()));
name.len = name_gs.size();
name.data = reinterpret_cast<u_char*>(
string_piece_to_pool_string(r->pool, name_gs.c_str()));
}
// In case string_piece_to_pool_string failed:
if (name.data == NULL || value.data == NULL) {
return NGX_ERROR;
}
value.len = value_gs.length();
value.data = reinterpret_cast<u_char*>(const_cast<char*>(value_gs.data()));
// TODO(jefftk): If we're setting a cache control header we'd like to
// prevent any downstream code from changing it. Specifically, if we're
@@ -535,24 +548,17 @@ ngx_int_t copy_response_headers_to_ngx(
// net/instaweb/apache/header_util:AddResponseHeadersToRequest
// Make copies of name and value to put into headers_out.
u_char* value_s = ngx_pstrdup(r->pool, &value);
if (value_s == NULL) {
return NGX_ERROR;
}
if (STR_EQ_LITERAL(name, "Cache-Control")) {
ps_set_cache_control(r, const_cast<char*>(value_gs.c_str()));
ps_set_cache_control(r, reinterpret_cast<char*>(value.data));
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;
headers_out->content_type = value;
// We should not include the charset when determining content_type_len, so
// scan for the ';' that marks the start of the charset part.
for (ngx_uint_t i = 0; i < value.len; i++) {
if (value_s[i] == ';') {
if (value.data[i] == ';') {
break;
}
headers_out->content_type_len = i + 1;
@@ -572,11 +578,6 @@ ngx_int_t copy_response_headers_to_ngx(
continue;
}
u_char* name_s = ngx_pstrdup(r->pool, &name);
if (name_s == NULL) {
return NGX_ERROR;
}
ngx_table_elt_t* header = static_cast<ngx_table_elt_t*>(
ngx_list_push(&headers_out->headers));
if (header == NULL) {
@@ -584,10 +585,10 @@ ngx_int_t copy_response_headers_to_ngx(
}
header->hash = 1; // Include this header in the output.
header->key.data = name.data;
header->key.len = name.len;
header->key.data = name_s;
header->value.data = value.data;
header->value.len = value.len;
header->value.data = value_s;
// Populate the shortcuts to commonly used headers.
if (STR_EQ_LITERAL(name, "Date")) {
@@ -636,7 +637,7 @@ typedef struct {
typedef struct {
// If pagespeed is configured in some server block but not this one our
// per-request code will be invoked but server context will be null. In those
// cases we neet to short circuit, not changing anything. Currently our
// cases we need to short circuit, not changing anything. Currently our
// header filter, body filter, and content handler all do this, but if anyone
// adds another way for nginx to give us a request to process we need to check
// there as well.
@@ -3066,7 +3067,9 @@ void ps_exit_child_process(ngx_cycle_t* cycle) {
ps_main_conf_t* cfg_m = static_cast<ps_main_conf_t*>(
ngx_http_cycle_get_module_main_conf(cycle, ngx_pagespeed));
NgxBaseFetch::Terminate();
cfg_m->driver_factory->ShutDown();
if (cfg_m->driver_factory != NULL) {
cfg_m->driver_factory->ShutDown();
}
}
// Called when nginx forks worker processes. No threads should be started
+8
View File
@@ -1241,6 +1241,14 @@ check_from "$OUT" fgrep -qi '404'
MATCHES=$(echo "$OUT" | grep -c "Cache-Control: override") || true
check [ $MATCHES -eq 1 ]
start_test Custom 404 does not crash.
URL=http://custom404.example.com/mod_pagespeed_test/
URL+=A.doesnotexist.css.pagespeed.cf.0.css
# The 404 response makes wget exit with an error code, which we ignore.
OUT=$(http_proxy=$SECONDARY_HOSTNAME $WGET_DUMP -O /dev/null -S $URL 2>&1) || true
# We ignored the exit code, check if we got a 404 response.
check_from "$OUT" fgrep -qi '404'
start_test Shutting down.
# Fire up some heavy load if ab is available to test a stressed shutdown
+8
View File
@@ -967,6 +967,14 @@ http {
}
}
server {
listen @@SECONDARY_PORT@@;
listen [::]:@@SECONDARY_PORT@@;
server_name custom404.example.com;
pagespeed FileCachePath "@@SECONDARY_CACHE@@";
error_page 404 /404.html;
}
server {
listen @@SECONDARY_PORT@@;
listen [::]:@@SECONDARY_PORT@@;