loopback-routing: apply session fetchers

Makes sure we use the LoopbackRouteFetcher, and also wires up AddHeadersFetcher.

Note that this pulls in loopback_route_fetcher.cc from svn revision r2649

The LoopbackRouteFetcher is applied unconditionally, while in mod_pagespeed it
is not applied when one of these configuration settings is true:

* disable_loopback_routing
* slurping_enabled, or
* test_proxy is set

I added a TODO for that.

(Sqash-merge of Otto's #193.)
This commit is contained in:
Jeff Kaufman
2013-03-28 10:29:24 -04:00
parent 24787567b6
commit 057038d20f
13 changed files with 543 additions and 23 deletions
+3
View File
@@ -137,6 +137,9 @@ if [ $ngx_found = yes ]; then
$ps_src/ngx_thread_system.cc \
$ps_src/ngx_message_handler.cc \
$ps_src/pthread_shared_mem.cc \
$ps_src/ngx_request_context.cc \
$ps_src/add_headers_fetcher.cc \
$ps_src/loopback_route_fetcher.cc \
$mod_pagespeed_dir/net/instaweb/apache/serf_url_async_fetcher.cc"
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
CORE_LIBS="$CORE_LIBS $pagespeed_libs"
@@ -15,7 +15,8 @@
// Author: morlovich@google.com (Maksim Orlovich)
//
// This fetcher routes requests to hosts that are not explicitly mentioned in
// the DomainLawyer via the loopback.
// the DomainLawyer towards our own IP, as extracted from the incoming
// connection.
#ifndef NET_INSTAWEB_APACHE_LOOPBACK_ROUTE_FETCHER_H_
#define NET_INSTAWEB_APACHE_LOOPBACK_ROUTE_FETCHER_H_
@@ -36,12 +37,14 @@ class MessageHandler;
class LoopbackRouteFetcher : public UrlAsyncFetcher {
public:
// Does not take ownership of anything. own_port is the port the incoming
// request came in on. If the backend_fetcher does actual fetching (and is
// not merely simulating it for testing purposes) it should be the Serf
// fetcher, as others may not direct requests this class produces properly.
// (As this fetcher may produce requests that need to connect to 127.0.0.1
// request came in on, and own_ip is the same for the IP. If the
// backend_fetcher does actual fetching (and is not merely simulating it for
// testing purposes) it should be the Serf fetcher, as others may not direct
// requests this class produces properly.
// (As this fetcher may produce requests that need to connect to some IP
// but have a Host: and URL from somewhere else).
LoopbackRouteFetcher(const RewriteOptions* options,
const GoogleString& own_ip,
int own_port,
UrlAsyncFetcher* backend_fetcher);
virtual ~LoopbackRouteFetcher();
@@ -59,6 +62,7 @@ class LoopbackRouteFetcher : public UrlAsyncFetcher {
private:
const RewriteOptions* const options_;
GoogleString own_ip_;
int own_port_;
UrlAsyncFetcher* const backend_fetcher_;
+2
View File
@@ -58,6 +58,8 @@ rsync -arvz "$MOD_PAGESPEED_SRC/" "psol/include/" --prune-empty-dirs \
--include="apr_mem_cache.cc" \
--include="key_value_codec.cc" \
--include="apr_memcache2.c" \
--include="loopback_route_fetcher.cc" \
--include="add_headers_fetcher.cc" \
--exclude='*'
git add psol/include/
+43
View File
@@ -0,0 +1,43 @@
// Copyright 2012 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: jefftk@google.com (Jeff Kaufman)
#include "add_headers_fetcher.h"
#include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/http/public/request_headers.h"
namespace net_instaweb {
AddHeadersFetcher::AddHeadersFetcher(const RewriteOptions* options,
UrlAsyncFetcher* backend_fetcher)
: options_(options), backend_fetcher_(backend_fetcher) {
}
AddHeadersFetcher::~AddHeadersFetcher() {}
void AddHeadersFetcher::Fetch(const GoogleString& original_url,
MessageHandler* message_handler,
AsyncFetch* fetch) {
RequestHeaders* request_headers = fetch->request_headers();
for (int i = 0, n = options_->num_custom_fetch_headers(); i < n; ++i) {
const RewriteOptions::NameValue* nv = options_->custom_fetch_header(i);
request_headers->Replace(nv->name, nv->value);
}
backend_fetcher_->Fetch(original_url, message_handler, fetch);
}
} // namespace net_instaweb
+57
View File
@@ -0,0 +1,57 @@
// Copyright 2012 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: jefftk@google.com (Jeff Kaufman)
// This class is a simple wrapper around another fetcher that adds headers to
// requests based on settings in the rewrite options before passing them on to
// the backend fetcher.
#ifndef NET_INSTAWEB_APACHE_ADD_HEADERS_FETCHER_H_
#define NET_INSTAWEB_APACHE_ADD_HEADERS_FETCHER_H_
#include "net/instaweb/http/public/url_async_fetcher.h"
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/util/public/string.h"
namespace net_instaweb {
class AsyncFetch;
class RewriteOptions;
class MessageHandler;
class AddHeadersFetcher : public UrlAsyncFetcher {
public:
AddHeadersFetcher(const RewriteOptions* options,
UrlAsyncFetcher* backend_fetcher);
virtual ~AddHeadersFetcher();
virtual bool SupportsHttps() const {
return backend_fetcher_->SupportsHttps();
}
virtual void Fetch(const GoogleString& url,
MessageHandler* message_handler,
AsyncFetch* callback);
private:
const RewriteOptions* const options_;
UrlAsyncFetcher* const backend_fetcher_;
DISALLOW_COPY_AND_ASSIGN(AddHeadersFetcher);
};
} // namespace net_instaweb
#endif // NET_INSTAWEB_APACHE_ADD_HEADERS_FETCHER_H_
+145
View File
@@ -0,0 +1,145 @@
// Copyright 2012 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)
#include "loopback_route_fetcher.h"
#include "base/logging.h"
#include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/meta_data.h"
#include "net/instaweb/http/public/request_headers.h"
#include "net/instaweb/http/public/url_async_fetcher.h"
#include "net/instaweb/rewriter/public/domain_lawyer.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/util/public/google_url.h"
#include "net/instaweb/util/public/string.h"
#include "net/instaweb/util/public/string_util.h"
#include "apr_network_io.h"
namespace net_instaweb {
class MessageHandler;
LoopbackRouteFetcher::LoopbackRouteFetcher(
const RewriteOptions* options,
const GoogleString& own_ip,
int own_port,
UrlAsyncFetcher* backend_fetcher)
: options_(options),
own_ip_(own_ip),
own_port_(own_port),
backend_fetcher_(backend_fetcher) {
if (own_ip_.empty()) {
own_ip_ = "127.0.0.1";
}
}
LoopbackRouteFetcher::~LoopbackRouteFetcher() {
}
void LoopbackRouteFetcher::Fetch(const GoogleString& original_url,
MessageHandler* message_handler,
AsyncFetch* fetch) {
GoogleString url = original_url;
GoogleUrl parsed_url(original_url);
if (!parsed_url.is_valid()) {
// Fail immediately in case we can't parse the URL, rather than risk
// getting weird handling due to inconsistencies in parsing between us
// and backend_fetcher_.
LOG(WARNING) << "Can't parse URL:" << original_url;
fetch->Done(false);
return;
}
RequestHeaders* request_headers = fetch->request_headers();
// Check to see if the URL we hand to the backend has an origin we were never
// explicitly told of, and if so just talk to loopback.
// Note that in case of an origin mapping the parsed_url will contain the
// fetch host, not the original host, so the domain_lawyer will know about it
// and the if body will not run.
if (!options_->domain_lawyer()->IsOriginKnown(parsed_url)) {
// If there is no host header, make sure to add one, since we are about
// to munge the URL.
if (request_headers->Lookup1(HttpAttributes::kHost) == NULL) {
request_headers->Replace(HttpAttributes::kHost, parsed_url.HostAndPort());
}
GoogleUrl base;
StringPiece scheme = parsed_url.Scheme();
if ((own_port_ == 80 && scheme == "http") ||
(own_port_ == 443 && scheme == "https")) {
base.Reset(StrCat(scheme, "://", own_ip_, "/"));
} else {
base.Reset(
StrCat(scheme, "://", own_ip_, ":", IntegerToString(own_port_), "/"));
}
GoogleString rel;
parsed_url.PathAndLeaf().CopyToString(&rel);
parsed_url.Reset(base, rel);
parsed_url.Spec().CopyToString(&url);
// Note that we end up with host: containing the actual URL's host, but
// the URL containing just our IP. This is technically wrong, but the
// Serf fetcher will interpret it in the way we want it to --- it will
// connect to our IP, pass only the path portion to the host, and
// keep the host: header matching what's in the request_headers.
}
backend_fetcher_->Fetch(url, message_handler, fetch);
}
bool LoopbackRouteFetcher::IsLoopbackAddr(const apr_sockaddr_t* addr) {
if (addr->family == APR_INET) {
// 127.0.0.0/8 is the IPv4 loopback.
// Note: is network byte order, so we can do char-wide indexing into it
// consistently (but not look at the whole thing).
const char* ipbytes = reinterpret_cast<const char*>(
&addr->sa.sin.sin_addr.s_addr);
return (ipbytes[0] == 127);
} else if (addr->family == APR_INET6) {
const in6_addr& addr_v6 = addr->sa.sin6.sin6_addr;
// There are a couple of ways we can see loopbacks in IPv6: as the
// proper IPv6 loopback, ::1, or as "IPv4-compatible IPv6 address"
// of the IPv4 loopback, ::FFFF:127.x.y.z.
// Regardless, the first 10 bytes ought to be 0.
for (int b = 0; b < 10; ++b) {
if (addr_v6.s6_addr[b] != 0) {
return false;
}
}
// If first 10 are OK, check the last 6 bytes for the 2 options.
return (addr_v6.s6_addr[10] == 0xFF &&
addr_v6.s6_addr[11] == 0xFF &&
addr_v6.s6_addr[12] == 127) ||
(addr_v6.s6_addr[10] == 0 &&
addr_v6.s6_addr[11] == 0 &&
addr_v6.s6_addr[12] == 0 &&
addr_v6.s6_addr[13] == 0 &&
addr_v6.s6_addr[14] == 0 &&
addr_v6.s6_addr[15] == 1);
} else {
return false;
}
}
} // namespace net_instaweb
+74
View File
@@ -0,0 +1,74 @@
// Copyright 2012 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 fetcher routes requests to hosts that are not explicitly mentioned in
// the DomainLawyer towards our own IP, as extracted from the incoming
// connection.
#ifndef NET_INSTAWEB_APACHE_LOOPBACK_ROUTE_FETCHER_H_
#define NET_INSTAWEB_APACHE_LOOPBACK_ROUTE_FETCHER_H_
#include "net/instaweb/http/public/url_async_fetcher.h"
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/util/public/string.h"
struct apr_sockaddr_t;
namespace net_instaweb {
class AsyncFetch;
class RewriteOptions;
class MessageHandler;
// See file comment.
class LoopbackRouteFetcher : public UrlAsyncFetcher {
public:
// Does not take ownership of anything. own_port is the port the incoming
// request came in on, and own_ip is the same for the IP. If the
// backend_fetcher does actual fetching (and is not merely simulating it for
// testing purposes) it should be the Serf fetcher, as others may not direct
// requests this class produces properly.
// (As this fetcher may produce requests that need to connect to some IP
// but have a Host: and URL from somewhere else).
LoopbackRouteFetcher(const RewriteOptions* options,
const GoogleString& own_ip,
int own_port,
UrlAsyncFetcher* backend_fetcher);
virtual ~LoopbackRouteFetcher();
virtual bool SupportsHttps() const {
return backend_fetcher_->SupportsHttps();
}
virtual void Fetch(const GoogleString& url,
MessageHandler* message_handler,
AsyncFetch* fetch);
// Returns true if the given address is an IPv4 or IPv6 loopback.
static bool IsLoopbackAddr(const apr_sockaddr_t* addr);
private:
const RewriteOptions* const options_;
GoogleString own_ip_;
int own_port_;
UrlAsyncFetcher* const backend_fetcher_;
DISALLOW_COPY_AND_ASSIGN(LoopbackRouteFetcher);
};
} // namespace net_instaweb
#endif // NET_INSTAWEB_APACHE_LOOPBACK_ROUTE_FETCHER_H_
+6 -18
View File
@@ -37,6 +37,7 @@ extern "C" {
#include "ngx_base_fetch.h"
#include "ngx_message_handler.h"
#include "ngx_request_context.h"
#include "ngx_rewrite_driver_factory.h"
#include "ngx_rewrite_options.h"
#include "ngx_server_context.h"
@@ -286,20 +287,6 @@ typedef struct {
net_instaweb::MessageHandler* handler;
} ps_loc_conf_t;
typedef struct {
net_instaweb::ProxyFetch* proxy_fetch;
net_instaweb::NgxBaseFetch* base_fetch;
net_instaweb::RewriteDriver* driver;
bool data_received;
int pipe_fd;
ngx_connection_t* pagespeed_connection;
ngx_http_request_t* r;
bool is_resource_fetch;
bool sent_headers;
bool write_pending;
net_instaweb::GzipInflater* inflater_;
} ps_request_ctx_t;
ngx_int_t ps_body_filter(ngx_http_request_t* r, ngx_chain_t* in);
void* ps_create_srv_conf(ngx_conf_t* cf);
@@ -1262,8 +1249,8 @@ CreateRequestContext::Response ps_create_request_context(
// the BaseFetch ourselves.
ctx->base_fetch = new net_instaweb::NgxBaseFetch(
r, file_descriptors[1],
net_instaweb::RequestContextPtr(new net_instaweb::RequestContext(
cfg_s->server_context->thread_system()->NewMutex())));
net_instaweb::RequestContextPtr(new net_instaweb::NgxRequestContext(
cfg_s->server_context->thread_system()->NewMutex(), ctx)));
// If null, that means use global options.
net_instaweb::RewriteOptions* custom_options = NULL;
@@ -1965,11 +1952,12 @@ ps_beacon_handler(ngx_http_request_t* r) {
user_agent = str_to_string_piece(r->headers_in.user_agent->value);
}
ps_request_ctx_t* ctx = ps_get_request_context(r);
cfg_s->server_context->HandleBeacon(
str_to_string_piece(r->unparsed_uri),
user_agent,
net_instaweb::RequestContextPtr(new net_instaweb::RequestContext(
cfg_s->server_context->thread_system()->NewMutex())));
net_instaweb::RequestContextPtr(new net_instaweb::NgxRequestContext(
cfg_s->server_context->thread_system()->NewMutex(), ctx)));
return NGX_HTTP_NO_CONTENT;
}
+23
View File
@@ -27,6 +27,15 @@ extern "C" {
#include "net/instaweb/http/public/response_headers.h"
#include "net/instaweb/util/public/string_util.h"
namespace net_instaweb {
class GzipInflater;
class NgxBaseFetch;
class ProxyFetch;
class RewriteDriver;
} // namespace net_instaweb
namespace ngx_psol {
// Allocate chain links and buffers from the supplied pool, and copy over the
@@ -60,6 +69,20 @@ ngx_int_t copy_response_headers_to_ngx(
ngx_http_request_t* r,
const net_instaweb::ResponseHeaders& pagespeed_headers);
typedef struct {
net_instaweb::ProxyFetch* proxy_fetch;
net_instaweb::NgxBaseFetch* base_fetch;
net_instaweb::RewriteDriver* driver;
bool data_received;
int pipe_fd;
ngx_connection_t* pagespeed_connection;
ngx_http_request_t* r;
bool is_resource_fetch;
bool sent_headers;
bool write_pending;
net_instaweb::GzipInflater* inflater_;
} ps_request_ctx_t;
} // namespace ngx_psol
#endif // NGX_PAGESPEED_H_
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright 2013 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.
*/
#include "ngx_request_context.h"
extern "C" {
#include <ngx_http.h>
}
#include "ngx_pagespeed.h"
#include "base/logging.h"
#include "net/instaweb/http/public/meta_data.h"
namespace net_instaweb {
NgxRequestContext::NgxRequestContext(AbstractMutex* logging_mutex,
ngx_psol::ps_request_ctx_t* ps_request_ctx)
: RequestContext(logging_mutex),
local_port_(-1) {
// Note that at the time we create a RequestContext we have full
// access to the nginx internal request structure. However,
// due to Cloning and (I believe) Detaching, we can initiate fetches after
// http_http_request_t* has been retired. So deep-copy the bits we need
// at the time we create our RequestContext.
// Save our own IP as well, LoopbackRouteFetcher will need it.
// Based on ngx_http_variable_server_port.
ngx_http_request_t* req = ps_request_ctx->r;
bool port_set = false;
#if (NGX_HAVE_INET6)
if (req->connection->local_sockaddr->sa_family == AF_INET6) {
local_port_ = ntohs(reinterpret_cast<struct sockaddr_in6*>(
req->connection->local_sockaddr)->sin6_port);
port_set = true;
}
#endif
if (!port_set) {
local_port_ = ntohs(reinterpret_cast<struct sockaddr_in*>(
req->connection->local_sockaddr)->sin_port);
}
ngx_str_t s;
u_char addr[NGX_SOCKADDR_STRLEN];
s.len = NGX_SOCKADDR_STRLEN;
s.data = addr;
ngx_int_t rc = ngx_connection_local_sockaddr(req->connection, &s, 0);
if (rc != NGX_OK) {
s.len = 0;
}
local_ip_ = ngx_psol::str_to_string_piece(s).as_string();
}
NgxRequestContext::~NgxRequestContext() {
}
NgxRequestContext* NgxRequestContext::DynamicCast(RequestContext* rc) {
if (rc == NULL) {
return NULL;
}
NgxRequestContext* out = dynamic_cast<NgxRequestContext*>(rc);
DCHECK(out != NULL) << "Invalid request conversion. Do not rely on RTTI for "
<< "functional behavior. Ngx handling flows must use "
<< "NgxRequestContexts.";
return out;
}
} // namespace net_instaweb
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright 2013 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: oschaaf@google.com (Otto van der Schaaf)
//
// I tried to keep this as close to ApacheRequestContext as possible.
// Captures the NGINX request details in our request context, including
// the port (used for loopback fetches).
#ifndef NGX_REQUEST_CONTEXT_H_
#define NGX_REQUEST_CONTEXT_H_
#include "ngx_pagespeed.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/util/public/string.h"
#include "net/instaweb/util/public/string_util.h"
namespace net_instaweb {
class AbstractMutex;
class NgxRequestContext : public RequestContext {
public:
NgxRequestContext(AbstractMutex* logging_mutex,
ngx_psol::ps_request_ctx_t* ps_request_context);
// Returns rc as an NgxRequestContext* if it is one and CHECK
// fails if it is not. Returns NULL if rc is NULL.
static NgxRequestContext* DynamicCast(RequestContext* rc);
int local_port() const { return local_port_; }
const GoogleString& local_ip() const { return local_ip_; }
protected:
virtual ~NgxRequestContext();
private:
int local_port_;
GoogleString local_ip_;
DISALLOW_COPY_AND_ASSIGN(NgxRequestContext);
};
} // namespace net_instaweb
#endif // NGX_REQUEST_CONTEXT_H_
+35
View File
@@ -18,10 +18,16 @@
#include "ngx_server_context.h"
#include "ngx_request_context.h"
#include "ngx_rewrite_options.h"
#include "ngx_rewrite_driver_factory.h"
// TODO(oschaaf): next time we update the binaries, we can drop our own
// versions of add_headers_fetcher and loopback_route_fetcher
#include "add_headers_fetcher.h"
#include "loopback_route_fetcher.h"
#include "net/instaweb/system/public/system_caches.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_stats.h"
#include "net/instaweb/util/public/shared_mem_statistics.h"
#include "net/instaweb/util/public/split_statistics.h"
@@ -105,4 +111,33 @@ void NgxServerContext::InitStats(Statistics* statistics) {
// initialise UrlAsyncFetcherStats here
}
void NgxServerContext::ApplySessionFetchers(
const RequestContextPtr& request, RewriteDriver* driver) {
const NgxRewriteOptions* conf = NgxRewriteOptions::DynamicCast(
driver->options());
CHECK(conf != NULL);
NgxRequestContext* ngx_request = NgxRequestContext::DynamicCast(
request.get());
if (ngx_request == NULL) {
return; // decoding_driver has a null RequestContext.
}
// Note that these fetchers are applied in the opposite order of how they are
// added
// TODO(oschaaf): in mod_pagespeed, LoopbackRouteFetcher is not added when
// one of these is set: disable_loopback_routing, slurping_enabled, or
// test_proxy.
// Note the port here is our port, not from the request, since
// LoopbackRouteFetcher may decide we should be talking to ourselves.
driver->SetSessionFetcher(new LoopbackRouteFetcher(
driver->options(), ngx_request->local_ip(),
ngx_request->local_port(), driver->async_fetcher()));
if (driver->options()->num_custom_fetch_headers() > 0) {
driver->SetSessionFetcher(new AddHeadersFetcher(driver->options(),
driver->async_fetcher()));
}
}
} // namespace net_instaweb
+2
View File
@@ -50,6 +50,8 @@ class NgxServerContext : public ServerContext {
// ::Initialize called on it.
void CreateLocalStatistics(Statistics* global_statistics);
static void InitStats(Statistics* statistics);
virtual void ApplySessionFetchers(const RequestContextPtr& req,
RewriteDriver* driver);
bool initialized() const { return initialized_; }
GoogleString hostname_identifier() { return hostname_identifier_; }
void set_hostname_identifier(GoogleString x) { hostname_identifier_ = x; }