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:
@@ -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_;
|
||||
|
||||
|
||||
@@ -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/
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user