blob: dd8fbacc35f022eebe299800eeebc38e7bef0029 [file] [log] [blame]
/*
* Copyright 2016 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: morlovich@google.com (Maksim Orlovich)
//
//
// This looks at URLs in syntax of MeasurementProxyUrlNamer, and produces
// a configuration appropriate for them, including whether:
// 1) The URL should be served at all (password, syntax correctness)
// 2) There should be any rewriting happening, given site and resource
// domains.
// 3) The rewriting should be blocking.
#include "net/instaweb/config/measurement_proxy_rewrite_options_manager.h"
#include "net/instaweb/rewriter/public/domain_lawyer.h"
#include "net/instaweb/rewriter/public/measurement_proxy_url_namer.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/http/domain_registry.h"
#include "pagespeed/kernel/http/google_url.h"
#include "pagespeed/kernel/http/request_headers.h"
namespace net_instaweb {
MeasurementProxyRewriteOptionsManager::MeasurementProxyRewriteOptionsManager(
const ServerContext* server_context,
const GoogleString& root_domain,
const GoogleString& password)
: server_context_(server_context), root_domain_(root_domain),
password_(password) {
}
void MeasurementProxyRewriteOptionsManager::GetRewriteOptions(
const GoogleUrl& url,
const RequestHeaders& headers,
OptionsCallback* done) {
RewriteOptions* options = server_context_->global_options()->Clone();
StringPiece config, config_domain, password;
GoogleString res_url;
if (url.Origin() != root_domain_) {
Force403(options);
} else if (MeasurementProxyUrlNamer::DecodePathDetails(
url, &config, &config_domain, &password, &res_url)) {
if (password != password_) {
Force403(options);
} else {
GoogleUrl decoded_url(res_url);
ApplyConfig(decoded_url, config, config_domain, options);
}
} else {
Force403(options);
}
done->Run(options);
}
void MeasurementProxyRewriteOptionsManager::Force403(RewriteOptions* options) {
options->set_reject_blacklisted(true);
options->Disallow("*");
}
void MeasurementProxyRewriteOptionsManager::ApplyConfig(
const GoogleUrl& decoded_url, StringPiece config,
StringPiece config_domain, RewriteOptions* options) {
if (!decoded_url.IsWebValid()) {
Force403(options);
return;
}
// We don't have config spec yet, so this will declare that 'b' means
// blocking, and everything else will get ignored.
if (config == "b") {
options->set_rewrite_deadline_ms(-1);
options->set_in_place_wait_for_optimized(true);
options->set_in_place_rewrite_deadline_ms(-1);
}
// Setup permissions to only rewrite things related to the config_domain.
// Note that this not meant to be a security measure; we are just making
// a guess as to what resources are likely to be also optimizable by the
// owner of the config_domain site.
GoogleString config_domain_suffix =
domain_registry::MinimalPrivateSuffix(config_domain).as_string();
GoogleString actual_domain_suffix =
domain_registry::MinimalPrivateSuffix(decoded_url.Host()).as_string();
LowerString(&config_domain_suffix);
LowerString(&actual_domain_suffix);
if (config_domain_suffix == actual_domain_suffix) {
options->WriteableDomainLawyer()->AddDomain(
StrCat("http*://", config_domain_suffix),
server_context_->message_handler());
options->WriteableDomainLawyer()->AddDomain(
StrCat("http*://*.", config_domain_suffix),
server_context_->message_handler());
} else {
// Note: ProxyFetch gets paranoid about disallow * when a namer is in
// use, so we just turn off all the filters instead.
options->SetRewriteLevel(RewriteOptions::kPassThrough);
}
}
} // namespace net_instaweb