Always parse process config into RewriteDriverFactory::default_options,
and then sync it back to per-ServerContext options. Should fix the regression with ImageMaxRewritesAtOnce (https://github.com/pagespeed/mod_pagespeed/issues/1305) and give RewriteDriverFactory and all the ServerContexts a consistent view of their value.
This commit is contained in:
@@ -1825,6 +1825,24 @@ ModPagespeedMessagesDomains Allow localhost
|
||||
ModPagespeedExperimentalMeasurementProxy "http://mpr.example.com" secret
|
||||
</VirtualHost>
|
||||
|
||||
# For testing how we handle process-scope options.
|
||||
ModPagespeedIproMaxResponseBytes 1048576001
|
||||
<VirtualHost localhost:@@APACHE_SECONDARY_PORT@@>
|
||||
ServerName ps1.example.com
|
||||
DocumentRoot "@@APACHE_DOC_ROOT@@"
|
||||
ModPagespeedFileCachePath "@@MOD_PAGESPEED_CACHE@@_mpr"
|
||||
ModPagespeedIproMaxResponseBytes 1048576002
|
||||
ModPagespeedEnableFilters debug
|
||||
</VirtualHost>
|
||||
|
||||
<VirtualHost localhost:@@APACHE_SECONDARY_PORT@@>
|
||||
ServerName ps2.example.com
|
||||
DocumentRoot "@@APACHE_DOC_ROOT@@"
|
||||
ModPagespeedFileCachePath "@@MOD_PAGESPEED_CACHE@@_mpr"
|
||||
ModPagespeedIproMaxResponseBytes 1048576003
|
||||
ModPagespeedEnableFilters debug
|
||||
</VirtualHost>
|
||||
|
||||
# For testing with a custom origin header. In this VirtualHost,
|
||||
# /mod_pagespeed_test is included in our DocumentRoot and thus does
|
||||
# not need to be in any resource URL paths. This helps us verify that
|
||||
|
||||
@@ -2772,6 +2772,10 @@ class RewriteOptions {
|
||||
// not true, this function will DCHECK.
|
||||
virtual void Merge(const RewriteOptions& src);
|
||||
|
||||
// Merge the process scope options (including strict ones) from src into
|
||||
// this.
|
||||
void MergeOnlyProcessScopeOptions(const RewriteOptions& src);
|
||||
|
||||
// Registers a wildcard pattern for to be allowed, potentially overriding
|
||||
// previous Disallow wildcards.
|
||||
void Allow(StringPiece wildcard_pattern) {
|
||||
|
||||
@@ -3885,6 +3885,28 @@ void RewriteOptions::Merge(const RewriteOptions& src) {
|
||||
}
|
||||
}
|
||||
|
||||
void RewriteOptions::MergeOnlyProcessScopeOptions(const RewriteOptions& src) {
|
||||
DCHECK(!frozen_);
|
||||
#ifndef NDEBUG // MergeOK is only around in CHECK-enabled builds.
|
||||
CHECK(src.MergeOK());
|
||||
#endif
|
||||
|
||||
DCHECK_EQ(all_options_.size(), src.all_options_.size());
|
||||
DCHECK_EQ(initialized_options_, src.initialized_options_);
|
||||
DCHECK_EQ(initialized_options_, all_options_.size());
|
||||
|
||||
size_t options_to_merge = std::min(all_options_.size(),
|
||||
src.all_options_.size());
|
||||
for (size_t i = 0; i < options_to_merge; ++i) {
|
||||
OptionScope scope = all_options_[i]->scope();
|
||||
if (scope == kProcessScope || scope == kProcessScopeStrict) {
|
||||
all_options_[i]->Merge(src.all_options_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Modify();
|
||||
}
|
||||
|
||||
RewriteOptions* RewriteOptions::Clone() const {
|
||||
RewriteOptions* options = NewOptions();
|
||||
options->Merge(*this);
|
||||
|
||||
@@ -662,6 +662,20 @@ TEST_F(RewriteOptionsTest, MergeDistributed) {
|
||||
EXPECT_FALSE(options_.Distributable(RewriteOptions::kCssFilterId));
|
||||
}
|
||||
|
||||
TEST_F(RewriteOptionsTest, MergeOnlyProcessScopeOptions) {
|
||||
RewriteOptions dest(&thread_system_), src(&thread_system_);
|
||||
dest.set_image_max_rewrites_at_once(2);
|
||||
dest.set_max_url_segment_size(1);
|
||||
src.set_image_max_rewrites_at_once(5);
|
||||
src.set_max_url_segment_size(4);
|
||||
|
||||
dest.MergeOnlyProcessScopeOptions(src);
|
||||
// Pulled in set_image_max_rewrites_at_once, which is process scope,
|
||||
// but not the other option.
|
||||
EXPECT_EQ(5, dest.image_max_rewrites_at_once());
|
||||
EXPECT_EQ(1, dest.max_url_segment_size());
|
||||
}
|
||||
|
||||
TEST_F(RewriteOptionsTest, Allow) {
|
||||
options_.Allow("*.css");
|
||||
EXPECT_TRUE(options_.IsAllowed("abcd.css"));
|
||||
|
||||
@@ -328,9 +328,9 @@ class ApacheProcessContext {
|
||||
return factory_.get();
|
||||
}
|
||||
|
||||
// Checks cmd to see if it's used in a vhost or conditional context, and
|
||||
// if so, if that's an error or warning condition.
|
||||
const char* CheckCommandForVhost(const cmd_parms* cmd);
|
||||
// Checks cmd to see if it's process scope, and if so if it's used in an
|
||||
// incorrect context, returning an error message if so.
|
||||
const char* CheckProcessScope(const cmd_parms* cmd, bool* is_process_scope);
|
||||
|
||||
scoped_ptr<ApacheRewriteDriverFactory> factory_;
|
||||
// Process-scoped static variable cleanups, mainly for valgrind.
|
||||
@@ -988,6 +988,18 @@ int pagespeed_post_config(apr_pool_t* pool, apr_pool_t* plog, apr_pool_t* ptemp,
|
||||
CHECK(server_context != NULL);
|
||||
server_contexts.push_back(server_context);
|
||||
}
|
||||
|
||||
// We also want propagate all the per-process options to each vhost. The
|
||||
// normal merge in merge_server_config isn't enough since that merges the
|
||||
// non-per process things from a dummy ServerContext corresponding to the
|
||||
// top-level config, not ApacheRewriteDriverFactory::default_options where
|
||||
// the process scope options go.
|
||||
//
|
||||
// We do this here rather than merge_server_config since we want to touch
|
||||
// the ServerContext corresponding to the top-level/non-<VirtualHost>
|
||||
// block, too.
|
||||
server_context->global_config()->MergeOnlyProcessScopeOptions(
|
||||
*factory->default_options());
|
||||
}
|
||||
|
||||
GoogleString error_message;
|
||||
@@ -1322,17 +1334,14 @@ static char* CheckGlobalOption(const cmd_parms* cmd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ApacheProcessContext::CheckCommandForVhost(const cmd_parms* cmd) {
|
||||
// Only do the vhost_command_handling_map_ lookup if it's going
|
||||
// to be used by CheckGlobalOption.
|
||||
//
|
||||
// TODO(jmarantz): Add a scope argument ParseAndSetOptionFromName[123] and
|
||||
// let it do the error-checking & reporting.
|
||||
const char* ApacheProcessContext::CheckProcessScope(
|
||||
const cmd_parms* cmd, bool* is_process_scope) {
|
||||
VhostCommandHandlingMap::const_iterator p =
|
||||
vhost_command_handling_map_.find(cmd->cmd);
|
||||
*is_process_scope = (p != vhost_command_handling_map_.end());
|
||||
const char* ret = NULL;
|
||||
if (cmd->server->is_virtual || (cmd->directive->data != NULL)) {
|
||||
VhostCommandHandlingMap::const_iterator p =
|
||||
vhost_command_handling_map_.find(cmd->cmd);
|
||||
if (p != vhost_command_handling_map_.end()) {
|
||||
if (*is_process_scope) {
|
||||
ret = CheckGlobalOption(cmd, p->second, factory_->message_handler());
|
||||
}
|
||||
}
|
||||
@@ -1407,20 +1416,36 @@ static const char* ParseDirective(cmd_parms* cmd, void* data, const char* arg) {
|
||||
if (directive.starts_with(prefix)) {
|
||||
StringPiece option = directive.substr(prefix.size());
|
||||
GoogleString msg;
|
||||
|
||||
bool use_global_config = false;
|
||||
// See if it's a global option, and perhaps not in place.
|
||||
ret = apache_process_context.CheckProcessScope(cmd, &use_global_config);
|
||||
if (ret != NULL) {
|
||||
return ret;
|
||||
}
|
||||
// Options that are per-process are always parsed into
|
||||
// ApacheRewriteDriverFactory::default_options(), and then propagated
|
||||
// in the post-config hook (pagespeed_post_config).
|
||||
if (use_global_config) {
|
||||
config = ApacheConfig::DynamicCast(factory->default_options());
|
||||
}
|
||||
|
||||
// See whether generic RewriteOptions name handling can figure this one out.
|
||||
RewriteOptions::OptionSettingResult result =
|
||||
config->ParseAndSetOptionFromName1(option, arg, &msg, handler);
|
||||
if (result == RewriteOptions::kOptionNameUnknown) {
|
||||
// RewriteOptions didn't know; try the driver factory.
|
||||
// TODO(morlovich): It may be cleaner to not have process-scope options
|
||||
// in RewriteOptions at all, but rather something RewriteDriverFactory
|
||||
// specific, as long as we can provide a painless way of integrating it
|
||||
// in the server and parsing it (areas where the current manual approach
|
||||
// fails).
|
||||
result = factory->ParseAndSetOption1(
|
||||
option, arg,
|
||||
!cmd->server->is_virtual, // is_process_scope
|
||||
&msg, handler);
|
||||
}
|
||||
if (StandardParsingHandled(cmd, result, msg, &ret)) {
|
||||
if (ret == NULL) {
|
||||
ret = apache_process_context.CheckCommandForVhost(cmd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -1903,6 +1928,7 @@ void* merge_server_config(apr_pool_t* pool, void* base_conf, void* new_conf) {
|
||||
new_non_spdy_overlay.release());
|
||||
}
|
||||
}
|
||||
|
||||
return new_conf;
|
||||
}
|
||||
|
||||
|
||||
@@ -1037,6 +1037,17 @@ if [ "$SECONDARY_HOSTNAME" != "" ]; then
|
||||
# Note that this also checks that it got minified --- the original has
|
||||
# spaces around the equal sign.
|
||||
check_from "$OUT" fgrep -q "goog.constructNamespace_="
|
||||
|
||||
start_test Process-scope configuration handling.
|
||||
# Must be the same value in top-level and both vhosts
|
||||
OUT=$($CURL --silent $HOSTNAME/?PageSpeedFilters=+debug)
|
||||
check_from "$OUT" fgrep -q "IproMaxResponseBytes (imrb) 1048576003"
|
||||
|
||||
OUT=$($CURL --silent --proxy $SECONDARY_HOSTNAME http://ps1.example.com)
|
||||
check_from "$OUT" fgrep -q "IproMaxResponseBytes (imrb) 1048576003"
|
||||
|
||||
OUT=$($CURL --silent --proxy $SECONDARY_HOSTNAME http://ps2.example.com)
|
||||
check_from "$OUT" fgrep -q "IproMaxResponseBytes (imrb) 1048576003"
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
|
||||
Reference in New Issue
Block a user