Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26a0c37b97 | |||
| ccd800a0b1 | |||
| e2e21474ce | |||
| 7680a159a7 | |||
| 7aa5bc4a99 | |||
| 462acc9eee | |||
| 4678a62be8 | |||
| 525e331c0c | |||
| dc40c902ec | |||
| 6a8a1c5bf7 | |||
| 5bcd9e277e | |||
| 554577bbf2 | |||
| 458a2f5236 | |||
| 71e89efc64 | |||
| bbdfb5b429 | |||
| 1f02f368e1 | |||
| 0c1cbbdf64 | |||
| 75a4481750 | |||
| b1e188bdb6 | |||
| 4d940fb84e | |||
| a6a2da765b | |||
| 70038bc64a | |||
| 815fa29985 | |||
| c82bb2c7a4 | |||
| e9eaa23356 | |||
| 168df6ae68 | |||
| a7969a6382 | |||
| 243d4e1931 | |||
| 8246c03fda | |||
| 99ac026f00 | |||
| 90e4c40d86 | |||
| 0de4e20be1 |
@@ -27,8 +27,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.8.31.2.tar.gz"
|
||||
echo " $ tar -xzvf 1.8.31.2.tar.gz # expands to psol/"
|
||||
echo " $ wget https://dl.google.com/dl/page-speed/psol/1.9.32.1.tar.gz"
|
||||
echo " $ tar -xzvf 1.9.32.1.tar.gz # expands to psol/"
|
||||
echo ""
|
||||
echo " Or see the installation instructions:"
|
||||
echo " https://github.com/pagespeed/ngx_pagespeed#how-to-build"
|
||||
@@ -39,31 +39,6 @@ else
|
||||
build_from_source=true
|
||||
fi
|
||||
|
||||
psol_binary="${PSOL_BINARY:-unset}"
|
||||
if [ "$psol_binary" = "unset" ] ; then
|
||||
if $build_from_source ; then
|
||||
psol_binary="\
|
||||
$mod_pagespeed_dir/net/instaweb/automatic/pagespeed_automatic.a"
|
||||
else
|
||||
psol_library_dir="$ngx_addon_dir/psol/lib/$buildtype/$os_name/$arch_name"
|
||||
psol_binary="$psol_library_dir/pagespeed_automatic.a"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "mod_pagespeed_dir=$mod_pagespeed_dir"
|
||||
echo "build_from_source=$build_from_source"
|
||||
|
||||
ngx_feature="psol"
|
||||
ngx_feature_name=""
|
||||
ngx_feature_run=no
|
||||
ngx_feature_incs="
|
||||
#include \"net/instaweb/htmlparse/public/html_parse.h\"
|
||||
#include \"net/instaweb/htmlparse/public/html_writer_filter.h\"
|
||||
#include \"net/instaweb/util/public/string.h\"
|
||||
#include \"net/instaweb/util/public/string_writer.h\"
|
||||
#include \"net/instaweb/util/public/null_message_handler.h\"
|
||||
"
|
||||
|
||||
os_name='unknown_os'
|
||||
arch_name='unknown_arch'
|
||||
uname_os=`uname`
|
||||
@@ -124,6 +99,31 @@ if [ "$WNO_ERROR" = "YES" ]; then
|
||||
CFLAGS="$CFLAGS -Wno-error"
|
||||
fi
|
||||
|
||||
psol_binary="${PSOL_BINARY:-unset}"
|
||||
if [ "$psol_binary" = "unset" ] ; then
|
||||
if $build_from_source ; then
|
||||
psol_binary="\
|
||||
$mod_pagespeed_dir/net/instaweb/automatic/pagespeed_automatic.a"
|
||||
else
|
||||
psol_library_dir="$ngx_addon_dir/psol/lib/$buildtype/$os_name/$arch_name"
|
||||
psol_binary="$psol_library_dir/pagespeed_automatic.a"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "mod_pagespeed_dir=$mod_pagespeed_dir"
|
||||
echo "build_from_source=$build_from_source"
|
||||
|
||||
ngx_feature="psol"
|
||||
ngx_feature_name=""
|
||||
ngx_feature_run=no
|
||||
ngx_feature_incs="
|
||||
#include \"pagespeed/kernel/base/string.h\"
|
||||
#include \"pagespeed/kernel/base/string_writer.h\"
|
||||
#include \"pagespeed/kernel/base/null_message_handler.h\"
|
||||
#include \"pagespeed/kernel/html/html_parse.h\"
|
||||
#include \"pagespeed/kernel/html/html_writer_filter.h\"
|
||||
"
|
||||
|
||||
pagespeed_include="\
|
||||
$mod_pagespeed_dir \
|
||||
$mod_pagespeed_dir/third_party/chromium/src \
|
||||
|
||||
@@ -39,7 +39,7 @@ NgxBaseFetch::NgxBaseFetch(ngx_http_request_t* r, int pipe_fd,
|
||||
last_buf_sent_(false),
|
||||
pipe_fd_(pipe_fd),
|
||||
references_(2),
|
||||
handle_error_(true),
|
||||
ipro_lookup_(false),
|
||||
preserve_caching_headers_(preserve_caching_headers) {
|
||||
if (pthread_mutex_init(&mutex_, NULL)) CHECK(0);
|
||||
}
|
||||
@@ -137,14 +137,20 @@ void NgxBaseFetch::HandleHeadersComplete() {
|
||||
int status_code = response_headers()->status_code();
|
||||
bool status_ok = (status_code != 0) && (status_code < 400);
|
||||
|
||||
if (status_ok || handle_error_) {
|
||||
if (!ipro_lookup_ || status_ok) {
|
||||
// If this is a 404 response we need to count it in the stats.
|
||||
if (response_headers()->status_code() == HttpStatus::kNotFound) {
|
||||
server_context_->rewrite_stats()->resource_404_count()->Add(1);
|
||||
}
|
||||
}
|
||||
|
||||
RequestCollection(); // Headers available.
|
||||
// For the IPRO lookup, supress notification of the nginx side here.
|
||||
// If we send both this event and the one from done, nasty stuff will happen
|
||||
// if we loose the race with with the nginx side destructing this base fetch
|
||||
// instance (and thereby clearing the byte and its pending extraneous event.
|
||||
if (!ipro_lookup_) {
|
||||
RequestCollection(); // Headers available.
|
||||
}
|
||||
}
|
||||
|
||||
bool NgxBaseFetch::HandleFlush(MessageHandler* handler) {
|
||||
|
||||
@@ -79,7 +79,7 @@ class NgxBaseFetch : public AsyncFetch {
|
||||
|
||||
// Called by nginx when it's done with us.
|
||||
void Release();
|
||||
void set_handle_error(bool x) { handle_error_ = x; }
|
||||
void set_ipro_lookup(bool x) { ipro_lookup_ = x; }
|
||||
|
||||
private:
|
||||
virtual bool HandleWrite(const StringPiece& sp, MessageHandler* handler);
|
||||
@@ -117,7 +117,7 @@ class NgxBaseFetch : public AsyncFetch {
|
||||
// decremented once when Done() is called and once when Release() is called.
|
||||
int references_;
|
||||
pthread_mutex_t mutex_;
|
||||
bool handle_error_;
|
||||
bool ipro_lookup_;
|
||||
PreserveCachingHeaders preserve_caching_headers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NgxBaseFetch);
|
||||
|
||||
+69
-22
@@ -89,6 +89,8 @@ extern ngx_module_t ngx_pagespeed;
|
||||
namespace net_instaweb {
|
||||
|
||||
const char* kInternalEtagName = "@psol-etag";
|
||||
bool factory_init_called = false;
|
||||
|
||||
// The process context takes care of proactively initialising
|
||||
// a few libraries for us, some of which are not thread-safe
|
||||
// when they are initialized lazily.
|
||||
@@ -206,6 +208,13 @@ ngx_int_t string_piece_to_buffer_chain(
|
||||
|
||||
namespace {
|
||||
|
||||
// Get the context for this request. ps_connection_read_handler should already
|
||||
// have been called to create it.
|
||||
ps_request_ctx_t* ps_get_request_context(ngx_http_request_t* r) {
|
||||
return static_cast<ps_request_ctx_t*>(
|
||||
ngx_http_get_module_ctx(r, ngx_pagespeed));
|
||||
}
|
||||
|
||||
// Setting headers in nginx is tricky because it's not just a matter of adding
|
||||
// them to a list. You also need to remove them if there's already one there,
|
||||
// as well as setting the shortcut pointers (both upper case and lower case).
|
||||
@@ -286,11 +295,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,
|
||||
@@ -435,7 +439,10 @@ ngx_int_t copy_response_headers_to_ngx(
|
||||
} else if (STR_EQ_LITERAL(name, "Last-Modified")) {
|
||||
headers_out->last_modified = header;
|
||||
} else if (STR_EQ_LITERAL(name, "Location")) {
|
||||
headers_out->location = header;
|
||||
ps_request_ctx_t* ctx = ps_get_request_context(r);
|
||||
if (ctx->location_field_set) {
|
||||
headers_out->location = header;
|
||||
}
|
||||
} else if (STR_EQ_LITERAL(name, "Server")) {
|
||||
headers_out->server = header;
|
||||
} else if (STR_EQ_LITERAL(name, "Content-Length")) {
|
||||
@@ -610,6 +617,16 @@ char* ps_configure(ngx_conf_t* cf,
|
||||
NgxRewriteOptions** options,
|
||||
MessageHandler* handler,
|
||||
net_instaweb::RewriteOptions::OptionScope option_scope) {
|
||||
ps_main_conf_t* cfg_m = static_cast<ps_main_conf_t*>(
|
||||
ngx_http_conf_get_module_main_conf(cf, ngx_pagespeed));
|
||||
|
||||
if (!factory_init_called) {
|
||||
// Init logging to nginx's default error_log.
|
||||
cfg_m->driver_factory->LoggingInit(cf->cycle->log);
|
||||
cfg_m->driver_factory->Init();
|
||||
factory_init_called = true;
|
||||
}
|
||||
|
||||
// args[0] is always "pagespeed"; ignore it.
|
||||
ngx_uint_t n_args = cf->args->nelts - 1;
|
||||
|
||||
@@ -660,8 +677,6 @@ char* ps_configure(ngx_conf_t* cf,
|
||||
// directive yet. That happens below in ParseAndSetOptions().
|
||||
}
|
||||
|
||||
ps_main_conf_t* cfg_m = static_cast<ps_main_conf_t*>(
|
||||
ngx_http_cycle_get_module_main_conf(cf->cycle, ngx_pagespeed));
|
||||
if (*options == NULL) {
|
||||
*options = new NgxRewriteOptions(
|
||||
cfg_m->driver_factory->thread_system());
|
||||
@@ -730,7 +745,16 @@ void ps_cleanup_srv_conf(void* data) {
|
||||
// from being executed
|
||||
|
||||
if (!factory_deleted && cfg_s->server_context != NULL) {
|
||||
delete cfg_s->server_context->factory();
|
||||
NgxRewriteDriverFactory* factory = dynamic_cast<NgxRewriteDriverFactory*>(
|
||||
cfg_s->server_context->factory());
|
||||
|
||||
if (!factory_init_called) {
|
||||
factory->LoggingInit(ngx_cycle->log);
|
||||
factory->Init();
|
||||
factory_init_called = true;
|
||||
}
|
||||
|
||||
delete factory;
|
||||
factory_deleted = true;
|
||||
}
|
||||
if (cfg_s->proxy_fetch_factory != NULL) {
|
||||
@@ -800,7 +824,7 @@ void* ps_create_main_conf(ngx_conf_t* cf) {
|
||||
new SystemThreadSystem(),
|
||||
"" /* hostname, not used */,
|
||||
-1 /* port, not used */);
|
||||
cfg_m->driver_factory->Init();
|
||||
factory_init_called = false;
|
||||
ps_set_conf_cleanup_handler(cf, ps_cleanup_main_conf, cfg_m);
|
||||
return cfg_m;
|
||||
}
|
||||
@@ -1084,13 +1108,6 @@ GoogleString ps_determine_url(ngx_http_request_t* r) {
|
||||
host, port_string, str_to_string_piece(r->unparsed_uri));
|
||||
}
|
||||
|
||||
// Get the context for this request. ps_connection_read_handler should already
|
||||
// have been called to create it.
|
||||
ps_request_ctx_t* ps_get_request_context(ngx_http_request_t* r) {
|
||||
return static_cast<ps_request_ctx_t*>(
|
||||
ngx_http_get_module_ctx(r, ngx_pagespeed));
|
||||
}
|
||||
|
||||
void ps_release_base_fetch(ps_request_ctx_t* ctx);
|
||||
|
||||
// we are still at pagespeed phase
|
||||
@@ -1178,6 +1195,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 {
|
||||
@@ -1280,6 +1303,15 @@ void ps_connection_read_handler(ngx_event_t* ev) {
|
||||
rc = read(c->fd, chr, 256);
|
||||
} while (rc > 0 || (rc == -1 && errno == EINTR)); // Retry on EINTR.
|
||||
|
||||
if (r->connection->error) {
|
||||
ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0,
|
||||
"pagespeed [%p] request already finalized", r);
|
||||
ctx->pagespeed_connection = NULL;
|
||||
ngx_close_connection(c);
|
||||
ngx_http_finalize_request(r, NGX_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
ctx->pagespeed_connection = NULL;
|
||||
ngx_close_connection(c);
|
||||
@@ -1844,12 +1876,20 @@ ngx_int_t ps_resource_handler(ngx_http_request_t* r,
|
||||
CHECK(ctx == NULL);
|
||||
ctx = new ps_request_ctx_t();
|
||||
|
||||
ctx->base_fetch = NULL;
|
||||
ctx->pagespeed_connection = NULL;
|
||||
ctx->r = r;
|
||||
ctx->write_pending = false;
|
||||
ctx->html_rewrite = false;
|
||||
ctx->in_place = false;
|
||||
ctx->pagespeed_connection = NULL;
|
||||
ctx->write_pending = false;
|
||||
ctx->fetch_done = false;
|
||||
ctx->preserve_caching_headers = kDontPreserveHeaders;
|
||||
ctx->proxy_fetch = NULL;
|
||||
ctx->inflater_ = NULL;
|
||||
ctx->driver = NULL;
|
||||
ctx->recorder = NULL;
|
||||
ctx->ipro_response_headers = NULL;
|
||||
ctx->location_field_set = false;
|
||||
|
||||
// See build_context_for_request() in mod_instaweb.cc
|
||||
// TODO(jefftk): Is this the right place to be modifying caching headers for
|
||||
@@ -2023,7 +2063,7 @@ ngx_int_t ps_resource_handler(ngx_http_request_t* r,
|
||||
url_string.c_str());
|
||||
|
||||
ctx->in_place = true;
|
||||
ctx->base_fetch->set_handle_error(false);
|
||||
ctx->base_fetch->set_ipro_lookup(true);
|
||||
ctx->driver->FetchInPlaceResource(
|
||||
url, false /* proxy_mode */, ctx->base_fetch);
|
||||
|
||||
@@ -2263,6 +2303,8 @@ ngx_int_t ps_html_rewrite_header_filter(ngx_http_request_t* r) {
|
||||
}
|
||||
|
||||
ps_strip_html_headers(r);
|
||||
// See https://github.com/pagespeed/ngx_pagespeed/issues/819
|
||||
ctx->location_field_set = r->headers_out.location != NULL;
|
||||
|
||||
// TODO(jefftk): is this thread safe?
|
||||
copy_response_headers_from_ngx(r, ctx->base_fetch->response_headers());
|
||||
@@ -3074,10 +3116,15 @@ ngx_int_t ps_init_module(ngx_cycle_t* cycle) {
|
||||
"UseNativeFetcher is on, please configure a resolver.");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
// Update logging to the configured error_log in the http{} block.
|
||||
cfg_m->driver_factory->LoggingInit(cycle->log);
|
||||
cfg_m->driver_factory->RootInit();
|
||||
} else {
|
||||
if (!factory_init_called) {
|
||||
cfg_m->driver_factory->LoggingInit(cycle->log);
|
||||
cfg_m->driver_factory->Init();
|
||||
factory_init_called = true;
|
||||
}
|
||||
delete cfg_m->driver_factory;
|
||||
cfg_m->driver_factory = NULL;
|
||||
}
|
||||
@@ -3114,11 +3161,11 @@ ngx_int_t ps_init_child_process(ngx_cycle_t* cycle) {
|
||||
// Some server{} blocks may not have a ServerContext in that case we must
|
||||
// not instantiate a ProxyFetchFactory.
|
||||
if (cfg_s->server_context != NULL) {
|
||||
cfg_s->proxy_fetch_factory = new ProxyFetchFactory(cfg_s->server_context);
|
||||
ngx_http_core_loc_conf_t* clcf = static_cast<ngx_http_core_loc_conf_t*>(
|
||||
cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]);
|
||||
cfg_m->driver_factory->SetServerContextMessageHandler(
|
||||
cfg_s->server_context, clcf->error_log);
|
||||
cfg_s->proxy_fetch_factory = new ProxyFetchFactory(cfg_s->server_context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ typedef struct {
|
||||
// We need to remember the URL here as well since we may modify what NGX
|
||||
// gets by stripping our special query params and honoring X-Forwarded-Proto.
|
||||
GoogleString url_string;
|
||||
bool location_field_set;
|
||||
} ps_request_ctx_t;
|
||||
|
||||
|
||||
|
||||
@@ -498,6 +498,10 @@ NgxRewriteOptions* NgxRewriteOptions::Clone() const {
|
||||
return options;
|
||||
}
|
||||
|
||||
void NgxRewriteOptions::Merge(const RewriteOptions& src) {
|
||||
SystemRewriteOptions::Merge(src);
|
||||
}
|
||||
|
||||
const NgxRewriteOptions* NgxRewriteOptions::DynamicCast(
|
||||
const RewriteOptions* instance) {
|
||||
return dynamic_cast<const NgxRewriteOptions*>(instance);
|
||||
|
||||
@@ -140,6 +140,7 @@ class NgxRewriteOptions : public SystemRewriteOptions {
|
||||
|
||||
// Make an identical copy of these options and return it.
|
||||
virtual NgxRewriteOptions* Clone() const;
|
||||
virtual void Merge(const RewriteOptions& src);
|
||||
|
||||
// Returns a suitably down cast version of 'instance' if it is an instance
|
||||
// of this class, NULL if not.
|
||||
|
||||
Reference in New Issue
Block a user