| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| #include "pagespeed/apache/apache_server_context.h" |
| |
| #include <memory> |
| |
| // http_protocol.h includes httpd.h. We need to include httpd_includes.h, which |
| // works around a conflicting definition of OK in gRPC. |
| #include "http_protocol.h" // NOLINT |
| #include "net/instaweb/rewriter/config/measurement_proxy_rewrite_options_manager.h" |
| #include "net/instaweb/rewriter/public/measurement_proxy_url_namer.h" |
| #include "pagespeed/apache/apache_config.h" |
| #include "pagespeed/apache/apache_httpd_includes.h" |
| #include "pagespeed/apache/apache_request_context.h" |
| #include "pagespeed/apache/apache_rewrite_driver_factory.h" |
| #include "pagespeed/automatic/proxy_fetch.h" |
| #include "pagespeed/automatic/proxy_interface.h" |
| #include "pagespeed/kernel/base/file_system.h" |
| #include "pagespeed/kernel/base/message_handler.h" |
| #include "pagespeed/kernel/base/statistics.h" |
| #include "pagespeed/kernel/base/string_util.h" |
| #include "pagespeed/kernel/base/thread_system.h" |
| #include "pagespeed/kernel/http/http_names.h" |
| |
| namespace net_instaweb { |
| |
| const char ApacheServerContext::kProxyInterfaceStatsPrefix[] = |
| "proxy-all-mode-"; |
| |
| ApacheServerContext::ApacheServerContext(ApacheRewriteDriverFactory* factory, |
| server_rec* server, |
| const StringPiece& version) |
| : SystemServerContext(factory, server->server_hostname, server->port), |
| apache_factory_(factory), |
| server_rec_(server), |
| version_(version.data(), version.size()) { |
| // We may need the message handler for error messages very early, before |
| // we get to InitServerContext in ChildInit(). |
| set_message_handler(apache_factory_->message_handler()); |
| |
| // Currently, mod_pagespeed always runs upstream of mod_headers when used as |
| // an origin server. Note that in a proxy application, this might not be the |
| // case. I'm not sure how we can detect this on a per-request basis so |
| // that might require a small refactor. |
| // |
| // TODO(jmarantz): We'd like to change this for various reasons but are unsure |
| // of the impact. |
| set_response_headers_finalized(false); |
| } |
| |
| ApacheServerContext::~ApacheServerContext() {} |
| |
| void ApacheServerContext::InitStats(Statistics* statistics) { |
| ProxyInterface::InitStats(kProxyInterfaceStatsPrefix, statistics); |
| SystemServerContext::InitStats(statistics); |
| } |
| |
| bool ApacheServerContext::InitPath(const GoogleString& path) { |
| if (file_system()->IsDir(path.c_str(), message_handler()).is_true()) { |
| return true; |
| } |
| bool ok = file_system()->RecursivelyMakeDir(path, message_handler()); |
| if (ok) { |
| apache_factory_->AddCreatedDirectory(path); |
| } |
| return ok; |
| } |
| |
| ApacheConfig* ApacheServerContext::global_config() { |
| return ApacheConfig::DynamicCast(global_options()); |
| } |
| |
| const ApacheConfig* ApacheServerContext::global_config() const { |
| return ApacheConfig::DynamicCast(global_options()); |
| } |
| |
| ApacheConfig* ApacheServerContext::SpdyConfigOverlay() { |
| // While we no longer actually use the spdy config overlay, it's still |
| // useful for backwards compatibility during parsing. |
| if (spdy_config_overlay_.get() == nullptr) { |
| spdy_config_overlay_ = |
| std::make_unique<ApacheConfig>("spdy_overlay", thread_system()); |
| // We want to copy any implicit rewrite level from the parent, |
| // so we don't end up overriding it with passthrough. It's also OK |
| // to forward explicit one to an implicit one here, since an implicit |
| // will never override an explicit one (even if its different). |
| spdy_config_overlay_->SetDefaultRewriteLevel(global_config()->level()); |
| } |
| return spdy_config_overlay_.get(); |
| } |
| |
| ApacheConfig* ApacheServerContext::NonSpdyConfigOverlay() { |
| if (non_spdy_config_overlay_.get() == nullptr) { |
| non_spdy_config_overlay_ = |
| std::make_unique<ApacheConfig>("non_spdy_overlay", thread_system()); |
| // See ::SpdyConfigOverlay for explanation. |
| non_spdy_config_overlay_->SetDefaultRewriteLevel(global_config()->level()); |
| } |
| return non_spdy_config_overlay_.get(); |
| } |
| |
| void ApacheServerContext::CollapseConfigOverlaysAndComputeSignatures() { |
| // These days we ignore the spdy overlay and merge-in the non-spdy one |
| // unconditionally. |
| if (non_spdy_config_overlay_.get() != nullptr) { |
| global_config()->Merge(*non_spdy_config_overlay_); |
| } |
| |
| SystemServerContext::CollapseConfigOverlaysAndComputeSignatures(); |
| |
| spdy_config_overlay_.reset(); |
| non_spdy_config_overlay_.reset(); |
| } |
| |
| bool ApacheServerContext::PoolDestroyed() { |
| DCHECK_EQ(num_active_rewrite_drivers(), 0); |
| return apache_factory_->PoolDestroyed(this); |
| } |
| |
| void ApacheServerContext::InitProxyFetchFactory() { |
| proxy_fetch_factory_ = std::make_unique<ProxyFetchFactory>(this); |
| } |
| |
| ApacheRequestContext* ApacheServerContext::NewApacheRequestContext( |
| request_rec* request) { |
| return new ApacheRequestContext(thread_system()->NewMutex(), timer(), |
| request); |
| } |
| |
| void ApacheServerContext::ReportNotFoundHelper(MessageType message_type, |
| StringPiece error_message, |
| request_rec* request, |
| Variable* error_count) { |
| error_count->Add(1); |
| request->status = HttpStatus::kNotFound; |
| ap_send_error_response(request, 0); |
| message_handler()->Message( |
| message_type, "%s %s: not found (404)", |
| (error_message.empty() ? "(null)" : error_message.as_string().c_str()), |
| error_count->GetName().as_string().c_str()); |
| } |
| |
| GoogleString ApacheServerContext::FormatOption(StringPiece option_name, |
| StringPiece args) { |
| return StrCat("ModPagespeed", option_name, " ", args); |
| } |
| |
| void ApacheServerContext::ChildInit(SystemRewriteDriverFactory* f) { |
| if (global_config()->proxy_all_requests_mode()) { |
| apache_factory_->SetNeedSchedulerThread(); |
| if (global_config()->measurement_proxy_mode()) { |
| measurement_url_namer_ = std::make_unique<MeasurementProxyUrlNamer>( |
| global_config()->measurement_proxy_root(), |
| global_config()->measurement_proxy_password()); |
| set_url_namer(measurement_url_namer_.get()); |
| SetRewriteOptionsManager(new MeasurementProxyRewriteOptionsManager( |
| this, global_config()->measurement_proxy_root(), |
| global_config()->measurement_proxy_password())); |
| } |
| } |
| SystemServerContext::ChildInit(f); |
| } |
| |
| } // namespace net_instaweb |