blob: 714c1b139f7e40172586065ee701e70d10fa77f7 [file] [log] [blame]
// Copyright 2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: jmarantz@google.com (Joshua Marantz)
#include "pagespeed/apache/apache_config.h"
#include "base/logging.h"
#include "net/instaweb/public/version.h"
#include "pagespeed/kernel/base/thread_system.h"
namespace net_instaweb {
namespace {
const char kModPagespeedStatisticsHandlerPath[] = "/mod_pagespeed_statistics";
const char kProxyAuth[] = "ProxyAuth";
const char kForceBuffering[] = "ForceBuffering";
const char kProxyAllRequests[] = "ExperimentalProxyAllRequests";
const char kMeasurementProxy[] = "ExperimentalMeasurementProxy";
} // namespace
RewriteOptions::Properties* ApacheConfig::apache_properties_ = nullptr;
void ApacheConfig::Initialize() {
if (Properties::Initialize(&apache_properties_)) {
SystemRewriteOptions::Initialize();
AddProperties();
}
}
void ApacheConfig::Terminate() {
if (Properties::Terminate(&apache_properties_)) {
SystemRewriteOptions::Terminate();
}
}
ApacheConfig::ApacheConfig(const StringPiece& description,
ThreadSystem* thread_system)
: SystemRewriteOptions(description, thread_system) {
Init();
}
ApacheConfig::ApacheConfig(ThreadSystem* thread_system)
: SystemRewriteOptions(thread_system) {
Init();
}
ApacheConfig::~ApacheConfig() {
}
void ApacheConfig::Init() {
DCHECK(apache_properties_ != NULL)
<< "Call ApacheConfig::Initialize() before construction";
InitializeOptions(apache_properties_);
}
void ApacheConfig::AddProperties() {
AddApacheProperty(
"", &ApacheConfig::proxy_auth_, "prxa",
kProxyAuth,
"CookieName[=Value][:RedirectUrl] -- checks proxy requests for "
"CookieName. If CookieValue is specified, checks for that. If "
"Redirect is specified, a failure results in a redirection to that URL "
"otherwise a 403 is generated.",
false /* safe_to_print */);
AddApacheProperty(
false, &ApacheConfig::force_buffering_, "afb",
kForceBuffering,
"Force buffering of non-html fetch responses rather than streaming",
true /* safe_to_print */);
AddApacheProperty(
false, &ApacheConfig::proxy_all_requests_mode_, "aparx",
kProxyAllRequests,
"Experimental mode where mod_pagespeed acts entirely as a proxy, and "
"doesn't attempt to work with any local serving. ",
false /* safe_to_print*/);
// Register deprecated options.
AddDeprecatedProperty("CollectRefererStatistics",
RewriteOptions::kDirectoryScope);
AddDeprecatedProperty("HashRefererStatistics",
RewriteOptions::kDirectoryScope);
AddDeprecatedProperty("RefererStatisticsOutputLevel",
RewriteOptions::kDirectoryScope);
AddDeprecatedProperty("StatisticsLoggingFile",
RewriteOptions::kDirectoryScope);
AddDeprecatedProperty("DisableForBots",
RewriteOptions::kDirectoryScope);
AddDeprecatedProperty("GeneratedFilePrefix",
RewriteOptions::kServerScope);
AddDeprecatedProperty("InheritVHostConfig",
RewriteOptions::kServerScope);
AddDeprecatedProperty("FetchFromModSpdy",
RewriteOptions::kServerScope);
AddDeprecatedProperty("NumShards", RewriteOptions::kServerScope);
AddDeprecatedProperty("UrlPrefix", RewriteOptions::kServerScope);
MergeSubclassProperties(apache_properties_);
// Default properties are global but to set them the current API requires
// an ApacheConfig instance and we're in a static method.
//
// TODO(jmarantz): Perform these operations on the Properties directly and
// get rid of this hack.
//
// Instantiation of the options with a null thread system wouldn't usually be
// safe but it's ok here because we're only updating the static properties on
// process startup. We won't have a thread-system yet or multiple threads.
ApacheConfig config("dummy_options", NULL);
config.set_default_x_header_value(kModPagespeedVersion);
}
ApacheConfig* ApacheConfig::Clone() const {
ApacheConfig* options =
new ApacheConfig(StrCat("cloned from ", description()), thread_system());
options->Merge(*this);
return options;
}
ApacheConfig* ApacheConfig::NewOptions() const {
return new ApacheConfig(StrCat("derived from ", description()),
thread_system());
}
const ApacheConfig* ApacheConfig::DynamicCast(const RewriteOptions* instance) {
const ApacheConfig* config = dynamic_cast<const ApacheConfig*>(instance);
DCHECK(config != NULL);
return config;
}
ApacheConfig* ApacheConfig::DynamicCast(RewriteOptions* instance) {
ApacheConfig* config = dynamic_cast<ApacheConfig*>(instance);
DCHECK(config != NULL);
return config;
}
void ApacheConfig::Merge(const RewriteOptions& src) {
SystemRewriteOptions::Merge(src);
const ApacheConfig* asrc = DynamicCast(&src);
CHECK(asrc != NULL);
// Can't use Merge() since we don't have names here.
measurement_proxy_root_.MergeHelper(&asrc->measurement_proxy_root_);
measurement_proxy_password_.MergeHelper(&asrc->measurement_proxy_password_);
}
RewriteOptions::OptionSettingResult ApacheConfig::ParseAndSetOptionFromName2(
StringPiece name, StringPiece arg1, StringPiece arg2,
GoogleString* msg, MessageHandler* handler) {
OptionSettingResult result = SystemRewriteOptions::ParseAndSetOptionFromName2(
name, arg1, arg2, msg, handler);
if (result == RewriteOptions::kOptionNameUnknown) {
if (name == kMeasurementProxy) {
arg1.CopyToString(&measurement_proxy_root_.mutable_value());
arg2.CopyToString(&measurement_proxy_password_.mutable_value());
result = RewriteOptions::kOptionOk;
}
}
return result;
}
GoogleString ApacheConfig::SubclassSignatureLockHeld() {
return StrCat(SystemRewriteOptions::SubclassSignatureLockHeld(),
"_MPR:", measurement_proxy_root_.value(),
"_MPP:", measurement_proxy_password_.value());
}
bool ApacheConfig::GetProxyAuth(StringPiece* name, StringPiece* value,
StringPiece* redirect) const {
StringPiece auth = proxy_auth_.value();
TrimWhitespace(&auth);
if (auth.empty()) {
return false;
}
// Strip the redirect off the tail if a colon is present. Note that
// a colon may exist in the redirect URL but we search from the beginning
// so it's no problem.
stringpiece_ssize_type colon = auth.find(':');
if (colon == StringPiece::npos) {
*redirect = StringPiece();
} else {
*redirect = auth.substr(colon + 1);
auth = auth.substr(0, colon);
}
// Split into name/value if an equals is present.
stringpiece_ssize_type equals = auth.find('=');
if (equals == StringPiece::npos) {
*name = auth;
*value = StringPiece();
} else {
*name = auth.substr(0, equals);
*value = auth.substr(equals + 1);
}
return true;
}
} // namespace net_instaweb