Compare commits

...

482 Commits

Author SHA1 Message Date
Jeff Kaufman 6865525deb 1.10.32.2 -> 1.10.32.4 2016-02-02 13:53:29 -05:00
Jeff Kaufman cd8c45fc86 1.10.33.1 -> 1.10.33.2 2015-12-18 15:04:42 -05:00
Jeff Kaufman 9d6bfad665 Restore dropped fix for #957
@rfnx fixed #957 in acb89a, but this was accidentally merged to master
instead of trunk-tracking.  I checked for this sort of problem as part
of the 1.10 release, but missed this commit.  Restored.

Fixes #1054
2015-12-18 15:04:42 -05:00
Otto van der Schaaf c253c3ba80 log: initialize logging earlier
It turns out to be possible to initialize logging earlier by
grabbing the log from a global ngx_cycle structure.

This makes us start logging earlier, yet loses the
"No threading detected ..." messages both from stderr and
in error.log when nginx initially starts.

With this change, these messages will now be logged as we start
logging earlier:

"
flush
.
"

These originate from SystemCachePath::CacheKey which appends
newlines to the key, and the resulting cache key ends up being
logged. We might want to change that, because the resulting
lines in error.log look weird and might raise questions.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/895
2015-12-17 17:18:18 -05:00
Jeff Kaufman 8c7c8a843a 1.10.33.0 -> 1.10.33.1 2015-12-16 08:13:40 -05:00
Jeff Kaufman bcb1eb1dec release: version 1.9 -> 1.10 2015-12-14 08:27:41 -05:00
Jeffrey Crowell df498ea788 Merge pull request #1067 from pagespeed/crowell-fix-gcc5
add flags for new GCC on config tests
2015-12-10 15:45:47 -05:00
Jeffrey Crowell 4b4d353156 add flags for new GCC on config tests
closes #1066
2015-12-10 15:41:44 -05:00
Maks Orlovich c9d4912746 Merge pull request #1050 from pagespeed/morlovich-compiler-req
Add compiler version checks for what we want to support going forward.

Also make us actually build with clang (the log_message_handler.cc change
and config.make change)
2015-12-09 14:50:11 -05:00
Maks Orlovich f1a6cd0ade Whitespace tweak 2015-12-07 10:01:23 -05:00
Joshua Marantz 0c01c0644e Merge pull request #1057 from pagespeed/jmarantz-2-pass-ipro
suppress errors on new 2-pass and 3-pass ipro tests
2015-12-02 16:45:48 -05:00
Joshua Marantz 14aa4fd962 suppress errors on new 2-pass and 3-pass ipro tests 2015-12-02 15:01:37 -05:00
Joshua Marantz 36a7ff9543 Merge pull request #1056 from pagespeed/jmarantz-no-error-on-slow-ReadFile
do not consider it a test failure to get a slow ReadFile operation.
2015-12-02 08:31:34 -05:00
Joshua Marantz 706577a34b do not consider it a test failure to get a slow ReadFile operation. 2015-12-02 08:27:47 -05:00
Otto van der Schaaf 6703b2d76e Merge pull request #1055 from pagespeed/oschaaf-trunk-tracking-location-header-handling
location-header: Be careful with headers_out->location
2015-12-01 18:56:53 +01:00
Otto van der Schaaf 40c05b4a4f location-header: Be careful with headers_out->location
Only set headers_out->location when the upstream originally did
as well. If the Location: header value involved starts with "/"
nginx will absolutify it, ignoring any X-Forwarded-Proto header
in the process.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/819
(Confirmed: https://github.com/pagespeed/ngx_pagespeed/issues/1029)
Hopefully fixes https://github.com/pagespeed/ngx_pagespeed/issues/711
2015-12-01 18:55:02 +01:00
Maks Orlovich bc875647f1 Add compiler version checks for what we want to support going forward,
and make us actually build with clang (the log_message_handler.cc change
and config.make change)
2015-11-25 13:44:13 -05:00
Maks Orlovich f88a0763fd Merge pull request #1048 from pagespeed/morlovich-buildflag
Pass in -D_GLIBCXX_USE_CXX11_ABI=0, so people using gcc-5.x can use our psol.a
2015-11-25 08:56:16 -05:00
Maks Orlovich 239ca9aa80 Pass in -D_GLIBCXX_USE_CXX11_ABI=0, so people using gcc-5.x can use psol.a
we built with 4.8

See issue 942
2015-11-24 15:16:06 -05:00
Jeff Kaufman 37c51d3b9e Merge pull request #1042 from pagespeed/jefftk-content-experiment
Add ContentExperiment support
2015-11-24 11:46:04 -05:00
Jeff Kaufman 2468257e2d Add ContentExperiment support 2015-11-20 16:39:02 -05:00
Jeff Kaufman 4628e1c0ea Merge pull request #1035 from pagespeed/jefftk-script-var-testing
Support script variables in ShardDomain
2015-11-19 11:01:41 -08:00
Jeff Kaufman 7f98ab448b Merge pull request #1047 from pagespeed/jefftk-ngx-brotli
Fix interaction with ngx_brotli module.
2015-11-18 11:20:17 -08:00
Piotr Sikora 103c479fbb Fix interaction with ngx_brotli module.
Reported by George Liu (eva2000) on GitHub (issue #1021).

Signed-off-by: Piotr Sikora <piotrsikora@google.com>

Conflicts:
	config
2015-11-16 18:26:30 -05:00
Jeffrey Crowell 887bd8fa98 Merge pull request #1046 from pagespeed/crowell_content_encoding
add content_encoding to headers_out
2015-11-16 11:09:04 -05:00
Jeffrey Crowell 804f234268 add remaining shortcuts to headers_out_t
this change is required for gzip cache change going into mod_pagespeed.
2015-11-16 10:56:23 -05:00
Jeff Kaufman ea82f0de19 Support script variables in ShardDomain 2015-11-02 10:08:00 -05:00
Jeff Kaufman 5f312820e5 Merge pull request #974 from pagespeed/jefftk-handler-restrictions
Add support for blocking access to our handlers.
2015-11-02 08:18:10 -05:00
Jeff Kaufman 7efac4ac4e Merge pull request #1028 from pagespeed/oschaaf-trunk-tracking-issue-1015
IPRO+MPD: Make In-Place-Resource-Optimization with MapProxyDomain work
2015-10-28 13:30:04 -04:00
Otto van der Schaaf 634b813071 IPRO+MPD: Make In-Place-Resource-Optimization with MapProxyDomain work
Fixes https://github.com/pagespeed/ngx_pagespeed/issues/1015

Pull with MPS Side for this change:
https://github.com/pagespeed/mod_pagespeed/pull/1161
2015-10-27 18:11:35 +01:00
Joshua Marantz d30972985b Merge pull request #1026 from pagespeed/jmarantz-remove-set-ua
Don't call RewriteDriver::SetUserAgent on the UA in the request-headers.
2015-10-22 15:17:15 -04:00
Joshua Marantz 3a6e833eae Don't call RewriteDriver::SetUserAgent on the UA in the request-headers.
RewriteDriver::SetRequestHeaders already pulls the UA from the request-headers.
2015-10-22 14:19:00 -04:00
Joshua Marantz 90c8ac8a12 Revert "Don't call RewriteDriver::SetUserAgent as the user-agent is already in the request-headers"
This reverts commit 6ccc1c513b.
2015-10-22 14:13:01 -04:00
Joshua Marantz 6ccc1c513b Don't call RewriteDriver::SetUserAgent as the user-agent is already in the request-headers 2015-10-22 13:20:00 -04:00
Jeff Kaufman fe47eeb4f3 Add support for blocking access to our handlers.
Nginx side of the fix for https://github.com/pagespeed/mod_pagespeed/issues/1088
2015-09-18 09:03:01 -04:00
Joshua Marantz e42f61e263 Merge pull request #1002 from pagespeed/jmarantz-log-slow-file-ops
ignore errors about slow file operations
2015-07-31 17:01:39 -04:00
Joshua Marantz 8bac32c669 ignore errors about slow file operations, which can occur when running valgrind tests 2015-07-31 16:57:20 -04:00
Jeffrey Crowell 4bef2af22c Merge pull request #995 from pagespeed/crowell-disable-sendfile
add test servers for sending x-sendfile and x-accel-redirect
2015-07-23 17:34:58 -04:00
Jeffrey Crowell 52bd966edd add test servers for sending x-sendfile and x-accel-redirect 2015-07-23 13:34:25 -04:00
Jeff Kaufman 0f7a1f4503 Merge pull request #994 from pagespeed/jefftk-allow-script-variables
config: whitelist a few more directives for script variables
2015-07-23 10:36:57 -04:00
Jeff Kaufman 7f477d6575 config: whitelist a few more directives for script variables
When configuring downstream caching if you have an origin with multiple caches in front of it you might want to choose how you handle requests in response to which cache you're getting them from.  Whitelist DownstreamCachePurgeLocationPrefix, DownstreamCachePurgeMethod, and DownstreamCacheRewrittenPercentageThreshold for scripting so this is possible.
2015-07-22 10:32:41 -04:00
Jan-Willem Maessen cc10f15f53 Fix pagespeed_libraries_generator.sh to fetch pagespeed_libraries.conf from github rather than svn. 2015-07-09 10:18:51 -04:00
Jeffrey Crowell 9ee745c2ef Revert "temporarily comment tests using modpagespeed.com"
This reverts commit 5337e4b558.

closes #984
2015-07-07 13:15:33 -04:00
Jeffrey Crowell 5337e4b558 temporarily comment tests using modpagespeed.com
revert this commit when modpagespeed.com is back up
2015-07-06 12:36:44 -04:00
jmarantz b31bf7b090 Merge pull request #967 from pagespeed/jmarantz-psoff-dir-on
nginx system test changes to repro issue https://github.com/pagespeed…
2015-05-19 11:12:14 -04:00
Joshua Marantz 8464a00a77 nginx system test changes to repro issue https://github.com/pagespeed/mod_pagespeed/issues/1077 2015-05-18 09:46:12 -04:00
Jeff Kaufman b048ceb858 Merge pull request #966 from pagespeed/jefftk-doneandsetheaders
Handle DoneAndSetHeaders() new second argument that wants to know whe…
2015-05-15 10:33:32 -04:00
Jeff Kaufman 0fbdf3ee97 Handle DoneAndSetHeaders() new second argument that wants to know whether the response is complete. 2015-05-14 15:26:10 -04:00
Jeffrey Crowell a9d85960b5 add psol tar.gz to gitignore 2015-05-13 11:57:32 -04:00
Jeffrey Crowell cd19284062 initialize uninitialized variables. 2015-04-01 15:45:22 -04:00
Jeffrey Crowell c2a756049e add support for nginx 1.7.11 --with-threads 2015-04-01 15:10:26 -04:00
Maks Orlovich 6b2999dfd4 Merge pull request #944 from pagespeed/morlovich-api-adjust-InitiatePropertyCacheLookup
Adjust to API change to InitiatePropertyCacheLookup
2015-04-01 14:08:33 -04:00
Maks Orlovich 5658c20327 Adjust to API change to InitiatePropertyCacheLookup
The last argument was not actually used, and hence was removed.
2015-03-30 17:02:58 -04:00
Jeffrey Crowell ec2dea84fe Merge pull request #943 from pagespeed/crowell-rm_unused_variable
move 'type' variable to inside an #if statement
2015-03-30 14:34:48 -04:00
Jeffrey Crowell e206e871aa move 'type' variable to inside an #if statement
removes an unused variable when compile without NGX_DEBUG, allows for
building with -Werror.
2015-03-30 14:33:33 -04:00
Jeff Kaufman f4fd9a3f7c Merge pull request #935 from pagespeed/jefftk-system-public
system/public/ was moved to system/, update our references.
2015-03-18 17:04:21 -07:00
Jeff Kaufman cf88925f1e system/public/ was moved to system/, update our references. 2015-03-13 14:38:16 -04:00
Jeff Kaufman 5ea8fb9f3e Merge pull request #934 from pagespeed/jefftk-automatic-moved
Moved `automatic/` into `pagespeed/` and got rid of the `public/` hierarchy.
2015-03-13 10:44:08 -04:00
Jeff Kaufman cd31a6b129 Move automatic/public to automatic/. 2015-03-13 09:59:52 -04:00
Jeff Kaufman 137792e88f Change references from net/instaweb/automatic to pagespeed/automatic. 2015-03-13 09:30:14 -04:00
Jeffrey Crowell 91cd587e68 Merge pull request #932 from pagespeed/crowell_rm-test-grep
rm "unexpected response" grep from system test
2015-03-05 14:42:05 -05:00
Otto van der Schaaf e9608b03b7 Merge pull request #931 from pagespeed/oschaaf-trunk-tracking-native-fetcher-more-fixes
native-fetcher: fixes
2015-03-05 20:35:21 +01:00
Jeffrey Crowell 6e1a9a73a5 rm "unexpected response" grep from system test 2015-03-05 14:02:55 -05:00
Otto van der Schaaf 3875acf392 native-fetcher: fixes
- Native fetching broke in https://github.com/pagespeed/ngx_pagespeed/pull/925
  Make changes so we can do early-stage fetches in the startup process
  to fix that.
- Properly cancel out any pending fetches upon ShutDown()
- Decline fetching after ShutDown(), decline fetching when Init()
  failed.
2015-03-05 14:43:29 +01:00
Jeffrey Crowell 4dd70b40ef Merge pull request #925 from pagespeed/crowell_rconfig
Port remote configuration option to nginx.
2015-03-04 13:26:04 -05:00
Jeffrey Crowell 88d9b5241d Merge remote-tracking branch 'origin/trunk-tracking' into crowell_rconfig 2015-02-25 16:47:48 -05:00
Otto van der Schaaf 23905f8ce9 Merge pull request #922 from pagespeed/oschaaf-trunk-tracking-native-fetcher-fixes
native-fetcher: fix a few bugs
2015-02-25 21:13:02 +01:00
Otto van der Schaaf effe857083 native-fetcher: Fix a few bugs
- Add handling for header only responses
- Fixup nginx i/o handling
- Fix issues in parser state
- Revert timeout for native fetcher dns resolve to 10 seconds
- Ignore warning that gets logged with this change in tests during
  fetching from a host that refuses connections.

Should help stabilizing (valgrind) test runs some more.
2015-02-25 21:03:01 +01:00
Jeffrey Crowell 599a3bca5c update to match apache for hostnames 2015-02-24 17:36:08 -05:00
Jeffrey Crowell c26313e7ab Port remote configuration option to nginx. 2015-02-23 11:25:17 -05:00
Otto van der Schaaf bcba22dd95 Merge pull request #919 from pagespeed/oschaaf-trunk-tracking-native-fetcher-pull-755
Call async_fetch_->Done after all usages.
2015-02-18 13:38:17 +01:00
Otto van der Schaaf 1ea7e3e568 Merge pull request #917 from pagespeed/oschaaf-trunk-tracking-native-fetcher-deflake
native-fetcher: bump dns timeout to deflake running the tests
2015-02-17 21:27:32 +01:00
Jeff Kaufman 34341251f6 Merge pull request #908 from pagespeed/oschaaf-trunk-tracking-shutdown-system-test-failure
shutdown: fix system test failure in error.log sanity check
2015-02-17 13:28:56 -05:00
Vasily Chekalkin d1f2a43a71 Call async_fetch_->Done after all usages.
AsyncFetch::Done will delete itself. Accessing
async_fetch_->extra_respond_headers() will crash nginx.
2015-02-17 12:18:30 +01:00
Otto van der Schaaf 58b1264745 native-fetcher: bump dns timeout to deflake running the tests
Nginx sometimes receives an expected response from 8.8.8.8 when
resolving host names, and the subsequent retry doesn't finish up
in 10 seconds. Bumping the timeout helps, but does not fully
explain why nginx is sometimes receiving an unexpected response.
I'll create a separate issue for investigating that.
2015-02-17 11:05:34 +01:00
Otto van der Schaaf 8b6fdf56ef shutdown: fix system test failure in error.log sanity check
- Should shut down with a clean valgrind and sane logging for the
  current test workload.
- Minor cleanup
2015-02-13 21:00:43 +01:00
Otto van der Schaaf 93d70feb3b Merge pull request #907 from pagespeed/oschaaf-trunk-tracking-test-reload
configuration-reload-test: wait for the new worker to get ready
2015-02-12 20:05:27 +01:00
Otto van der Schaaf 62c8947b2d configuration-reload-test: wait for the new worker to get ready
After sending a SIGHUP, wait for the new worker process with the
new configuration to handle further requests, or else the tests
running after that might get confused when the new worker becomes
active with fresh shared mem statistics and shared mem cache.
2015-02-12 18:08:18 +01:00
Otto van der Schaaf 22749d7222 Merge pull request #906 from pagespeed/oschaaf-trunk-tracking-module-position
module-position: optional switch to install at HTTP_AUX_FILTER_MODULES
2015-02-12 17:09:23 +01:00
Otto van der Schaaf a8141eadd3 module-position: optional switch to install at HTTP_AUX_FILTER_MODULES
This change adds a flag to optionally position the module at HTTP_AUX_FILTER_MODULES
instead of just in front of the gzip module. Doing so allows header module(s) to
fully manipulate any response headers before they are send to the user-agent.
With https://github.com/pagespeed/ngx_pagespeed/pull/880, SSI no longer hangs,
and other modules using subrequests should not do so either. SSI subrequests are
not optimized when ngx_pagespeed runs at HTTP_AUX_FILTER_MODULES, so the test for
it is added to the expected failures when the tests are run for this module position.

To build with the module respositioned:
  POSITION_AUX=true ./configure ......
The same variable can be set before running the system tests, in which case it will
perform additional header tests and add the SSI test to the expected failures.
2015-02-12 16:23:11 +01:00
Otto van der Schaaf 2d28ff38e8 Merge pull request #899 from pagespeed/oschaaf-trunk-tracking-shutdown
trunk-tracking-shutdown: improve shutdown code
2015-02-10 23:52:33 +01:00
Otto van der Schaaf d7f1c0dc48 Shutdown: improve shutdown handling
- Fix valgrind errors
- Add a test to make sure all logged output looks sane by whitelisting
  current errors/warnings.
- Stop our nginx test instances after we are done testing.
- Add tests for shutting down and reloading configuration under high
  load (depends on ab).
- Reduce the number of keepalive requests in the keepalive tests to speed
  up test runs.
- Fix exiting with open file descriptors, fix cleanup in nginx's cache
  manager/loader processes
- Attempt to finish up queued up NgxBaseFetches/requests on shutdown/reload
- Under valgrind the blocking rewrite started failing after adding a test
  for reloading configuration under high load.
  I've added it to the expected failures for valgrind, looking into this
  is up next.
- Decline in ps_resource_handler when nginx is quitting. This makes us
  more reliable on continued stress during shutdown/reload.
2015-02-10 23:13:44 +01:00
Jeffrey Crowell 737e9396f5 Merge pull request #892 from pagespeed/crowell-fix-888
Replace CHECK with return failure and log.
2015-01-30 10:28:04 -05:00
Jeffrey Crowell 81029dafa6 Replace CHECK with return failure and log.
Fixes #888 along with
https://code.google.com/p/modpagespeed/source/detail?r=4533
2015-01-30 10:23:00 -05:00
Otto van der Schaaf 001cd2dc4c Merge pull request #889 from pagespeed/oschaaf-trunk-tracking-content-handler-error-responses
content-handling-errors: fall back to nginx's default handling
2015-01-27 16:50:04 +01:00
Otto van der Schaaf 3efebb7948 content-handling-errors: fall back to nginx's default handling
This change passes on non succesful status codes for pagespeed
resources and other places where we act as a content handler to
nginx. This has two benefits:
- Instead of a blank page, the user agent receives a formatted
  and (hopefully customized and informative) response.
- Header modules are able to operate on that response, which was
  requested in https://github.com/pagespeed/ngx_pagespeed/issues/612#issuecomment-58855816
2015-01-26 22:13:15 +01:00
Otto van der Schaaf 02b67b79ad Merge pull request #885 from pagespeed/oschaaf-trunk-tracking-release-early
Release base fetch early, eliminate write_pending and fetch_done
2015-01-26 16:46:30 +01:00
Otto van der Schaaf d0858790e4 Merge pull request #884 from pagespeed/oschaaf-trunk-tracking-base-fetch
base-fetch: prevent unused constructions and prop. cache lookups
2015-01-23 20:09:45 +01:00
Otto van der Schaaf 4d945b1c59 Release base fetch early, eliminate write_pending and fetch_done
Get rid of write_pending & fetch_done flags on the request context.
Assume that having ctx->base_fetch set means we have outstanding
work and thus we are not done yet, for simplicity.
This also means we'll release the base fetch earlier which seems
like a good idea to me.
2015-01-23 15:07:14 +01:00
Otto van der Schaaf 7d965aced7 Merge pull request #880 from pagespeed/oschaaf-trunk-tracking-run-posted-requests
posted-requests: run posted requests when appropriate
2015-01-21 19:47:13 +01:00
Otto van der Schaaf a5411a1c7c base-fetch: prevent unused constructions and prop. cache lookups
- Don't construct `NgxBaseFetch` instances and call `Done(false)` later when it turns out it wasn't needed.
- Track the purpose of the base fetch instead of just wether it is an IPRO lookup or not for more informational tracing
  as well as avoiding constructing base fetches when their purpose isn't know yet.
- Don't initiate a property cache lookup when we won't need it (`ProxyFetchFactory::InitiatePropertyCacheLookup`)
- Improve IPRO handling of `NgxBaseFetch` and make it clearer. Indicate we want to supress further events when the
  base fetch was used to lookup an IPRO url, and the result was not indicative of something we can respond with to the
  browser.
- Remove unused `RequestRouting` constants
2015-01-20 02:19:47 +01:00
Otto van der Schaaf 8a1260a1d1 posted-requests: run posted requests when appropriate
Request termination code relies on posted requests being run.
One of the things this fixes is that we won't hang when configured
to run before the SSI module.

Avoids trouble when changing the module order, which helps
https://github.com/pagespeed/ngx_pagespeed/issues/612
2015-01-19 10:28:00 +01:00
Otto van der Schaaf f2e7b15d9c Merge pull request #879 from pagespeed/oschaaf-trunk-tracking-server-header
server-header: improve handling of server header
2015-01-17 20:28:34 +01:00
Otto van der Schaaf 5bc61a7092 server-header: improve handling of server header
- Fixes an issue in the html flow that would prevent overriding the
value of the 'Server' response-header.
- Add tests that ensure we emit a single and correct server header
in all flows when not overriding it.
- Add tests that ensure overriding the 'Server' response header
works. The resource and IPRO flow are added to the expected failures
as those are not working yet (and will be adressed in a follow-up).

Fixed https://github.com/pagespeed/ngx_pagespeed/issues/864 (html flow)
2015-01-17 20:27:45 +01:00
Otto van der Schaaf 03819f4e4a Merge pull request #876 from pagespeed/oschaaf-single-fd-fixed
Oschaaf single fd fixed
2015-01-16 15:53:06 +01:00
Otto van der Schaaf 7ef61d2580 base-fetch-leak: Shut down NgxEventConnection before deleting it
Shutdown will drain the pipe and process the last events which
will give nginx the opportunity to run the cleanup handlers on the
associated requests.
2015-01-10 22:45:04 +01:00
Otto van der Schaaf a73c096950 Revert "Merge pull request #872 from pagespeed/jefftk-revert-834"
This reverts commit 7bd90f7b3a, reversing
changes made to 58228564dd.
2015-01-10 22:07:21 +01:00
Jeff Kaufman 7bd90f7b3a Merge pull request #872 from pagespeed/jefftk-revert-834
Revert "NgxConnection: single event mechanism
2015-01-09 10:25:12 -05:00
Jeff Kaufman 73981ffe1a Revert "NgxConnection: single event mechanism for NgxFetch and NgxBaseFetch"
This reverts commit 5dfe42f3d3.
2015-01-08 13:02:19 -05:00
Jeff Kaufman 58228564dd Merge pull request #869 from pagespeed/jefftk-system-moved
mod_pagespeed moved the location of the system directory; update our includes
2015-01-06 09:50:11 -05:00
Jeff Kaufman 340c86a49e mod_pagespeed moved the location of the system directory; update our includes 2015-01-06 09:22:56 -05:00
Otto van der Schaaf abdafc7aa4 Merge pull request #834 from pagespeed/oschaaf-single-pipe2
NgxConnection: single event mechanism for NgxFetch and NgxBaseFetch
2014-12-30 21:52:07 +01:00
Jan-Willem Maessen 8cf10873d1 Merge pull request #863 from pagespeed/jmaessen-ngx-message-handler-fix
Make ngx_message_handler work with new message_handler api.
2014-12-19 16:13:26 -05:00
Jan-Willem Maessen 2496716e36 Make ngx_message_handler work with new message_handler api. 2014-12-19 15:11:55 -05:00
Jeff Kaufman af364344e9 Merge pull request #862 from pagespeed/jefftk-rmdir
testing: give '-p' to mkdir
2014-12-17 12:55:44 -05:00
Jeff Kaufman 9da45910c7 rm won't remove the containing directory if a file is removed out from under it, which means the directory will still be there but will be empty. This is not a problem, so pass '-p' to not fail on already existing directories. 2014-12-17 12:50:23 -05:00
Otto van der Schaaf 5dfe42f3d3 NgxConnection: single event mechanism for NgxFetch and NgxBaseFetch
Abstract the pipe communication into NgxEventConnection, for reuse
by NgxBaseFetch and NgxUrlAsyncFetcher.

Based on Chai's earlier work, but with a few fixes discovered
while working on this and SPDY module compatibility

- Uses less file descriptors, I expect this to be faster but need
  measurement is needed to back that.
- Fixed NgxUrlAsyncFetcher actually shutting down its fetchers.
- Fixes a bug where we wouldn't clean idle pooled NgxConnections.
- Fixes a bug for requests that are finalized mid-IPRO lookup.
- Makes us use ngx_handle_read_event/ngx_del_event
2014-12-14 02:29:40 +01:00
Jeff Kaufman bff15040be Merge pull request #857 from pagespeed/jefftk-upstream-check-failure-function
Upstream the change to check_failures_and_exit, moving it to mod_pagespeed
2014-12-04 15:42:31 -05:00
Jeff Kaufman 3c5c5076de Upstream the change to check_failures_and_exit, moving it to mod_pagespeed 2014-12-04 13:22:13 -05:00
Jeff Kaufman eab4f8672f Merge pull request #852 from pagespeed/jefftk-move-tests-to-system
Move duplicate tests from the nginx-specific system test to system
2014-12-02 20:12:52 -05:00
Jeff Kaufman 852e376130 Move duplicate tests from the nginx-specific system test to system/system_test
As system/system_test.sh is in the mod_pagespeed repo, this is just a bunch of
deletes.
2014-12-02 15:11:23 -05:00
Jeff Kaufman b7529a8d9a Merge pull request #855 from pagespeed/jefftk-fix-tempdir
Rework parallization separation
2014-12-02 13:34:03 -05:00
Jeff Kaufman 5dd93fffae Rework parallization separation 2014-12-01 10:49:08 -05:00
Jeff Kaufman 48d23f10ba Merge pull request #851 from pagespeed/jefftk-fix-url-purging
Fix error with url cache purging test.  Followup to #850.
2014-11-17 11:25:03 -05:00
Jeff Kaufman f924bc72d9 Fix error with url cache purging test. Followup to #850. 2014-11-17 11:19:51 -05:00
Otto van der Schaaf 1aff187d0e Merge pull request #850 from pagespeed/oschaaf-trunk-tracking-script-filters-test
script-filters: Add a test for modifying filters via script variables
2014-11-14 16:03:22 +01:00
Jeff Kaufman 3b64df255a Merge pull request #849 from pagespeed/jefftk-prioritize-critical-css-test
testing: allow the prioritize_critical_css post test to fail
2014-11-14 10:02:49 -05:00
Otto van der Schaaf 0eeeca6e47 script-filters: Add a test for modifying filters via script variables
As requested via https://github.com/pagespeed/ngx_pagespeed/pull/822
2014-11-14 15:56:13 +01:00
Jeff Kaufman 6f68ba2f68 testing: allow the prioritize_critical_css post test to fail 2014-11-14 08:56:37 -05:00
Otto van der Schaaf e6e70c32a8 Merge pull request #822 from pagespeed/oschaaf-trunk-tracking-script-filters
script-filters: Allow using script variables in Enable/DisableFilters
2014-11-06 22:35:44 +01:00
Jeffrey Crowell a3e20a05e2 Merge pull request #846 from pagespeed/oschaaf-trunk-tracking-conf-multi-typo
NGX_CONF_MULTI: Typo
2014-11-04 13:46:55 -05:00
Otto van der Schaaf e28255e2ef NGX_CONF_MULTI: Typo
Fix accidental double pipe symbol.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/843
2014-11-04 13:29:49 +01:00
Otto van der Schaaf 10ac8ae4a3 Merge pull request #798 from pagespeed/oschaaf-trunk-tracking-conf-multi
older-nginx-versions: Add NGX_CONF_MULTI to ps_command flags.
2014-10-30 15:13:27 +01:00
Jeffrey Crowell 1b3ca08e22 Merge pull request #841 from pagespeed/crowell-tengine-stable-support
Check type of resolver_ctx->addrs.
2014-10-29 14:59:51 -04:00
Jeffrey Crowell de5bc5d943 Check type of resolver_ctx->addrs.
Check the type of resolver_ctx->addrs and make sure that it is
ngx_addr_t* instead of in_addr_t*. addresses issue #839
2014-10-29 14:49:55 -04:00
Otto van der Schaaf afd0f01686 script-filters: Allow using script variables in Enable/DisableFilters
To support a non-evil way (if-in-location) of tuning SPDY specific
configuration, allow scripting of Enable/DisableFilters in nginx.conf
2014-10-10 17:33:44 +02:00
Otto van der Schaaf 0cdb81fab4 Merge pull request #795 from pagespeed/oschaaf-native-fetcher-remove-check
native-fetcher: remove a DCHECK that possibly fires on shutdown.
2014-10-06 17:04:56 +02:00
hillsp b492d3966e Merge pull request #811 from pagespeed/cheesy-device-matching
Support minor PSOL API change for matches_device_type
2014-09-22 17:38:06 -04:00
Steve Hill 232c05a81d Merge remote-tracking branch 'origin/trunk-tracking' into cheesy-device-matching 2014-09-19 18:17:20 -04:00
Steve Hill adbe2cb359 Remove unit tests; They are now in system_test.sh 2014-09-19 18:14:18 -04:00
Jeffrey Crowell 88370cf54d Merge pull request #809 from pagespeed/crowell-update-config
Merge config from 1.9.32.1
2014-09-19 10:47:08 -04:00
Jeffrey Crowell b43a973071 Merge config from 1.9.32.1 2014-09-19 10:30:38 -04:00
Steve Hill a524127d49 PSOL API change and unit tests for matches_device_type 2014-09-18 18:22:46 -04:00
Otto van der Schaaf 53a6de6da8 Merge pull request #797 from pagespeed/oschaaf-finalized-requests-fix
connection_read_handler: fix potential double free
2014-09-15 16:26:29 +02:00
Otto van der Schaaf 66f1b9aa9b older-nginx-versions: Add NGX_CONF_MULTI to ps_command flags.
Older nginx versions don't allow 'pagespeed' configuration
directives to appear in blocks other then http{} without it.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/786
2014-09-14 09:19:13 +02:00
Otto van der Schaaf 6903286aa4 connection_read_handler: fix potential double free
In connection_read_handler(), make sure we act accordingly when
r->connection->error is set (indicating the the current request has
been finalized).

Reproduction of what happens when we don't: enable IPRO+SPDY, and
rapidly refresh a page with chrome. These rapid abortions will
eventually trigger a segfault/hang/misc bad behaviour.
2014-09-13 16:30:34 +02:00
Otto van der Schaaf 46dc39f5a9 Merge pull request #794 from pagespeed/oschaaf-ipro-race
IPRO: Fix a race in processing writes() from NgxBaseFetch
2014-09-12 16:33:29 +02:00
Otto van der Schaaf 7d8fefe780 native-fetcher: remove a DCHECK that possibly fires on shutdown. 2014-09-11 23:33:22 +02:00
Otto van der Schaaf 43d1706e2f IPRO: Fix a race in processing writes() from NgxBaseFetch
For FetchInPlaceResource, NgxBaseFetch would send two bytes down its
pipe, one upon HeaderComplete() and one upon HandleDone(). We need
only one to resume processing on the nginx side.

There is a race between ps_connection_read_handler() and processing
of the byte send by NgxBaseFetch::HandleDone().
ps_connection_read_handler() clears the pipe when the request is
finalized, and also drains it on each event - so two writes could be
processed as one when lucky, masking the problem).

One concrete problem this solved for me was that SPDY + IPRO +
proxy_pass would segfault, hang, and/or pass on 5xx/404 responses
from IPRO lookup fetches to the browser, next to alerts about
r->count being zero in nginx's error.log

Might fix https://github.com/pagespeed/ngx_pagespeed/issues/788
Fixes https://github.com/pagespeed/ngx_pagespeed/issues/792
2014-09-11 23:14:41 +02:00
Otto van der Schaaf 622d088a3e Merge pull request #790 from pagespeed/oschaaf-trunk-tracking-native-fetcher-keepalive
native fetcher: Support http keep-alive
2014-09-05 17:29:22 +02:00
Otto van der Schaaf 0290f52a88 native fetcher: Support http keep-alive
Based on @dinic his work, add keep-alive support for the native fetcher.
Adds a new option, usable at the http{} level in configuration:

pagespeed NativeFetcherMaxKeepaliveRequests 50;

The default value is 100 (aligned to nginx). Setting the value to 1 turns off
keep-alive requests altogether).

Most notable changes:
- Request keep-alive by adding the appropriate request header
- Fixes connections getting reused while they are servicing other requests:
- Remove connection from the pool of available connections for keepalive when applicable
- Disable keepalive in more appropriate situations
- Response parsing fixes
- Remove connections that timeout from the k.a. pool
- Add a few sanity (D)CHECKS
- Emit debug messages for traceability
- Fix for ignoring ipv6 addresses returned from dns queries when ipv6 is enabled.
- Bump the fetch timeout in test configuration to deflake tests that require dns
  lookups (which will be done via 8.8.8.8 currently for the native fetcher)
2014-09-05 17:23:16 +02:00
Maks Orlovich c94146a54d Merge pull request #791 from pagespeed/morlovich-trunk-tracking-remove-deprecated-headers
Remove use of deprecated forwarding headers
2014-09-04 16:06:52 -04:00
Maks Orlovich f3a1cb6cf4 Remove use of deprecated forwarding headers 2014-09-04 09:16:05 -04:00
jmarantz 5a23347e64 Merge pull request #785 from pagespeed/jmarantz-error-option-format
Implement NgxServerContext::FormatOption so we can indicate nginx formatting in error messages
2014-08-29 16:32:43 -04:00
Joshua Marantz 7ce289346a Override the method used to specify the format for conf files, so we can put an accurate error message in the admin GUI, and test it 2014-08-29 09:13:43 -04:00
jmarantz 6b4a9dc487 Merge pull request #784 from pagespeed/jmarantz-fgrep-for-counts
use fgrep for counting ".pagespeed."
2014-08-27 09:47:46 -04:00
Joshua Marantz a3f2e4766c use fgrep for counting ".pagespeed.", rather than grep with backslashed dot, which matches too much 2014-08-26 15:02:10 -04:00
jmarantz ab0a5e4b65 Merge pull request #782 from pagespeed/jmarantz-start-test-resets-wget-args
Assume WGET_ARGS is cleared on every start_test
2014-08-23 13:20:34 -04:00
Joshua Marantz a458a65d4e Update system test to be compatible with a helper-script update that makes start_test clear WGET_ARGS, making test stanzas more independent 2014-08-20 12:59:04 -04:00
Jeff Kaufman d00911b00f Merge pull request #775 from pagespeed/jefftk-clearer-test-flake-error
testing: make it clearer why test flake in Issue #774 happens
2014-08-14 11:34:50 -04:00
Jeff Kaufman ed80427ae6 Merge pull request #761 from pagespeed/jefftk-adding-comments
Add some comments and a few style fixes.
2014-08-14 10:29:22 -04:00
Jeff Kaufman f556ca4926 Add some comments and a few style fixes. 2014-08-14 09:52:13 -04:00
Jeff Kaufman cad618dff7 testing: make it clearer why test flake in Issue #774 happens 2014-08-13 13:53:22 -04:00
Jeff Kaufman a906411367 Merge pull request #773 from pagespeed/jefftk-nginx-message-color
testing: direct port of r4146 to fix message color issue
2014-08-13 10:51:37 -04:00
Jeff Kaufman e6c5bc1b2e testing: direct port of r4146 to fix message color issue 2014-08-13 10:13:13 -04:00
Otto van der Schaaf d6d3b90ea3 Merge pull request #769 from pagespeed/oschaaf-large-beacon-posts
beacon response body processing from temp file
2014-08-12 17:57:34 +02:00
Otto van der Schaaf d7afd2acbc beacon response body processing from temp file
Add support for processing beacon posts with data sizes that exceed
the default or configured client_body_buffer_size, plus a system test
to ensure it.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/752
2014-08-12 07:46:30 +02:00
Maks Orlovich 05f6993801 Merge pull request #772 from pagespeed/morlovich-fix-metadata-form-test
Port over test adjustment.

This is just a straight port of relevant portion of https://code.google.com/p/modpagespeed/source/detail?r=4140
2014-08-11 16:45:32 -04:00
Maks Orlovich fe63bbf53f Port over test adjustment. 2014-08-11 16:26:20 -04:00
Otto van der Schaaf c7aa72d9c5 Merge pull request #767 from pagespeed/oschaaf-issue-757
rewriting-posts: Support POST responses for html
2014-08-07 16:28:51 +02:00
Otto van der Schaaf 8f6bb0c9e3 rewriting-posts: Support POST responses for html
Allow rewriting html responses to POST requests

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/757
2014-08-07 16:02:23 +02:00
Otto van der Schaaf 84f2a1884e Merge pull request #765 from pagespeed/oschaaf-trunk-tracking-script-support
script-variables: Support LoadFromFileXXX
2014-08-05 16:45:19 +02:00
Otto van der Schaaf da83f73f19 script-variables: Support LoadFromFileXXX
Based on 75a4481 from master.

Add support for script variables in LoadFromFileXXX configuration to trunk-tracking,
which can be enabled by adding "pagespeed ProcessScriptVariables on" in
the http{} block.
Also adds a helpful comment to ps_dollar().

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/549
Docs: https://github.com/pagespeed/ngx_pagespeed/wiki/Script-variables-in-LoadFromFile-configuration

Resolved conflicts:
	src/ngx_rewrite_driver_factory.h
	src/ngx_rewrite_options.cc
	test/nginx_system_test.sh
2014-08-05 00:51:07 +02:00
jmarantz 2bfc05b4c6 Merge pull request #763 from pagespeed/jmarantz-http-200-ok-function
use a new helper method to verify HTTP response codes are 200 OK
2014-08-04 11:00:03 -04:00
jmarantz ea9e209687 Merge pull request #764 from pagespeed/jmarantz-systest-exit-on-error
Make script execute properly in the context of 'set -e'
2014-08-04 10:04:03 -04:00
Joshua Marantz c073a3120b remove debug comments 2014-08-04 10:02:31 -04:00
Joshua Marantz 5e3b2f23a5 Make script execute properly in the context of 'set -e' 2014-08-01 09:29:08 -04:00
Joshua Marantz f41ecf4010 use a new helper method to verify HTTP response codes are 200 OK 2014-08-01 09:19:40 -04:00
Jeff Kaufman 34a62db9cf Merge pull request #760 from pagespeed/sligocki-request-context-set-options
Set options for RequestContexts in ngx_pagespeed.
2014-07-30 09:53:00 -04:00
Jeffrey Crowell b0efa9f982 Merge pull request #758 from pagespeed/crowell-debug-filter-safe-to-print
add safe_to_print on nginx rewrite options
2014-07-29 16:58:10 -04:00
Shawn Ligocki fb00ac373b Set options for RequestContexts in ngx_pagespeed. 2014-07-29 16:05:27 -04:00
Jeffrey Crowell 9550629768 add safe_to_print on nginx rewrite options 2014-07-29 14:58:06 -04:00
Shawn Ligocki 26a5deb341 Merge pull request #756 from pagespeed/sligocki-in-place-api-change
Fix InPlaceResourceRecorder constructor to remove two arguments passed in through options now.
2014-07-29 13:09:44 -04:00
Shawn Ligocki 7bcd5aadde Fix InPlaceResourceRecorder constructor to remove two arguments passed in through options now. 2014-07-28 18:02:17 -04:00
matterbury 594ba13606 Merge pull request #751 from pagespeed/matterbury-unauthorized-debug
Test the new debug messages for unauthorized domains.
2014-07-09 14:40:24 -04:00
Matt Atterbury 9d0b896737 Test the new debug messages for unauthorized domains. 2014-07-08 09:17:06 -04:00
Jud Porter 89f6465288 Merge pull request #748 from pagespeed/jud-ipv6-smoke-test
Fix smoke test on systems with ipv6 localhost
2014-07-02 13:37:23 -04:00
Jud Porter eb11cfe0cf Add ipv6 listen directives to smoke test config server blocks. 2014-07-02 10:57:40 -04:00
Jud Porter 7a0e45d025 Ignore "Hostname was NOT found in DNS cache" message generated by more recent versions of curl. 2014-07-02 10:49:23 -04:00
jmarantz 3cf731ee24 Merge pull request #743 from pagespeed/jmarantz-nginx-purge-method
Fix PURGE method support and testing to ngx_pagespeed
2014-07-01 17:44:38 -04:00
Joshua Marantz 1a4ffcf335 Fix PURGE method support and testing to ngx_pagespeed 2014-06-30 09:49:10 -04:00
Jeff Kaufman 72c7e584f7 Merge pull request #740 from pagespeed/jefftk-unused-function
Remove unused function.  Fixes #739.
2014-06-30 11:26:07 +01:00
Jeff Kaufman 08f69913dc Merge pull request #738 from pagespeed/jefftk-fix-style
style: minor fixes, mostly as a followup to #665
2014-06-27 17:15:11 -04:00
Jud Porter f2d6bcf3ac Merge pull request #742 from pagespeed/jud-exit-status
Have manual ngx_pagespeed runs return exit code 0.
2014-06-27 16:55:30 -04:00
Jud Porter 2c89815084 Have manual ngx_pagespeed runs return exit code 0. 2014-06-27 16:54:31 -04:00
Jeff Kaufman e55b062c17 Remove unused function. Fixes #739. 2014-06-27 10:22:58 -04:00
Jeff Kaufman 62ef051844 style: minor fixes, mostly as a followup to #665 2014-06-24 15:50:19 -04:00
Jeff Kaufman 36b07ca209 Merge pull request #665 from We-Amp/keesspoelstra-gzip-enable-trunk
gzip: enabling gzip on "pagespeed on"
2014-06-24 07:20:12 -04:00
Jeff Kaufman 1280cd0dfa Merge pull request #734 from pagespeed/jefftk-move-doc-to-devsite
readme: reference doc on developers.google.com instead of duplicating it
2014-06-23 10:38:43 -04:00
Jeffrey Crowell a06551a97d Merge pull request #735 from pagespeed/crowell-accept-invalid-signatures
add tests for accepting invalid signatures.
2014-06-20 16:36:42 -04:00
Jeffrey Crowell 679618f998 remove signature tests that live in automatic/system_test.sh 2014-06-20 11:24:30 -04:00
Jeffrey Crowell fb9b355715 rename REGEX to URL_REGEX in test 2014-06-20 10:56:31 -04:00
Jeffrey Crowell f71ac7dd0c add accept-invalid-signatures tests for transition to signed resources 2014-06-20 10:51:31 -04:00
Jeff Kaufman 19f479a6b6 readme: reference doc on developers.google.com instead of duplicating it. 2014-06-20 10:19:53 -04:00
xqyin 7431946d23 Merge pull request #733 from pagespeed/xqyin-refactor-message-handler3
Make NgxMessageHandler inherit to SystemMessageHandler
2014-06-20 10:17:54 -04:00
Cathy Yin 0d760dbf31 Make NgxMessageHandler inherit to SystemMessageHandler. Move SharedCircularBuffer things to SystemMessageHandler. 2014-06-19 15:56:03 -04:00
Cathy Yin e9d7b2ad01 Merge remote-tracking branch 'origin/trunk-tracking' into xqyin-refactor-message-handler2 2014-06-19 13:55:25 -04:00
jmarantz 0d89df0e80 Merge pull request #732 from pagespeed/jmarantz-cache-purge
add support for cache purge requests via GET from admin or PURGE method....
2014-06-19 13:44:27 -04:00
Cathy Yin 218d74f206 Make NginxMessageHandler inherit to a new class SystemMessageHandler. Move SharedCircularBuffer related operations there. 2014-06-19 13:06:53 -04:00
Jeff Kaufman bcefd56941 Merge pull request #720 from pagespeed/jefftk-lff-ipro
testing: a server block for testing load from file with ipro
2014-06-19 11:20:33 -04:00
Jeff Kaufman 676344bc8a testing: a server block for testing load from file with ipro 2014-06-19 10:01:33 -04:00
Joshua Marantz 7293f649d1 add support for cache purge requests via GET from admin or PURGE method. PURGE doesn't quite work yet, so we skip testing that one. 2014-06-19 09:34:40 -04:00
Jeff Kaufman 10f5093bf6 Merge pull request #731 from pagespeed/jefftk-thread-config
options: support setting NumRewriteThreads
2014-06-18 15:08:42 -04:00
Jeff Kaufman 357eb92683 options: move global option parsing to system/ 2014-06-18 15:08:08 -04:00
Jeff Kaufman a6c6d13392 Support setting NumRewriteThreads and NumExpensiveRewriteThreads
Several rewrite driver factory options are duplicated between apache and nginx.  Instead of duplicating this one too, a PSOL change moves them into system/, and this change takes advantage of that move.
2014-06-16 11:25:39 -04:00
xqyin 9007e582ad Merge pull request #727 from pagespeed/xqyin-refactor-admin-site
Change SystemServerContext::kStatistics to AdminSite::kStatistics
2014-06-11 14:55:42 -04:00
Cathy Yin 1ca04d514c Change SystemServerContext::kStatistics to AdminSite::kStatistics. 2014-06-11 14:01:15 -04:00
Kees Spoelstra 8e08b2b7e0 this adds the following configuration on "pagespeed on"
gzip on;
gzip_proxied any;
gzip_vary on;
gzip_types application/ecmascript;
gzip_types application/javascript;
gzip_types application/json;
gzip_types application/pdf;
gzip_types application/postscript;
gzip_types application/x-javascript;
gzip_types image/svg+xml;
gzip_types text/css;
gzip_types text/csv;
gzip_types text/html;
gzip_types text/javascript;
gzip_types text/plain;
gzip_types text/xml;
gzip_http_version 1.0;

If any explicit gzip configuration is detected the gzip configuration
set by pagespeed is rolled back completely and the explicit gzip
configuration is used.

To enable/disable gzip with pagespeed the following commands can be used:

pagespeed gzip on;
pagespeed gzip off;

We test the nesting of the gzip configuration (pagespeed gzip on/off and
pagespeed on/off)
Ideally we need to test all the content types as well and the rollback in
case of an explicit gzip configuration, but to do this we need to be able
to map a custom directory into the nginx tests this and seperate nginx
config files.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/238
2014-06-11 17:40:52 +02:00
Kees Spoelstra ad1a1594d6 this adds the following configuration on "pagespeed on"
gzip on;
gzip_proxied any;
gzip_vary on;
gzip_types application/ecmascript;
gzip_types application/javascript;
gzip_types application/json;
gzip_types application/pdf;
gzip_types application/postscript;
gzip_types application/x-javascript;
gzip_types image/svg+xml;
gzip_types text/css;
gzip_types text/csv;
gzip_types text/html;
gzip_types text/javascript;
gzip_types text/plain;
gzip_types text/xml;
gzip_http_version 1.0;

If any explicit gzip configuration is detected the gzip configuration
set by pagespeed is rolled back completely and the explicit gzip
configuration is used.

To enable/disable gzip with pagespeed the following commands can be used:

pagespeed gzip on;
pagespeed gzip off;
2014-06-11 17:28:25 +02:00
jmarantz d5e37d2d2e Merge pull request #726 from pagespeed/jmarantz-remove-spew-and-extra-read
make check-from greps be silent, and remove extra 'read'
2014-06-11 11:28:21 -04:00
Joshua Marantz 4bceb402a6 make check-from greps be silent, and remove extra 'read' that was causing smoke tests to apparently hang 2014-06-11 10:48:42 -04:00
Jeffrey Crowell 80a50fe9d8 Merge pull request #724 from pagespeed/crowell-signed-urls
signed-urls tests added.
2014-06-10 17:16:30 -04:00
Jeffrey Crowell 28192a509e update nginx_system_test to use signed resources. 2014-06-10 16:41:41 -04:00
Jeff Kaufman 9331815350 Merge pull request #721 from pagespeed/oschaaf-lff-ipro-trunk-tracking
ipro-lff: Prevent handing out 200/OK when we can't rewrite in place
2014-06-05 15:22:51 -04:00
Otto van der Schaaf 727d339dfd ipro-lff: Prevent handing out 200/OK when we can't rewrite in place
PSOL change for in_place_rewrite_context.cc
- Reorder setting the status code so we actually change the
  ResponseHeaders that we are using to serve
- Prevent non-error http status codes from being served up.

As noted by @jeffkaufman, to prevent a potential lifetime issue with
ResponseHeaders, remove the call to ps_release_base_fetch() in
ps_decline_request().

PSOL patch:
```diff
--- ../rewriter/in_place_rewrite_context.cc	(revision 4020)
+++ ../rewriter/in_place_rewrite_context.cc	(working copy)
@@ -127,9 +127,20 @@
       // to us.
       streaming_ = false;
       set_request_headers(NULL);
+      // If we cannot rewrite in-place, we should not serve a 200/OK.
+      // Serve kNotFound instead to fall back to the server's native
+      // method of serving the url and indicate we don't want it recorded
+      // either.
+      // TODO(oschaaf): When the resource is loaded via LoadFromFile,
+      // this code gets repeatedly hit for the same url. That might
+      // become a drag when the file in question is very large and popular.
+      // Marking urls that end up in this flow as not cachable in the http cache
+      // at this point had no effect (for the LoadFromFile flow at least).
+      if (!response_headers()->IsErrorStatus()) {
+	response_headers()->set_status_code(HttpStatus::kNotFound);
+      }
       set_response_headers(NULL);
       set_extra_response_headers(NULL);
-      response_headers()->set_status_code(HttpStatus::kNotFound);
       SharedAsyncFetch::HandleDone(false);
     }
   }
```
2014-06-05 15:46:53 +02:00
jmarantz b3e5297dc3 Merge pull request #717 from pagespeed/jmarantz-psol-library-from-env-var2
Allow the path to the PSOL library to be specified by an env var.
2014-06-03 18:01:40 -06:00
Joshua Marantz 639a01015c fix indentation 2014-06-03 19:59:44 -04:00
Kees Spoelstra 29a43196e8 gzip: enabling gzip on "pagespeed on"
this adds the following configuration on "pagespeed on"
gzip  on;
gzip_proxied any;
gzip_vary on;
gzip_types application/ecmascript;
gzip_types application/javascript;
gzip_types application/json;
gzip_types application/pdf;
gzip_types application/postscript;
gzip_types application/x-javascript;
gzip_types image/svg+xml;
gzip_types text/css;
gzip_types text/csv;
gzip_types text/html;
gzip_types text/javascript;
gzip_types text/plain;
gzip_types text/xml;
gzip_http_version 1.0;

If an explicit configuration is detected the gzip configuration
set by pagespeed on is rollbacked

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/238
2014-06-03 23:29:31 +02:00
matterbury 0b20c91217 Merge pull request #718 from pagespeed/matterbury-move-redirection-tests
Move redirection tests to the common test script.
2014-06-03 11:27:16 -04:00
Matt Atterbury d654062516 Move redirection tests to the common test script. 2014-06-02 09:30:34 -04:00
Joshua Marantz b6991fd107 Allow the path to the PSOL library to be specified by an env var. This was already doc'd in a comment in 'config' but did not work. 2014-05-31 07:58:50 -04:00
Jeff Kaufman bf042f8af9 Merge pull request #715 from pagespeed/jefftk-move-contrnet-length-test
headers: content length is now tested in common code
2014-05-30 09:28:11 -04:00
Jeff Kaufman 22950666e0 headers: content length is now tested in common code 2014-05-29 15:19:58 -04:00
xqyin 96f185d472 Merge pull request #709 from pagespeed/xqyin-color-messages
Color messages in the message_history page. Add system test for this change.
2014-05-28 17:39:05 -04:00
Jeff Kaufman c9a106b4b0 readme: with 1.8 we need different default config 2014-05-28 16:33:01 -04:00
Jeff Kaufman 00080ff728 readme: 1.7.30.4 -> 1.8.31.2 2014-05-28 16:13:01 -04:00
Cathy Yin b6098ce302 Color the messages in message_history page. Add corresponding system test for this change. 2014-05-28 09:42:14 -04:00
Jeff Kaufman 36d285a354 Merge pull request #707 from pagespeed/jefftk-fix-static-asset-prefix
options: support StaticAssetPrefix
2014-05-27 11:35:39 -04:00
Matt Atterbury 149d1c7a5c Moved cookie option tests to common test script. 2014-05-27 09:59:59 -04:00
Matt Atterbury 9e9bf76164 Added system test for sticky options. 2014-05-27 09:59:59 -04:00
Matt Atterbury 09bc3b0aba Added query parameter to make the other query parameters 'sticky' by returning cookies that set them so are passed in subsequent requests. 2014-05-27 09:59:59 -04:00
Jeff Kaufman 502abb2f10 options: support StaticAssetPrefix 2014-05-23 14:09:49 -04:00
matterbury 08bdfb8c65 Merge pull request #700 from pagespeed/matterbury-sticky-options
Added query parameter to make the other query parameters 'sticky' ...
2014-05-20 14:16:47 -04:00
Matt Atterbury 8a8f62fefa Moved cookie option tests to common test script. 2014-05-19 09:27:26 -04:00
Matt Atterbury 94ab5c33f8 Added system test for sticky options. 2014-05-16 12:01:57 -04:00
Matt Atterbury 0e766e4096 Merge remote-tracking branch 'origin/trunk-tracking' into matterbury-sticky-options
if it merges an updated upstream into a topic branch.
2014-05-16 12:00:33 -04:00
Jeff Kaufman a7fdc86744 Merge pull request #701 from pagespeed/jefftk-move-settings-to-server-scope
move settings to server scope

Allow you to set `MessagesPath`, `StatisticsPath`, `AdminPath`, or `ConsolePath`  in a `server {}` block.
2014-05-12 09:34:39 -04:00
Jeff Kaufman aed13fc578 Allow admin paths to be set at server scope. 2014-05-12 09:12:52 -04:00
Matt Atterbury cd753a22a7 Added query parameter to make the other query parameters 'sticky' by returning cookies that set them so are passed in subsequent requests. 2014-05-12 08:26:32 -04:00
matterbury 6af5774ef8 Merge pull request #688 from pagespeed/matterbury-queryparams
Rename QueryParams::Parse to ParseFromUrl. Add a wrapper that takes an untrusted string.
2014-04-30 10:05:01 -04:00
Matt Atterbury 117994993a Rename QueryParams::Parse to ParseFromUrl. Add a wrapper that takes an untrusted string. 2014-04-30 09:59:34 -04:00
Jeffrey Crowell 5487b7350c Merge pull request #684 from pagespeed/crowell-requst-option-override
add ngx test support for RequestOptionOverride option
2014-04-28 13:53:41 -04:00
Jeffrey Crowell 261b602f83 add ngx test support for RequestOptionOverride option 2014-04-25 11:48:29 -04:00
Jeff Kaufman ae3cf7a425 Merge branch 'master' into trunk-tracking 2014-04-25 08:27:36 -04:00
Jeff Kaufman b4af0738a5 readme: use nginx 1.6.0 2014-04-25 08:27:26 -04:00
Jeff Kaufman ff049a55c3 Merge pull request #681 from pagespeed/jefftk-psol-dep
dependencies: include psol as a dependency
2014-04-24 14:04:24 -04:00
Jeff Kaufman 0772787ad4 dependencies: include psol as a dependency 2014-04-24 13:30:17 -04:00
jmarantz 7eedc2ce3c Merge pull request #680 from pagespeed/jmarantz-clean-proactive
clean up the conf file overrides to turn off proactive resource
2014-04-24 11:21:20 -04:00
Joshua Marantz 7af665b5dd clean up the conf file overrides to turn off proactive resource
fetching and compressed cache.  the compressed cache was ok but
proactive resource fetching consistently fails system tests in nginx
2014-04-24 11:16:27 -04:00
Jeff Kaufman 8136a15352 Merge pull request #678 from pagespeed/jefftk-update-trunk-tracking
port r3968 which is supposed to be just a test that a bug isn't present...
2014-04-23 15:46:59 -04:00
Jeff Kaufman 31024cfc24 trunk-tracking: also turn off ProactiveResourceFreshening until we fix PSOL. 2014-04-23 15:25:49 -04:00
Jeff Kaufman 703fda7eba port r3968 which is supposed to be just a test that a bug isn't present, but in ngx_pagespeed actually triggers that bug. This needs to be fixed, but is out of scope for a trunk-tracking update. 2014-04-23 14:56:25 -04:00
Jeff Kaufman d4bc40007e Merge pull request #677 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: update from r3949 to r3967
2014-04-23 14:11:50 -04:00
Jeff Kaufman f2e2ab6056 port r3966 by turning off CompressMetadataCache which breaks ipro 2014-04-23 13:22:14 -04:00
Jeff Kaufman e06a65e7e6 port 3967 which adds a fetch_until to the prioritize critical css test 2014-04-23 10:20:31 -04:00
Jeff Kaufman 3231949e03 port r3964 which handles options in request cookies 2014-04-23 10:10:48 -04:00
Jeff Kaufman f5713996f2 Merge branch 'trunk-tracking' of github.com:pagespeed/ngx_pagespeed into trunk-tracking 2014-04-23 09:15:57 -04:00
Jeff Kaufman 185632583b Merge pull request #675 from pagespeed/jefftk-update-trunk-tracking
trunk tracking: update from r3934 to r3949
2014-04-23 09:15:45 -04:00
Jeff Kaufman c5dbfa16cd trunk-tracking: fix comment 2014-04-23 09:14:58 -04:00
Jeff Kaufman 33b2e82ec6 trunk-tracking: port tests for r3948, PageSpeed=... not ModPagespeed=... 2014-04-22 17:56:09 -04:00
Jeff Kaufman b87ffce5ba trunk-tracking: port r3945 which made the location of static assets configurable 2014-04-22 17:55:57 -04:00
Jeff Kaufman 7d5fc11afd trunk-tracking: port tests for r3937, url-valued attributes overriding spec 2014-04-22 17:38:51 -04:00
Jeff Kaufman 7cba7ba4f4 trunk-tracking: port tests for r3935 which changes image lazyloading 2014-04-22 17:38:51 -04:00
Jeff Kaufman cf434f71cc trunk-tracking: port r3937 which supports custom url-valued attributes overriding spec-defined ones 2014-04-22 16:37:13 -04:00
Jeff Kaufman ba8c149a88 Merge pull request #670 from pagespeed/oschaaf-downstream-cache-headers
downstream-caching-headers: make nginx 1.5.9+ pass tests as well
2014-04-21 17:07:23 -04:00
Jeff Kaufman f5bac604a1 Merge pull request #671 from pagespeed/oschaaf-downstream-cache-test
downstream-cache-test: deflake the test
2014-04-21 10:27:53 -04:00
Otto van der Schaaf f18faa3ae1 downstream-cache-test: deflake the test
As suggested by Anupama, deflake the test by only allowing beaconing
when explitly requested by http request from tests.

Html with beacons in it will bypass the proxy cache.
2014-04-20 00:24:32 +02:00
Otto van der Schaaf 070ae2aad2 downstream-caching-headers: make nginx 1.5.9+ pass tests as well
- Fix a mistake I made in https://github.com/pagespeed/ngx_pagespeed/pull/653
  This is the primary reason the test starts failing, the base fetch
  handled `kPreserveOnlyCacheControl` in the wrong way.
- Use `ps_set_cache_control` when copying a Cache-Control header
  to nginx, as `r->headers_out.cache_control` is where modules running
  after us might expect it
- Exclude a few more lines from curl's verbose output in the keep-
  alive tests that I came accross when testing on ubuntu 13.10
  Desktop.

Note that this does not deflake the downstream cache test yet, I will
look at that in a follow-up.
2014-04-19 22:58:09 +02:00
Jeff Kaufman 674c70e32c Merge pull request #669 from pagespeed/morlovich-trunk-tracking-ssl-tests
Port over the basic HTTPS fetching test.
2014-04-17 16:36:01 -04:00
Maks Orlovich b4ef143a88 Port over the basic HTTPS fetching test. 2014-04-17 16:20:10 -04:00
Jeff Kaufman ffdc3c8fd6 Merge pull request #667 from pagespeed/jefftk-merge-master-to-tt
trunk-tracking: merge in master
2014-04-17 15:21:19 -04:00
Jeff Kaufman af10fc3ddb trunk-tracking: merge in master 2014-04-17 15:16:43 -04:00
Jeff Kaufman e9a099f9c5 Merge pull request #666 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: update from r3924 to r3934
2014-04-17 10:43:46 -04:00
Jeff Kaufman e4a2933c58 trunk-tracking: update from r3924 to r3934
There aren't actually any changes required from r3924 to r3934 but the admin
work from previous versions wasn't completely ported before.

This change:
 * adds support for /pagespeed_admin and /pagespeed_global_admin
 * removes NgxPagespeedConsoleAsyncFetch using NgxBaseFetch instead
 * adds options StatisticsPath, GlobalStatisticsPath, ConsolePath,
   MessagesPath, AdminPath, and GlobalAdminPath which allow site owners to
   control what path these are served under
 * changes /ngx_pagespeed_statistics etc from default-on to default-off,
   requiring explicit path configuration to function
 * does not fix the problem where trunk-tracking fails tests on 1.5 post #653
2014-04-17 10:10:20 -04:00
Jeff Kaufman 2601232457 Merge pull request #655 from pagespeed/oschaaf-native-fetcher-resolve-timeout
native-fetcher: fix CHECK failure on DNS timeout
2014-04-14 07:28:42 -04:00
Otto van der Schaaf a3e1810a6a Merge pull request #653 from pagespeed/oschaaf-downstream-caching-headers
downstream-caching: Fix pagespeed resource response headers
2014-04-10 21:56:01 +02:00
Otto van der Schaaf 72f3c79fec downstream-caching: Fix pagespeed resource response headers
- Make kPreserveOnlyCacheControl do what it says on the tin
- Serve pagespeed resources with the response headers computed
  by PSOL regardless of whether downstream caching is configured.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/652
2014-04-10 21:42:48 +02:00
Otto van der Schaaf 323e820fde Merge pull request #658 from pagespeed/oschaaf-configure-wnoerror
nginx-gridfs: Add configure option to build with wno-error
2014-04-09 20:38:57 +02:00
Otto van der Schaaf a9a7bf56ac Merge pull request #659 from pagespeed/jud-trunk-tracking
trunk-tracking: update from r3895 to r3924
2014-04-08 21:58:16 +02:00
Jud Porter 2358f957cb trunk-tracking: update from r3895 to r3924 2014-04-08 14:51:04 -04:00
Otto van der Schaaf 7d72a7c89a nginx-gridfs: Add configure option to build with wno-error
Some modules add things to CFLAGS that will make ngx_pagespeed emit
warnings at compile time. For example, nginx-gridfs will add
`--std=c99` - which is no good for ngx_pagespeed.

@peterbowey mentioned that -wno-error fixes the build -- so
to work around, make configure add `-wno-error` when used like
this: `WNO_ERROR=YES ./configure`
On my system, that results in a succesfull build when nginx-gridfs
is added to the module mix.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/626
2014-04-08 13:10:58 +02:00
Otto van der Schaaf 8830724580 native-fetcher: fix CHECK failure on DNS timeout
Make sure we clear the timeout event associated with resolving
a hostname in `CallbackDone()`, which would otherwise end up
calling `CallbackDone()` a second time upon firing.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/625
2014-04-06 09:17:45 +02:00
Otto van der Schaaf c2d07a8d5a Merge pull request #651 from pagespeed/morlovich-trunk-tracking-upto-r3895
trunk tracking upto r3895
2014-04-02 18:53:04 +02:00
Maks Orlovich c3bff67637 Fix improper cache key on write for IPRO of resources with PageSpeed params
We need to be writing with the base name, with params stripped.
This was causing a test to "flake" under valgrind, since with it we got
to the test showing the bug slowly enough for the entry written out by
an earlier test under proper URL to expire.
2014-04-02 18:41:08 +02:00
Maks Orlovich 5a1a29ee8b trunk-tracking: update from r3872 to r3895
Squash-merge of @morlovich's work on this.

Note that this does not yet incorprorate the new
pagespeed_admin handler from r3891
2014-04-02 18:39:08 +02:00
Jeff Kaufman 61025c5e4f if: support pagespeed directives in location if blocks 2014-03-31 10:35:05 -04:00
Otto van der Schaaf d3e7900704 Merge pull request #648 from pagespeed/jmaessen-trunk-tracking
trunk-tracking: update from r3852 to r3872
note that it will only compile against mod_pagespeed r3872 if you first patch in r3889
2014-03-28 22:37:31 +01:00
Jan-Willem Maessen 85e19c962b trunk-tracking: update from r3852 to r3872 2014-03-27 10:59:13 -04:00
Otto van der Schaaf 20fd7d18dd Merge pull request #646 from pagespeed/oschaaf-chunked-transfer
content-length: fix pagespeed/ipro resource content-lengths
2014-03-26 08:53:50 +01:00
Otto van der Schaaf 4667aa1fc3 content-length: fix pagespeed/ipro resource content-lengths
Makes life downstream easier and more efficient
2014-03-25 21:29:28 +01:00
Jeff Kaufman 6ced8c0f65 Merge pull request #641 from pagespeed/jefftk-if-block
if: support pagespeed directives in location if blocks
2014-03-25 13:16:27 -04:00
Jeff Kaufman bfaf4268cf Merge pull request #639 from pagespeed/jefftk-trunk-tracking
trunk-tracking: update from r3827 to r3852
2014-03-19 16:57:28 -04:00
Jeff Kaufman 78cf39f9b3 if: support pagespeed directives in location if blocks 2014-03-19 16:46:48 -04:00
Jeff Kaufman 215071a383 trunk-tracking: update from r3827 to r3852
* port EnrollExperiment tests.
* tricky changes to get gzip+ipro working properly.
* reduce code duplication by calling copy_response_headers_from_ngx instead
  of reimplementing it.
* port Vary: Accept test changes.
2014-03-18 16:58:50 -04:00
Jeff Kaufman 630f7d848b lint: fix lint errors 2014-03-18 10:38:58 -04:00
Huibao Lin d90245af69 trunk-tracking: merge changes in from master:
* release: prepare 1.7.30.3
* Don't call chown() when initializing config dirs unless owner != worker user.
* Update README.md
* release: build against backported change
* release: udpate version number 1.7.30.3 to 1.7.30.4
2014-03-18 10:38:28 -04:00
Jeff Kaufman f25569690a merge commit: merge 1.7.30.4 into master 2014-03-14 10:15:42 -04:00
huibaolin 707d671826 Change version 1.7.30.3 to 1.7.30.4 2014-03-14 08:16:38 -04:00
Jeff Kaufman f8b87ea436 Merge pull request #636 from pagespeed/huibao-prepare-1.7.30.4-release
release: update version number 1.7.30.3 to 1.7.30.4
2014-03-13 10:37:21 -04:00
Huibao Lin 86d840f76e release: udpate version number 1.7.30.3 to 1.7.30.4 2014-03-13 10:27:21 -04:00
Jeff Kaufman 0110d33fa7 Merge pull request #635 from pagespeed/huibao-prepare-1.7.30.4-release
release: build against backported change
2014-03-13 10:26:16 -04:00
Huibao Lin 497594ba7f release: build against backported change 2014-03-13 10:18:57 -04:00
Jeff Kaufman 336352df38 Merge pull request #633 from pnommensen/patch-2
readme: use nginx 1.4.6
2014-03-07 13:17:42 -05:00
Patrick Nommensen 0edd405eb8 Update README.md
Don't know how I missed that.
2014-03-07 10:16:43 -08:00
Jeff Kaufman d004c4d916 Merge pull request #632 from pnommensen/patch-2
1.4.5 to 1.4.6 update
2014-03-07 11:32:01 -05:00
Jeff Kaufman c754cf1be0 trunk-tracking: update from r3811 to r3927 2014-03-07 11:18:35 -05:00
Patrick Nommensen 091ef6399b version update
1.4.5 to 1.4.6 http://nginx.org/en/CHANGES-1.4
2014-03-06 23:25:13 -08:00
Jeff Kaufman 9e4d26da5e Merge pull request #629 from pagespeed/jmaessen-trunk-tracking
trunk-tracking: update from r3784 to r3811
2014-03-03 16:56:15 -05:00
Jan-Willem Maessen 027d481817 trunk-tracking: update from r3784 to r3811
The big change here is Vary: headers, which are no longer being stripped from the pagespeed response.  Take a look; it might be we want to be smart about merging these headers with the original request's Vary: headers.
2014-02-27 19:41:23 -05:00
Jeff Kaufman 67106e920e apr: call SystemRewriteDriverFactory::InitApr()
squash-merge of morlovich's #601.
2014-02-20 09:13:56 -05:00
Jeff Kaufman 9699caeab5 Merge pull request #623 from pnommensen/patch-1
Update README.md
2014-02-20 09:12:04 -05:00
Patrick Nommensen c371d516a8 Update README.md
nginx version update
2014-02-20 00:04:21 -08:00
Jeff Kaufman 207eb2d131 Merge pull request #622 from pagespeed/jefftk-trunk-tracking
trunk-tracking: update from r3770 to r3784
2014-02-19 12:58:40 -05:00
Jeff Kaufman d9e2142f31 trunk-tracking: update from r3770 to r3784
* r3772 changed the format of unauthorized resource inlining config
* r3776 changed query param handling, but due to Jud's nice work in
  #616 needed no changes.
* r3780 huibao's refactoring lets us remove some duplicate code
* r3783 changes header passing with ipro
* Also cleaned up error messages for unknown options.
2014-02-19 10:53:48 -05:00
Jeff Kaufman bf6c6c0e9b Merge pull request #621 from jart/dont-chown
Security Fix: Don't call chown() unless necessary.
2014-02-18 14:32:32 -05:00
Justine Tunney e8dd9fd3c3 Don't call chown() when initializing config dirs unless owner != worker user. 2014-02-15 22:32:55 -05:00
Jud Porter 33d006625e Merge pull request #616 from pagespeed/jud-trunk-tracking
trunk-tracking: update from r3736 to r3770
2014-02-11 16:43:33 -05:00
Anupama Dutta 2dcaa95278 trunk-tracking: update from r3736 to r3770
Updated global_only options to include the correct APACHE_CONFIG_OPTIONX directives.
Removed repeated tests for prioritize_critical_css basic functionality.
Added new tests, mostly downstream caching tests and related pagespeed.conf updates. Also added missing pagespeed.conf updates for downstream caching.
Added support for checking option scope.
2014-02-11 16:40:07 -05:00
Jeff Kaufman f5252b569a trunk-tracking: update from r3715 to r3736
Squash-merge of Jan's #608 and Otto's #611.

* r3726:
  * Updated closure compiler flags for static JS files.
* r3729:
  * Centralize parsing of FetchHttps in SystemRewriteOptions so ngx_pagespeed
    can get it too.
  * To keep the helpful error_message from SerfUrlAsyncFetcher, wire it through
    RewriteOptions as a new-fangled error_detail.
* r3735:
  * Follow-up changes for downstream caching integration with beaconing
    dependent filters: If a downstream cache rebeaconing key is configured, we
    should instrument the page only if the key present in the PS-ShouldBeacon
    header matches the one in the configuration. This allows us to send no-cache
    headers for anything that carries the right beaconing key, and continue to
    send out the original cache control headers in other cases where downstream
    caching is enabled.
* Native fetcher: fortify handling of content length (and absense).
* Native fetcher: fail when the stream terminates before having
  completely parsed the headers.
* Tests: Rename `test_filter` -> `start_test` in ngx_system_test.sh for
  a test.
* Tests: Move blockingrewrite key to the http {} block.
* Tests: Update localhost -> 127.0.0.1. The native fetcher uses
  dns to resolve, and won't be able to retreive an ip for
  localhost.
* Tests: Allow outstanding proxy fetches some time to finish
  when running under valgrind, before terminating nginx.
* Valgrind: Add suppressions to make testing a release build pass.

This pull update was extra work because the valgrind and native fetcher flows
had rotted a bit.  We need to make sure to test them with every update.
2014-01-31 10:07:36 -05:00
Jeff Kaufman 64eaa2a659 Merge pull request #602 from tcpper/fix_ngx_fetch_content_length
fix bug in NgxFetch#content_length_
2014-01-30 11:25:52 -08:00
Jeff Kaufman 4783144e7d Merge branch 'master' into trunk-tracking 2014-01-24 16:56:26 -05:00
Jeff Kaufman 83205c9c31 Merge pull request #606 from pagespeed/oschaaf-multiple-experiment-cookies
Experiments: fix sending out multiple experiment cookies
2014-01-24 13:12:27 -08:00
Otto van der Schaaf 625e762961 Experiments: fix sending out multiple experiment cookies
Only classify people into an experiment when we are rewriting html.
Fixes https://github.com/pagespeed/ngx_pagespeed/issues/586
2014-01-24 22:09:31 +01:00
Jeff Kaufman c20affe323 Merge pull request #605 from pagespeed/oschaaf-date-header
Date header: use current date when we don't get one handed over
2014-01-24 08:47:00 -08:00
Otto van der Schaaf 7a9e6de802 Date header: use current date when we don't get one handed over
When the content generator does not supply us with a date header,
we need to create one ourselves and set it to the current date.

Fixes:
https://github.com/pagespeed/ngx_pagespeed/issues/604 (duplicate)
https://github.com/pagespeed/ngx_pagespeed/issues/577
2014-01-24 16:49:37 +01:00
Huibao Lin 96cf9a22f7 Update to 1.7.30.3 release 2014-01-16 18:37:36 -05:00
Jeff Kaufman ab83a70a35 Merge pull request #599 from eezis/docfix
Added a missing 'cd ~' command to the README
2014-01-16 13:30:44 -08:00
huibaolin 6db4d02a91 Merge pull request #600 from pagespeed/huibao-prepare-release-1.7.30.3-beta
release: prepare 1.7.30.3
2014-01-16 12:12:53 -08:00
Huibao Lin 1354cee4ed release: prepare 1.7.30.3 2014-01-16 15:06:49 -05:00
Ernest Ezis 658b2cf7a9 Added the missing 'cd ~' command to the '3. Download and build nginx:' section 2014-01-16 12:45:14 -07:00
Jeff Kaufman 092bbf2862 Merge pull request #597 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: update from r3696 to r3714
2014-01-16 07:18:31 -08:00
tcpper 6ccb815df3 fix bug in NgxFetch#content_length_ 2014-01-16 21:06:12 +08:00
Jeff Kaufman f04c533df0 trunk-tracking: update from r3696 to r3714
https://code.google.com/p/modpagespeed/source/detail?r=3697
 * system test improvements

https://code.google.com/p/modpagespeed/source/detail?r=3699
 * moved some config from location block to server block
 * system test improvements

https://code.google.com/p/modpagespeed/source/detail?r=3707
 * tests for OptimizeForBandwidth
   * had to switch tests from directory blocks to server+location blocks

https://code.google.com/p/modpagespeed/source/detail?r=3708
 * update to a test that had never been ported

* ngx_pagespeed.cc:
  * change in signature of FindIgnoreCase

https://code.google.com/p/modpagespeed/source/detail?r=3689
 * Was apparently skipped with #591.
2014-01-15 13:18:47 -05:00
Jeff Kaufman 8468e4849a Merge branch 'master' into trunk-tracking 2014-01-08 10:51:42 -05:00
Jeff Kaufman df5736609d native-fetcher: add support for FetchProxy
The native fetcher previously ignored FetchProxy settings; now it doesn't.

Squash-merge of tcpper's #590.
2014-01-08 10:51:24 -05:00
Jeff Kaufman 72ddb34a1c readme: release 1.7.30.2 2014-01-06 16:54:56 -05:00
Jeff Kaufman 7fbb2c61ee readme: release 1.7.30.2 2014-01-06 16:51:41 -05:00
Jeff Kaufman ae2d4bac7f native-fetcher: fix to work with nginx 1.5.8+
nginx 1.5.8 changed the resolver api, which the native fetcher uses.

Fixes #578.

Squash-merge of @dinic's #581.
2014-01-06 16:46:48 -05:00
Jeff Kaufman af772c2fe8 Merge pull request #592 from pagespeed/jefftk-better-configure-error
config: point people to obj/autoconf.err when psol isn't detected
2014-01-03 03:33:47 -08:00
Jeff Kaufman a4bd9b9c13 config: point people to obj/autoconf.err when psol isn't detected by ./configure 2014-01-02 23:09:42 -05:00
Jeff Kaufman f87d0f7ae2 Merge pull request #591 from pagespeed/jud-trunk-tracking
Updates to trunk tracking branch.
2014-01-02 13:43:11 -08:00
Jud Porter 501742cb56 trunk-tracking: update from r3677 to r3696.
Add inline unauthorized resources test and fix rendered image dimensions test.
2014-01-02 16:42:10 -05:00
Jeff Kaufman a669be99b1 Merge branch 'master' into trunk-tracking 2014-01-02 16:25:23 -05:00
Jeff Kaufman 328d3afc9b Merge pull request #583 from pagespeed/jefftk-support-purge
native-fetcher: support non-GET request methods like PURGE
2013-12-20 07:11:55 -08:00
Jeff Kaufman 2681c24ee0 native-fetcher: fix to work with nginx 1.5.8+
nginx 1.5.8 changed the resolver api, which the native fetcher uses.

Fixes #578.

Squash-merge of @dinic's #581.
2013-12-19 12:46:53 -05:00
Jeff Kaufman f86f47fda4 native-fetcher: support non-GET request methods like PURGE 2013-12-19 11:38:46 -05:00
Jeff Kaufman 179c81afa3 test: don't run downstream caching test with native fetcher 2013-12-19 11:03:53 -05:00
Jeff Kaufman 8d7eb20c89 Merge pull request #575 from pagespeed/dec9-trunk-tracking-updates
Trunk tracking updates to sync to PSOl r3677.
2013-12-13 07:14:30 -08:00
Anupama Dutta 1fe6c54b94 Trunk tracking updates to sync to PSOl r3677.
Includes minor additions to test only.

Trunk tracking updates to sync to PSOl r3677.

Trunk tracking update to sync to PSOL r3677

Includes minor additions to test only.
2013-12-12 22:27:27 -05:00
Jeff Kaufman 1667879202 Merge pull request #571 from morlovich/morlovich-trunk-tracking-20131125
Trunk tracking update for up to r3646
2013-12-02 07:45:08 -08:00
Maks Orlovich 0076e45677 Port over ModPagespeed r3635: RespectXForwardedProto is vhost-scope 2013-11-27 12:59:47 -05:00
Jeff Kaufman 1f3560ea21 backport header-only fix
Was: trunk-tracking: update to r3632 from 1.7.30.1
2013-11-26 16:39:52 -05:00
Jeff Kaufman 54352bff72 trunk-tracking: update to r3632 from 1.7.30.1 2013-11-26 16:37:30 -05:00
Maks Orlovich 329985659c Fix flakey test
It doesn't make sense to fetch_until the uncombined URL and then
grep for combined one: you might just get entirely unoptimized
output and fail the test. Instead wait for the combining to happen,
and make sure it combined the right # of things.
2013-11-25 16:32:31 -05:00
Maks Orlovich db870f7023 Update to pagespeed_automatic.ca more symbols + symbol renaming
This make it possible to build w/o disabling SSL, makes us need
less extra .a + .cc files, but does mean that APR can't be used
directly (since it got renamed), so just use PosixTimer where it was
used.
2013-11-25 15:36:30 -05:00
Jeff Kaufman ed14455412 valgrind: unflake cache purging test
Fixes #569.
2013-11-25 14:38:24 -05:00
Jeff Kaufman be4d263d10 valgrind: suppressions file might not be in current directory 2013-11-25 10:23:25 -05:00
Jeff Kaufman 0bafd6b7e0 Merge pull request #565 from pagespeed/oschaaf-valgrind
Valgrind: Add an automated test
2013-11-25 07:03:33 -08:00
Otto van der Schaaf 9bbe912bd7 Valgrind: Add an automated test
This makes nginx run in the background under valgrind,
with both a master and a child process.
Valgrind errors will be redirected to `valgrind.log`.
When `USE_VALGRIND` is set, all system tests will be run under valgrind,
and at the end a new test is appended which ensures no valgrind errors
where encountered.

It is also worth noting that:
- There is a new file, `valgrind.sup`, which contains a few suppressions.
- Some tests behave flakey under valgrind. For now these are appended
  to the expected failures (when under valgrind only).
- 'Possibly lost' errors are all suppressed to get the amount of false
  positives manageable.
2013-11-21 21:26:15 +01:00
Jeff Kaufman b78eb8a939 Merge pull request #567 from pagespeed/oschaaf-304-timeout
system-tests: Test keepalive behaviour after a 304 response
2013-11-21 11:05:18 -08:00
Otto van der Schaaf e082a01912 system-tests: Test keepalive behaviour after a 304 response 2013-11-20 23:15:14 +01:00
Jeff Kaufman fa5815e1e8 Merge pull request #560 from pagespeed/jefftk-fix-messages
messages: unbreak /ngx_pagespeed_messages
2013-11-12 11:51:57 -08:00
Jeff Kaufman f12af2f03b messages: unbreak /ngx_pagespeed_messages
The shared circular buffer wasn't hooked up fully, which meant loading
/ngx_pagespeed_messages didn't work.  This fixes that and adds a test.

I also noticed while adding this that the 'Handling of large files' test
wasn't set up properly, so I converted that to use start_test.

Fixing that exposed another bug where the 'Handling of large files' test
was actually failing but being marked as an expected failure by being
grouped in with the test above.  Adding `pagespeed MaxHtmlParseBytes 5000`
to the appropriate location made it test what it was supposed to be testing
again, and the underlying feature wasn't broken.
2013-11-12 13:11:12 -05:00
Jeff Kaufman e22fae46bc readme: use release 2013-11-08 11:41:53 -05:00
Jeff Kaufman 53a599fbd4 readme: recommend tmpfs for file cache 2013-11-08 11:36:16 -05:00
Jeff Kaufman 70c47c13a4 Merge pull request #557 from pagespeed/jefftk-fix-header-only
headers: don't special case header-only requests
2013-11-08 08:32:57 -08:00
Jeff Kaufman 8021751d69 headers: don't special case header-only requests
Fixes #537.
2013-11-08 11:21:52 -05:00
Jeff Kaufman 6b29b5220d Merge pull request #555 from pagespeed/jefftk-prepare-release-1.7.30.1-beta
trunk-tracking: update to 1.7.30.1 from r3581
2013-11-08 08:19:27 -08:00
Jeff Kaufman 07286005a6 trunk-tracking: update to 1.7.30.1 from r3581
Changes:
 * r3585: With downstream caching, don't touch `Cache-Control` headers.
   * No longer require `Modify Caching Headers off`.
   * Change from `modify_caching_headers` as a boolean to a three valued enum
     `PreserveCachingHeaders`.
 * r3596: Make tests less flaky.
   * Changes WGET_DUMP to write to WGET_DIR instead of OUTDIR.
 * r3597: Remove now-redundant system tests.
   * Some system tests were moved into `automatic/system_test.sh` which means we
     can remove our forks.
 * r3598: Enable the shared memory metadata cache by default.
   * The code change just worked and needed no changes, but it also added
     substantial tests, which needed some porting.
 * Deflake the `scrape stats` test by moving it before config reloading.
2013-11-07 17:47:37 -05:00
Jeff Kaufman 721c49dc71 release: version 1.6.29.7 -> 1.7.30.1 2013-11-07 17:47:07 -05:00
Jeff Kaufman 658a30d836 Merge branch 'master' into trunk-tracking 2013-11-07 17:46:30 -05:00
Jeff Kaufman 94688bd1e5 Merge pull request #556 from pagespeed/jefftk-increase-timeout
system-test: increase timeout for keepalive tests from 1s to 2s
2013-11-07 14:46:11 -08:00
Jeff Kaufman 26aaf221c7 system-test: increase timeout for keepalive tests from 1s to 2s
The keepalive tests were occasionally bumping up against
the 1s timeout we had set for curl, but a 1s 99.9% tail
latency is a little agressive.  Drop it to 2s to make the
tests less flaky.

What we really need is a proper load testing setup, so
the keepalive test isn't doing double-duty.
2013-11-07 17:36:56 -05:00
Jeff Kaufman 530bf3c05e prepare-psol: properly include generated console files 2013-11-06 16:38:10 -05:00
Jeff Kaufman dfedc6b025 merge commit 2013-11-06 15:20:40 -05:00
Jeff Kaufman 4e3fe6f35f readme: suggest restricting the global statistics handler 2013-10-29 17:06:50 -04:00
Jeff Kaufman af6706a4c9 Merge pull request #550 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: update to r3581 (from r3537)
2013-10-29 06:46:47 -07:00
Jeff Kaufman b6c3001df2 trunk-tracking: update to r3581 (from r3537) 2013-10-28 16:52:56 -04:00
Jeff Kaufman b8ff84ed9b Factor out handling for errors, stats, and logs. Add nosniff protection. 2013-10-28 10:15:03 -04:00
Jeff Kaufman b83bb636f0 Factor out handling for errors, stats, and logs. Add nosniff protection. 2013-10-28 10:09:24 -04:00
Jeff Kaufman 7d6b6c4b4c versions: 1.6.29.5 -> 1.6.29.7 2013-10-28 09:59:45 -04:00
Jeff Kaufman 2629865c59 versions: 1.6.29.5 -> 1.6.29.7 2013-10-28 09:58:19 -04:00
Jeff Kaufman fd546f270b readme: 1.4.3 is stable 2013-10-23 16:25:36 -04:00
Jeff Kaufman 641fb971d1 merge commit 2013-10-23 11:07:05 -04:00
Jeff Kaufman e40cde221c Merge pull request #547 from pagespeed/jefftk-fix-dir-permissions
paths: don't require existence
2013-10-23 07:26:54 -07:00
Jeff Kaufman f956ef92e9 paths: don't require existence
Create paths for FileCachePath and LogDir if they don't exist yet and give
them proper permissions.
2013-10-22 16:47:49 -04:00
Jeff Kaufman 687e0a7028 readme: reword the canonicalize_javascript_libraries note 2013-10-21 13:26:26 -04:00
Jeff Kaufman 7c15cd83f4 canonicalize libraries: script to convert from Apache format to Nginx
Merge of Vid's #533 with some fixes.
2013-10-21 13:21:28 -04:00
Jeff Kaufman 8f6ac0660e Merge pull request #543 from pagespeed/oschaaf-shared-mem-trunk-tracking
trunk-tracking: update to build with mps r3537
2013-10-18 08:37:45 -07:00
Otto van der Schaaf 422d5afa6b trunk-tracking: update to build with mps r3537 2013-10-18 11:46:09 +02:00
Jeff Kaufman f653094040 Merge pull request #536 from pagespeed/jefftk-vlogs
logging: restore call to log_message_handler::Install()
2013-10-07 07:47:36 -07:00
Jeff Kaufman 8430a6c40e logging: remove unused constant 2013-10-04 17:52:35 -04:00
Jeff Kaufman d4fa76463d logging: restore call to log_message_handler::Install()
I missed this when moving shared components to SystemRewriteDriverFactory;
this call used to be in NgxRewriteDriverFactory::RootInit.  Without it we only
log VLOG(0), not VLOG(1) and VLOG(2) the way Apache does.

Fixes #518.
2013-10-04 17:50:19 -04:00
Jeff Kaufman 1e5769df11 Merge pull request #535 from pagespeed/jefftk-close-connection-v3
logging: fix use-after-free
2013-10-04 10:42:47 -07:00
Jeff Kaufman f1a800d37f logging: fix use-after-free
The pagespeed_connection needs a log to write to, but unfortunately
r->connection->log isn't guaranteed to still be around for the whole
lifetime of the pagespeed_connection.  Use the log from the server
context instead.

Fixes issue #522.
2013-10-04 13:21:42 -04:00
Jeff Kaufman ee4958e7dd Merge pull request #530 from pagespeed/oschaaf-process-context
Use net_instaweb::ProcessContext
2013-10-01 14:19:55 -07:00
Jeff Kaufman dbead4a62e Merge pull request #529 from pagespeed/jefftk-ipro-headers
ipro: support calling ps_in_place_body_filter multiple times
2013-09-25 08:21:42 -07:00
Jeff Kaufman 2b2d19e78d ipro: support calling ps_in_place_body_filter multiple times
Fixes #520
2013-09-25 11:21:33 -04:00
Jeff Kaufman 9ed9fecc0f ipro: fix typo: 2013-09-25 10:07:50 -04:00
Jeff Kaufman 06e64dec7a Merge pull request #531 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: update to r3508
2013-09-25 07:03:39 -07:00
Jeff Kaufman 420b58c346 trunk-tracking: update to r3508
No major changes that we need to be compatible with.  r3508 tweaks
InPlaceResourceRecorder::DoneAndSetHeaders so that we can now make sure to
release it: the recorder is allocated in ps_in_place_check_header_filter and
released in ps_in_place_body_filter, but if there's an error in between it will
be leaked.  We know ps_release_request_context will get run regardless because
it's set as a cleanup handler, so clean up the recorder there.

Fixes #527
2013-09-24 17:19:06 -04:00
Jeff Kaufman 36554ce92f merging: accidentally restored obselete NgxThreadSystem 2013-09-24 17:09:37 -04:00
Otto van der Schaaf c5265b47cf Use net_instaweb::ProcessContext
This fixes a few valgrind errors on shutdown, plus a potential
issue when url_util.cc would lazily initialize in a thread-unsafe
manner. Also adds --leak-check=full to the suggested valgrind
command for the system tests.
2013-09-24 23:09:14 +02:00
Jeff Kaufman c29ac1e6a3 merge commit 2013-09-24 16:16:16 -04:00
Jeff Kaufman 6e86835599 Merge pull request #528 from pagespeed/jud-gcc48
Fix GCC 4.8 build errors
2013-09-24 13:11:42 -07:00
Jud Porter f70eb5df40 Add -Wno-unused-local-typedefs and -Wno-error to CFLAGS to fix build issues on GCC 4.8. 2013-09-24 15:59:56 -04:00
Jeff Kaufman 4650aa4a3f Merge pull request #508 from pagespeed/jefftk-backport-reload-fix
reloading: backport reloading fix
2013-09-24 07:21:14 -07:00
Jeff Kaufman 34e3101edd reloading: backport reloading fix
Issue #364 was fixed upstream in r3492.  Backport the fix to master.

"We only need to shut down the caches in child processes because they are not
started in the master process.  This wasn't a problem before, but shutting down
the caches can start a thread which isn't safe to do in the master process of a
forking server like Nginx."

Also backport the change from r3497 where we use a DCHECK for
may_start_threads_.  It's bad to start threads in the root process, but it's not
worth crashing a production server over.
2013-09-13 10:11:51 -04:00
Jeff Kaufman fdbdf11bab Merge pull request #506 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: update from 3485 to 3497
2013-09-13 07:02:31 -07:00
Jeff Kaufman db238e7705 trunk-tracking: update from 3485 to 3497
* Remove NgxThreadSystem because there's now a SystemThreadSystem that
  has everything we need.
* fixes https://github.com/pagespeed/ngx_pagespeed/issues/364
2013-09-12 17:33:14 -04:00
Jeff Kaufman a196cfe071 Merge branch 'master' into trunk-tracking 2013-09-12 11:27:40 -04:00
Jeff Kaufman 442d319aef Merge pull request #505 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: update to r3485
2013-09-12 08:27:00 -07:00
Jeff Kaufman a48c243e3e config: fix typo in FLAG_MARCH 2013-09-11 09:51:12 -04:00
Jeff Kaufman 5c17cb671c trunk-tracking: update to r3485
* Adds IPRO tests that we should have copied from apache_system_test.sh back
  when we first added IPRO.
  * The "IPRO-optimized resources should have fixed size, not chunked" test
    fails.  The problem is as it says: IPRO optimized resources are being sent
    out with `Transfer-Encoding: Chunked` instead of `Content-Length: ...`.  How
    do we fix this?
* install/system_test.sh moved to net/instaweb/automatic/system_test.sh
* minor method signature changes
* url.is_valid() is gone, replaced by .IsWebValid()
* I pushed Otto's #464 upstream, and now we need to make some IPRO changes.
* beacons have nonces now, so we need to update tests.
2013-09-10 16:57:44 -04:00
Jeff Kaufman 94d004e72c Merge pull request #504 from yaoweibin/march_i686
fixed the dynamic link problem with tengine in i686 box.
2013-09-10 08:16:31 -07:00
Weibin Yao 21a9705b78 fixed the dynamic link problem with tengine in i686 box.
The compiler needs to know that __sync_add_and_fetch_4 is ok,
and this requires an instruction that didn't exist on i586 or i386.
2013-09-10 22:59:37 +08:00
Jeff Kaufman 137182792e Merge pull request #499 from pagespeed/jefftk-simplify-handlers
handlers: collect redundant handler information
2013-08-30 06:23:16 -07:00
Jeff Kaufman 3dbb845603 handlers: collect redundant handler information
Create ps_simple_handler to combine haandling for static content, statistics,
console, and messages.
2013-08-29 16:04:22 -04:00
Jeff Kaufman ac7a6bce2c Merge pull request #498 from pagespeed/jefftk-code-cleanup
code cleanup
2013-08-29 09:51:04 -07:00
Jeff Kaufman 9baf3d01d3 code cleanup
Get rid of net_instaweb:: everywhere.  By eliminating the ngx_psol namespace we
can stop prefixing everything in ngx_pagespeed.cc with net_instaweb::

Fix other minor style issues.

Remove unnecessary declarations.

Rename ps_create_request_context to ps_route_request and CreateRequestContext to
RequestRouting because it no longer creates the request context.
2013-08-29 09:53:05 -04:00
Jeff Kaufman 1db13030fa trunk-tracking: update from r3403 to r3457
Statistics reporting is now handled in system/ but we need to call in.
2013-08-29 09:03:11 -04:00
Jeff Kaufman be2fb57d85 Merge pull request #495 from pagespeed/jefftk-cleanup-property-cache-lookup
property-cache: use ProxyFetchFactory::InitiatePropertyCacheLookup
2013-08-28 08:29:28 -07:00
Jeff Kaufman 3a99b9adff property-cache: use ProxyFetchFactory::InitiatePropertyCacheLookup 2013-08-28 09:37:47 -04:00
Jeff Kaufman 8cb48034f0 Merge pull request #494 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: update to r3448 from r3403
2013-08-28 06:34:49 -07:00
Jeff Kaufman 49c96c9202 trunk-tracking: update to r3448 from r3403
As of r3447 ServerContext::ChildInit is now in system/, which means we can
delete a lot of code.

DangerFetchFromUnknownHosts and FetchWithGzip are now handled by RewriteOptions.

ServerContext now needs a hostname and port, but we don't have one so we
hackishly provide a different unique id.
2013-08-27 14:10:09 -04:00
Jeff Kaufman ad2ea9498b Merge branch 'master' into trunk-tracking 2013-08-27 13:50:47 -04:00
Jeff Kaufman 3a085e114d Merge pull request #480 from pagespeed/jefftk-update-trunk-tracking
Adjust for fetchers and options that moved from apache/ to system/ in r3390
2013-08-27 07:41:24 -07:00
Jeff Kaufman 3fbb740101 Merge pull request #490 from pagespeed/new-trunk-tracking-rotation
Removing redundant X-Cache header handling.
2013-08-21 09:49:44 -07:00
Anupama Dutta fa99ac39b4 Removing redundant X-Cache header handling.
X-Cache handling is not needed because the pagespeed server never gets to see
a request with X-Cache header added by its downstream cache. X-Cache headers
are only to be added in responses served out of the downstream cache for debugging
purposes only. This piece of deleted code was also conflicting with X-Cache
headers present on upstream caches (wrt pagespeed) and hence not optimizing responses
that happened to carry this header.

(More details are present in https://github.com/pagespeed/ngx_pagespeed/issues/488)
2013-08-21 10:57:48 -04:00
Jeff Kaufman d0de777452 Merge pull request #484 from pagespeed/jefftk-base-fetch-request-headers
headers: simplify header setting
2013-08-09 15:56:46 -07:00
Jeff Kaufman eb9979f048 headers: simplify header setting
* Remove PopulateRequestHeaders() and PopulateResponseHeaders().
* Set stop copying request headers to the base fetch twice.
  * This fixes a dcheck failure in the debug build.
2013-08-09 14:10:18 -04:00
Jeff Kaufman c57c16c499 trunk-tracking: update to r3402
Adjust for fetchers and options that moved from apache/ to system/ in r3390.

Use AllocateFetcher() hook from r3402 to put the native fetcher into the fetcher
map maintained by the SystemRewriteDriverFactory.
2013-08-08 10:49:34 -04:00
Jeff Kaufman 70284c987e Merge pull request #477 from pagespeed/jefftk-style
style: indentation and other minor style fixes
2013-08-06 07:46:14 -07:00
Jeff Kaufman 64f2ab6591 style: indentation and other minor style fixes 2013-08-06 10:07:49 -04:00
Jeff Kaufman c739bf29c4 Merge branch 'master' into trunk-tracking 2013-08-05 17:30:36 -04:00
Jeff Kaufman bb1093e8b2 Merge pull request #469 from pagespeed/jefftk-update-trunk-tracking
trunk-tracking: take advantage of new functionality in system/
2013-08-05 14:24:25 -07:00
Jeff Kaufman 51eaeddfba trunk-tracking: update apache_system_test for minor changes in r3369 and r3374 2013-08-05 17:23:23 -04:00
Jeff Kaufman 122c234570 trunk-tracking: adjust for big changes from r3366
SystemRewriteDriverFactory was expanded by r3366 to do a lot of what
NgxRewriteDriverFactory used to have to do.  Take advantage of this and
simplifiy our code.
2013-08-05 11:22:58 -04:00
Jeff Kaufman ddf844b680 Merge pull request #473 from pagespeed/oschaaf-response-header-options
response-header-options: consider the response headers for options
2013-08-05 08:06:34 -07:00
Otto van der Schaaf a245f40bcf Merge pull request #472 from pagespeed/oschaaf-native-fetcher-timeouts
native-fetcher: timeouts
2013-08-05 07:57:44 -07:00
Otto van der Schaaf cafb06c011 native-fetcher: timeouts
After more testing, it turns out that the timer that is initially set
in Init() remains active throughout the whole lifetime of the fetch.

This reverts the previous change, which isn't correct, and replaces
all TODO's concerning timers with a comment about that we don't need
them.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/466
2013-08-05 16:57:02 +02:00
Otto van der Schaaf cbfbb5b6d6 response-header-options: consider the response headers for options
Take the response headers into account when determining the options
for the request. Also adds tests for this.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/356
2013-08-05 16:42:49 +02:00
Jeff Kaufman 606a75a068 Merge pull request #474 from pagespeed/oschaaf-max-buffer-size
max-buffer-size: use ngx_pagesize
2013-08-05 04:44:38 -07:00
Jeff Kaufman 0c26aafc2f Merge pull request #471 from pagespeed/oschaaf-pointer-declaration-style
pointer-declaration-style: fix style issues
2013-08-05 04:32:47 -07:00
Otto van der Schaaf 8bd4ed2ec2 max-buffer-size: use ngx_pagesize
Other modules seem to use ngx_pagesize as the default buffer size:
http://lxr.evanmiller.org/http/source/http/modules/ngx_http_gunzip_filter_module.c#L661
2013-08-05 10:33:47 +02:00
Otto van der Schaaf 9c5fb3107e pointer-declaration-style: fix style issues 2013-08-04 15:25:26 +02:00
Otto van der Schaaf 1c86ab66be Merge pull request #465 from pagespeed/oschaaf-native-fetcher-crash
native-fetcher: fix a crasher, and set a timeout
2013-08-03 00:06:13 -07:00
Otto van der Schaaf f05e3cf281 native-fetcher: fix a crasher, and set a timeout
Handle the case where ngx_event_connect_peer didn't return NGX_OK.
Also replace a TODO for adding a timer with actually adding the
timer.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/463
2013-08-01 15:39:02 +02:00
Jeff Kaufman 177b70b995 Merge pull request #460 from pagespeed/oschaaf-test-accidental-quotes
system-test: remove a few stray quotes
2013-07-30 13:53:29 -07:00
Otto van der Schaaf 3b2b28559a system-test: remove a few stray quotes
This fixes nginx's complaints about receiving invalid headers after
running the system tests.
2013-07-30 22:43:39 +02:00
Jeff Kaufman 7e89db8fa1 trunk-tracking: in_place_resource_recorder changes 2013-07-30 15:38:42 -04:00
Jeff Kaufman 9b3ab25cea Merge branch 'master' into trunk-tracking 2013-07-30 15:27:53 -04:00
Otto van der Schaaf 54ef25214c Merge pull request #457 from pagespeed/oschaaf-modify-headers
header-handling: ModifyCachingheaders & Content-Encoding
2013-07-30 12:19:46 -07:00
Otto van der Schaaf b9db498199 header-handling: ModifyCachingHeaders & Content-Encoding
- Change header handling for ModifyCachingHeaders
- Don't copy over response headers which have their hash set to 0
- Don't invent a date header
2013-07-30 21:14:49 +02:00
Jeff Kaufman 6503ebfb1a merge commit 2013-07-30 14:30:55 -04:00
Jeff Kaufman baf35dc906 Merge pull request #458 from pagespeed/jud-trunk-tracking
Trunk tracking updates
2013-07-26 12:14:24 -07:00
Jud Porter f4466918f3 System test changes to align with latest mod_pagespeed trunk. 2013-07-26 14:54:02 -04:00
Jeff Kaufman 3b6caa38aa release: merging readme changes for 1.6.29.5 2013-07-25 14:31:45 -04:00
Jeff Kaufman b1127c2a01 release: 1.6.29.5 2013-07-25 13:56:28 -04:00
Jeff Kaufman ad6429d26f ipro: support in-place resource optimization
Squash-merge of chaizhenhua's work over many pull requests, especially #450.

The copy of in_place_resource_recorder.cc is temporary and can be removed after
the next PSOL release.
2013-07-24 10:45:39 -04:00
Jeff Kaufman 59cdafaf70 Merge pull request #454 from pagespeed/oschaaf-force-caching
force-caching: fix configuration handling
2013-07-24 07:15:40 -07:00
Otto van der Schaaf 34ebc2d179 force-caching: fix configuration handling
Make pagespeed ForceCaching [on|off] work
2013-07-23 13:12:24 +02:00
Otto van der Schaaf 49c9de63cd Merge pull request #448 from pagespeed/oschaaf-log-vhost-specific
logging: respect error_log in nginx.conf server blocks
2013-07-23 01:52:34 -07:00
Otto van der Schaaf 502a604a26 logging: respect error_log in nginx.conf server blocks
This makes messages written via the NgxMessageHandler from the
NgxServerContext be written with the nginx error_log configuration
specified at the server{} level, if specified.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/447
2013-07-23 10:51:47 +02:00
Jeff Kaufman fca58f2d6f Merge pull request #444 from morlovich/morlovich-trunk-tracking-20130719
trunk-tracking: merge with MPS trunk as of 2003-07-19
2013-07-22 07:13:31 -07:00
Jeff Kaufman b2bbdcc0df Merge pull request #443 from patschi/patch-2
readme: recommend nginx 1.4.2 stable
2013-07-22 07:05:20 -07:00
Otto van der Schaaf bdb5de5a2f Merge pull request #446 from pagespeed/oschaaf-missing-beacon-urls
system-tests: fix missing beacon urls
2013-07-22 04:56:18 -07:00
Otto van der Schaaf 960d0940bb system-tests: fix missing beacon url parameters in tests
Fix 2 tests on the beacon by adding the missing url parameter
2013-07-21 14:20:16 +02:00
Otto van der Schaaf e7a91c2f0a Merge pull request #445 from pagespeed/oschaaf-fix-keepalive-test-gzip
keepalive-test: fix gzip accept encoding
2013-07-20 03:11:06 -07:00
Otto van der Schaaf e583afdb49 keepalive-test: fix gzip accept encoding
We would send "Accept-Encoding:gzip" in the request headers. NGINX
would mark that as an invalid header, as it misses a space after ':'
2013-07-20 09:06:38 +02:00
Maks Orlovich 53138d7b34 Merge with MPS trunk as of 2003-07-19
This has 2 families of changes:
- Port to changes in PropertyCache API
- Update to a MapProxyDomain test.
2013-07-19 14:28:46 -04:00
Patschi e45acf4613 nginx 1.4.2 stable released
Changelog: http://nginx.org/en/CHANGES-1.4
2013-07-19 14:45:21 +02:00
Otto van der Schaaf 47e3364332 Merge pull request #439 from pagespeed/oschaaf-shutdown-fix
shutdown: fix segfault when shutting down a worker process
2013-07-18 14:21:12 -07:00
Otto van der Schaaf 49760f03a0 shutdown: fix a crash when shutting down a worker process
Remove the deferred cleanup, as in ngx_pagespeed the fetcher
is owned by the RewriteDriverFactory.

Fixes the backtrace pointing to
net_instaweb::RewriteDriverFactory::Deleter
at https://github.com/pagespeed/ngx_pagespeed/issues/367
2013-07-18 23:20:03 +02:00
Jud Porter 2f5afcddd1 Merge pull request #440 from pagespeed/anupama-updates-to-trunk-tracking
Updating trunk-tracking to be in sync with r3298.
2013-07-15 11:05:43 -07:00
Anupama Dutta 67beee1444 Updating trunk-tracking to be in sync with r3298.
Fixes to allow ngx_pagespeed trunk-tracking branch to compile and work with r3298 mod_pagespeed revision:
- Config fix to include path for critical_keys.pb.h.
- Make changes needed due to RewriteOptions refactoring done in https://code.google.com/p/modpagespeed/source/detail?r=3226
2013-07-15 13:20:14 -04:00
Jeff Kaufman cd80e92df1 Merge pull request #435 from pagespeed/oschaaf-refactor-static-handler
static-handler: refactor to use write_handler_response
2013-07-12 13:33:30 -07:00
Otto van der Schaaf e303c92041 Merge pull request #437 from pagespeed/oschaaf-downstream-cache-fix-test
downstream-cache-test: don't hard code the port to 8051
2013-07-12 09:26:47 -07:00
Otto van der Schaaf ccd36dd658 downstream-cache-test: don't hard code the port to 8051 2013-07-12 18:21:55 +02:00
Otto van der Schaaf 3a9953e25c static-handler: refactor to use write_handler_response
This fixes sending out the weak ETag for ngx_pagespeed_static/js_defer.hash.js,
and simplifies things somewhat for this code path.
It also adds a test for it.

Fixes https://github.com/pagespeed/ngx_pagespeed/issues/434
2013-07-12 18:12:13 +02:00
Jeff Kaufman 311ea897cf Merge pull request #436 from pagespeed/jefftk-simplify-option-setting
options: refactor repeated code in option setting
2013-07-12 07:55:07 -07:00
Jeff Kaufman 4cc3e4def3 options: refactor repeated code in option setting 2013-07-12 10:44:34 -04:00
40 changed files with 6855 additions and 4763 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
test/tmp test/tmp
psol/ psol/
psol-*.tar.gz psol-*.tar.gz
*.*.*.*.tar.gz
+6 -85
View File
@@ -19,94 +19,15 @@ optimizations, see our <a href="http://ngxpagespeed.com">demonstration site</a>.
## How to build ## How to build
Because nginx does not support dynamic loading of modules, you need to compile Follow the steps on <a
nginx from source to add ngx_pagespeed. Alternatively, if you're using Tengine you can [install ngx_pagespeed without href="https://developers.google.com/speed/pagespeed/module/build_ngx_pagespeed_from_source">build
recompiling Tengine](https://github.com/pagespeed/ngx_pagespeed/wiki/Using-ngx_pagespeed-with-Tengine). ngx_pagespeed from source</a>.
1. Install dependencies:
```bash
# These are for RedHat, CentOS, and Fedora.
$ sudo yum install gcc-c++ pcre-dev pcre-devel zlib-devel make
# These are for Debian. Ubuntu will be similar.
$ sudo apt-get install build-essential zlib1g-dev libpcre3 libpcre3-dev
```
2. Download ngx_pagespeed:
```bash
$ cd ~
$ wget https://github.com/pagespeed/ngx_pagespeed/archive/release-1.6.29.3-beta.zip
$ unzip release-1.6.29.3-beta.zip # or unzip release-1.6.29.3-beta
$ cd ngx_pagespeed-release-1.6.29.3-beta/
$ wget https://dl.google.com/dl/page-speed/psol/1.6.29.3.tar.gz
$ tar -xzvf 1.6.29.3.tar.gz # expands to psol/
```
3. Download and build nginx:
```bash
$ # check http://nginx.org/en/download.html for the latest version
$ wget http://nginx.org/download/nginx-1.4.1.tar.gz
$ tar -xvzf nginx-1.4.1.tar.gz
$ cd nginx-1.4.1/
$ ./configure --add-module=$HOME/ngx_pagespeed-release-1.6.29.3-beta
$ make
$ sudo make install
```
If this doesn't work see the [build
troubleshooting](https://github.com/pagespeed/ngx_pagespeed/wiki/Build-Troubleshooting) page.
This will use a binary PageSpeed Optimization Library, but it's also possible to
[build PSOL from
source](https://github.com/pagespeed/ngx_pagespeed/wiki/Building-PSOL-From-Source).
Note: ngx_pagespeed currently doesn't support Windows or MacOS because the
underlying PSOL library doesn't.
## How to use ## How to use
In your `nginx.conf`, add to the main or server block: Follow the steps on <a
href="https://developers.google.com/speed/pagespeed/module/configuration">PageSpeed
```nginx configuration</a>.
pagespeed on;
# needs to exist and be writable by nginx
pagespeed FileCachePath /var/ngx_pagespeed_cache;
```
In every server block where pagespeed is enabled add:
```apache
# Ensure requests for pagespeed optimized resources go to the pagespeed
# handler and no extraneous headers get set.
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { add_header "" ""; }
location ~ "^/ngx_pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon$" { }
location /ngx_pagespeed_statistics { allow 127.0.0.1; deny all; }
location /ngx_pagespeed_message { allow 127.0.0.1; deny all; }
location /pagespeed_console { allow 127.0.0.1; deny all; }
```
To confirm that the module is loaded, fetch a page and check that you see the
`X-Page-Speed` header:
```bash
$ curl -I 'http://localhost:8050/some_page/' | grep X-Page-Speed
X-Page-Speed: 1.6.29.3-...
```
Looking at the source of a few pages you should see various changes, such as
urls being replaced with new ones like `yellow.css.pagespeed.ce.lzJ8VcVi1l.css`.
For complete documentation, see [Using
PageSpeed](https://developers.google.com/speed/pagespeed/module/using).
There are extensive system tests which cover most of ngx_pagespeed's
functionality. Consider [testing your
installation](https://github.com/pagespeed/ngx_pagespeed/wiki/Testing).
For feedback, questions, and to follow For feedback, questions, and to follow
the progress of the project: the progress of the project:
+155 -53
View File
@@ -17,6 +17,8 @@
# PSOL_BINARY: absolute path to pagespeed_automatic.a # PSOL_BINARY: absolute path to pagespeed_automatic.a
mod_pagespeed_dir="${MOD_PAGESPEED_DIR:-unset}" mod_pagespeed_dir="${MOD_PAGESPEED_DIR:-unset}"
position_aux="${POSITION_AUX:-unset}"
if [ "$mod_pagespeed_dir" = "unset" ] ; then if [ "$mod_pagespeed_dir" = "unset" ] ; then
mod_pagespeed_dir="$ngx_addon_dir/psol/include" mod_pagespeed_dir="$ngx_addon_dir/psol/include"
build_from_source=false build_from_source=false
@@ -27,8 +29,8 @@ if [ "$mod_pagespeed_dir" = "unset" ] ; then
echo " You need to separately download the pagespeed library:" echo " You need to separately download the pagespeed library:"
echo "" echo ""
echo " $ cd /path/to/ngx_pagespeed" echo " $ cd /path/to/ngx_pagespeed"
echo " $ wget https://dl.google.com/dl/page-speed/psol/1.6.29.3.tar.gz" echo " $ wget https://dl.google.com/dl/page-speed/psol/1.10.33.4.tar.gz"
echo " $ tar -xzvf 1.6.29.3.tar.gz # expands to psol/" echo " $ tar -xzvf 1.10.33.4.tar.gz # expands to psol/"
echo "" echo ""
echo " Or see the installation instructions:" echo " Or see the installation instructions:"
echo " https://github.com/pagespeed/ngx_pagespeed#how-to-build" echo " https://github.com/pagespeed/ngx_pagespeed#how-to-build"
@@ -39,20 +41,6 @@ else
build_from_source=true build_from_source=true
fi fi
echo "mod_pagespeed_dir=$mod_pagespeed_dir"
echo "build_from_source=$build_from_source"
ngx_feature="psol"
ngx_feature_name=""
ngx_feature_run=no
ngx_feature_incs="
#include \"net/instaweb/htmlparse/public/html_parse.h\"
#include \"net/instaweb/htmlparse/public/html_writer_filter.h\"
#include \"net/instaweb/util/public/string.h\"
#include \"net/instaweb/util/public/string_writer.h\"
#include \"net/instaweb/util/public/null_message_handler.h\"
"
os_name='unknown_os' os_name='unknown_os'
arch_name='unknown_arch' arch_name='unknown_arch'
uname_os=`uname` uname_os=`uname`
@@ -83,9 +71,81 @@ else
buildtype=Release buildtype=Release
fi fi
# Building with HTTPS fetching enabled pulls in a version of OpenSSL that causes # If the compiler is gcc, we want to use g++ to link, if at all possible,
# linker errors, so disable it here. # so that -static-libstdc++ works.
CFLAGS="$CFLAGS -DSERF_HTTPS_FETCHING=0" # Annoyingly, the feature test doesn't even use $LINK for linking, so that
# needs an explicit -lstdc++
pagespeed_libs=
ps_maybe_gpp_base=`basename $CC| sed s/gcc/g++/`
ps_maybe_gpp="`dirname $CC`/$ps_maybe_gpp_base"
if [ -n "$NGX_GCC_VER" -a \( -x "$ps_maybe_gpp" \) ]; then
LINK=$ps_maybe_gpp
NGX_TEST_LD_OPT="$NGX_TEST_LD_OPT -lstdc++"
else
pagespeed_libs="-lstdc++"
fi
# The compiler needs to know that __sync_add_and_fetch_4 is ok,
# and this requires an instruction that didn't exist on i586 or i386.
if [ "$uname_arch" = "i686" ]; then
FLAG_MARCH='-march=i686'
fi
CFLAGS="$CFLAGS $FLAG_MARCH"
# For now, standardize on gcc-4.x ABI --- if we don't set this, people building
# with new gcc defaulting to gcc-5 C++11 ABI will have build trouble linking
# to our libpsol.a
# See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
CFLAGS="$CFLAGS -D_GLIBCXX_USE_CXX11_ABI=0"
CC_TEST_FLAGS="$CC_TEST_FLAGS -D_GLIBCXX_USE_CXX11_ABI=0"
case "$NGX_GCC_VER" in
4.8*)
# On GCC 4.8 and above, -Wall enables -Wunused-local-typedefs. This breaks
# on VerifySizesAreEqual in bit_cast in chromium/src/base/basictypes.h which
# has a typedef that is intentionally unused.
CFLAGS="$CFLAGS -Wno-unused-local-typedefs"
# On GCC 4.8 and above, we get the following compiler warning:
# chromium/src/base/memory/scoped_ptr.h:133:7: warning: declaration of class scoped_ptr<C> [enabled by default]
# Based on discussion at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54055,
# this is invalid code, but hasn't been fixed yet in chromium.
# Unfortunately, there also does not appear to be a flag for just disabling
# that warning, so we add Wno-error to override nginx's default -Werror
# option.
CFLAGS="$CFLAGS -Wno-error"
;;
esac
if [ "$WNO_ERROR" = "YES" ]; then
CFLAGS="$CFLAGS -Wno-error"
fi
psol_binary="${PSOL_BINARY:-unset}"
if [ "$psol_binary" = "unset" ] ; then
if $build_from_source ; then
psol_binary="\
$mod_pagespeed_dir/pagespeed/automatic/pagespeed_automatic.a"
else
psol_library_dir="$ngx_addon_dir/psol/lib/$buildtype/$os_name/$arch_name"
psol_binary="$psol_library_dir/pagespeed_automatic.a"
fi
fi
echo "mod_pagespeed_dir=$mod_pagespeed_dir"
echo "build_from_source=$build_from_source"
ngx_feature="psol"
ngx_feature_name=""
ngx_feature_run=no
ngx_feature_incs="
#include \"pagespeed/kernel/base/string.h\"
#include \"pagespeed/kernel/base/string_writer.h\"
#include \"pagespeed/kernel/base/null_message_handler.h\"
#include \"pagespeed/kernel/html/html_parse.h\"
#include \"pagespeed/kernel/html/html_writer_filter.h\"
"
pagespeed_include="\ pagespeed_include="\
$mod_pagespeed_dir \ $mod_pagespeed_dir \
@@ -95,30 +155,17 @@ pagespeed_include="\
$mod_pagespeed_dir/third_party/protobuf/src \ $mod_pagespeed_dir/third_party/protobuf/src \
$mod_pagespeed_dir/third_party/re2/src \ $mod_pagespeed_dir/third_party/re2/src \
$mod_pagespeed_dir/out/$buildtype/obj/gen \ $mod_pagespeed_dir/out/$buildtype/obj/gen \
$mod_pagespeed_dir/out/$buildtype/obj/gen/protoc_out/instaweb \
$mod_pagespeed_dir/third_party/apr/src/include \ $mod_pagespeed_dir/third_party/apr/src/include \
$mod_pagespeed_dir/third_party/aprutil/src/include \ $mod_pagespeed_dir/third_party/aprutil/src/include \
$mod_pagespeed_dir/third_party/apr/gen/arch/$os_name/$arch_name/include \ $mod_pagespeed_dir/third_party/apr/gen/arch/$os_name/$arch_name/include \
$mod_pagespeed_dir/third_party/aprutil/gen/arch/$os_name/$arch_name/include" $mod_pagespeed_dir/third_party/aprutil/gen/arch/$os_name/$arch_name/include"
ngx_feature_path="$pagespeed_include" ngx_feature_path="$pagespeed_include"
if $build_from_source ; then pagespeed_libs="$pagespeed_libs $psol_binary -lrt -pthread -lm"
psol_library_binaries="\
$mod_pagespeed_dir/net/instaweb/automatic/pagespeed_automatic.a \
$mod_pagespeed_dir/out/$buildtype/obj.target/third_party/serf/libserf.a \
$mod_pagespeed_dir/out/$buildtype/obj.target/third_party/aprutil/libaprutil.a \
$mod_pagespeed_dir/out/$buildtype/obj.target/third_party/apr/libapr.a"
else
psol_library_dir="$ngx_addon_dir/psol/lib/$buildtype/$os_name/$arch_name"
psol_library_binaries="\
$psol_library_dir/pagespeed_automatic.a \
$psol_library_dir/libserf.a \
$psol_library_dir/libaprutil.a \
$psol_library_dir/libapr.a"
fi
pagespeed_libs="-lstdc++ $psol_library_binaries -lrt -pthread -lm"
ngx_feature_libs="$pagespeed_libs" ngx_feature_libs="$pagespeed_libs"
ngx_feature_test=" ngx_feature_test="
GoogleString output_buffer; GoogleString output_buffer;
net_instaweb::StringWriter write_to_string(&output_buffer); net_instaweb::StringWriter write_to_string(&output_buffer);
@@ -146,48 +193,103 @@ if [ $ngx_found = yes ]; then
$ps_src/log_message_handler.h \ $ps_src/log_message_handler.h \
$ps_src/ngx_base_fetch.h \ $ps_src/ngx_base_fetch.h \
$ps_src/ngx_caching_headers.h \ $ps_src/ngx_caching_headers.h \
$ps_src/ngx_event_connection.h \
$ps_src/ngx_fetch.h \ $ps_src/ngx_fetch.h \
$ps_src/ngx_gzip_setter.h \
$ps_src/ngx_list_iterator.h \ $ps_src/ngx_list_iterator.h \
$ps_src/ngx_message_handler.h \ $ps_src/ngx_message_handler.h \
$ps_src/ngx_pagespeed.h \ $ps_src/ngx_pagespeed.h \
$ps_src/ngx_request_context.h \
$ps_src/ngx_rewrite_driver_factory.h \ $ps_src/ngx_rewrite_driver_factory.h \
$ps_src/ngx_rewrite_options.h \ $ps_src/ngx_rewrite_options.h \
$ps_src/ngx_server_context.h \ $ps_src/ngx_server_context.h \
$ps_src/ngx_thread_system.h \
$ps_src/ngx_url_async_fetcher.h \ $ps_src/ngx_url_async_fetcher.h \
$ps_src/pthread_shared_mem.h" $psol_binary"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
$ps_src/log_message_handler.cc \ $ps_src/log_message_handler.cc \
$ps_src/ngx_base_fetch.cc \ $ps_src/ngx_base_fetch.cc \
$ps_src/ngx_caching_headers.cc \ $ps_src/ngx_caching_headers.cc \
$ps_src/ngx_event_connection.cc \
$ps_src/ngx_fetch.cc \ $ps_src/ngx_fetch.cc \
$ps_src/ngx_gzip_setter.cc \
$ps_src/ngx_list_iterator.cc \ $ps_src/ngx_list_iterator.cc \
$ps_src/ngx_message_handler.cc \ $ps_src/ngx_message_handler.cc \
$ps_src/ngx_pagespeed.cc \ $ps_src/ngx_pagespeed.cc \
$ps_src/ngx_request_context.cc \
$ps_src/ngx_rewrite_driver_factory.cc \ $ps_src/ngx_rewrite_driver_factory.cc \
$ps_src/ngx_rewrite_options.cc \ $ps_src/ngx_rewrite_options.cc \
$ps_src/ngx_server_context.cc \ $ps_src/ngx_server_context.cc \
$ps_src/ngx_thread_system.cc \ $ps_src/ngx_url_async_fetcher.cc"
$ps_src/ngx_url_async_fetcher.cc \ # Save our sources in a separate var since we may need it in config.make
$ps_src/pthread_shared_mem.cc \ PS_NGX_SRCS="$NGX_ADDON_SRCS"
$mod_pagespeed_dir/out/$buildtype/obj/gen/data2c_out/instaweb/net/instaweb/system/console_out.cc \
$mod_pagespeed_dir/out/$buildtype/obj/gen/data2c_out/instaweb/net/instaweb/system/console_css_out.cc \ if [ "$position_aux" = "true" ] ; then
$mod_pagespeed_dir/net/instaweb/system/add_headers_fetcher.cc \ HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
$mod_pagespeed_dir/net/instaweb/system/loopback_route_fetcher.cc \ else
$mod_pagespeed_dir/net/instaweb/system/serf_url_async_fetcher.cc" # Make pagespeed run immediately before gzip and Brotli.
# Make pagespeed run immediately before gzip. if echo $HTTP_FILTER_MODULES | grep ngx_http_brotli_filter_module >/dev/null; then
module=ngx_http_brotli_filter_module
elif [ $HTTP_GZIP = YES ]; then
module=$HTTP_GZIP_FILTER_MODULE
else
module=$HTTP_RANGE_HEADER_FILTER_MODULE
fi
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES |\
sed "s/$module/$module $ngx_addon_name/")
fi
# Make the etag header filter run immediately before range header filter.
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES |\ HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES |\
sed "s/$HTTP_GZIP_FILTER_MODULE/$HTTP_GZIP_FILTER_MODULE $ngx_addon_name/") sed "s/$HTTP_RANGE_HEADER_FILTER_MODULE/$HTTP_RANGE_HEADER_FILTER_MODULE ngx_pagespeed_etag_filter/")
# Make the etag header filter run immediately after gzip.
HTTP_FILTER_MODULES=$(echo $HTTP_FILTER_MODULES |\
sed "s/$HTTP_GZIP_FILTER_MODULE/ngx_pagespeed_etag_filter $HTTP_GZIP_FILTER_MODULE/")
CORE_LIBS="$CORE_LIBS $pagespeed_libs" CORE_LIBS="$CORE_LIBS $pagespeed_libs"
CORE_INCS="$CORE_INCS $pagespeed_include" CORE_INCS="$CORE_INCS $pagespeed_include"
echo "List of modules (in reverse order of applicability): "$HTTP_FILTER_MODULES
else else
cat << END cat << END
$0: error: module ngx_pagespeed requires the pagespeed optimization library $0: error: module ngx_pagespeed requires the pagespeed optimization library.
Look in obj/autoconf.err for more details.
END
exit 1
fi
# Test whether the compiler is compatible
ngx_feature="psol-compiler-compat"
ngx_feature_name=""
ngx_feature_run=no
ngx_feature_incs=""
ngx_feature_path=""
ngx_feature_libs="-lstdc++"
ngx_feature_test="
#if defined(__clang__) && defined(__GLIBCXX__)
// See https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html#abi.versioning
// for a list of various values of __GLIBCXX__. Note that they're not monotonic
// with respect to version numbers.
#if __GLIBCXX__ == 20120322 || __GLIBCXX__ == 20120614
#error \"clang is using libstdc++ 4.7.0 or 4.7.1, which can cause binary incompatibility.\"
#endif
#endif
#if !defined(__clang__) && defined(__GNUC__)
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
#error \"GCC < 4.8 no longer supported. Please use gcc >= 4.8 or clang >= 3.3\"
#endif
#endif
#if defined(__clang__)
#if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 3)
#error \"Please use gcc >= 4.8 or clang >= 3.3\"
#endif
#endif
"
. "$ngx_addon_dir/cpp_feature"
if [ $ngx_found = no ]; then
cat << END
$0: error: module ngx_pagespeed requires gcc >= 4.8 or clang >= 3.3.
See https://developers.google.com/speed/pagespeed/module/build_ngx_pagespeed_from_source for some recommendations.
Look in objs/autoconf.err for more details.
END END
exit 1 exit 1
fi fi
+7
View File
@@ -0,0 +1,7 @@
if [ -n "$NGX_CLANG_VER" ]; then
# Chromium headers assume clang is always in C++11 mode. Oblige it.
for ps_src_file in $PS_NGX_SRCS; do
ps_obj_file="$NGX_OBJS/addon/src/`basename $ps_src_file .cc`.o"
echo "$ps_obj_file : CFLAGS += --std=c++11" >> $NGX_MAKEFILE
done
fi
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
#
# Converts pagespeed_libraries.conf from Apache-format to Nginx-format,
# supporting the canonicalize_javascript_libraries filter.
# Inspired by https://github.com/pagespeed/ngx_pagespeed/issues/532
#
# Usage:
# scripts/pagespeed_libraries_generator.sh > pagespeed_libraries.conf
#
# Then have nginx include that configuration file and enable the filter
# canonicalize_javascript_libraries.
#
# Author: vid@zippykid.com (Vid Luther)
# jefftk@google.com (Jeff Kaufman)
URL="https://github.com/pagespeed/mod_pagespeed/raw/master/"
URL+="net/instaweb/genfiles/conf/pagespeed_libraries.conf"
curl -L -s -S "$URL" \
| grep ModPagespeedLibrary \
| while read library size hash url ; do
echo " pagespeed Library $size $hash $url;"
done
+3
View File
@@ -70,6 +70,9 @@ rsync -arvz "$MOD_PAGESPEED_SRC/" "psol/include/" --prune-empty-dirs \
--include="sparse_hash_map" \ --include="sparse_hash_map" \
--include="sparse_hash_set" \ --include="sparse_hash_set" \
--include="sparsetable" \ --include="sparsetable" \
--include="mod_pagespeed_console_out.cc" \
--include="mod_pagespeed_console_css_out.cc" \
--include="mod_pagespeed_console_html_out.cc" \
--exclude='*' --exclude='*'
mkdir -p psol/lib/Debug/linux/ia32 mkdir -p psol/lib/Debug/linux/ia32
mkdir -p psol/lib/Debug/linux/x64 mkdir -p psol/lib/Debug/linux/x64
+5 -7
View File
@@ -29,7 +29,7 @@
#include "base/debug/stack_trace.h" #include "base/debug/stack_trace.h"
#include "base/logging.h" #include "base/logging.h"
#include "net/instaweb/public/version.h" #include "net/instaweb/public/version.h"
#include "net/instaweb/util/public/string_util.h" #include "pagespeed/kernel/base/string_util.h"
// Make sure we don't attempt to use LOG macros here, since doing so // Make sure we don't attempt to use LOG macros here, since doing so
// would cause us to go into an infinite log loop. // would cause us to go into an infinite log loop.
@@ -38,7 +38,7 @@
namespace { namespace {
ngx_log_t* log = NULL; ngx_log_t* ngx_log = NULL;
ngx_uint_t GetNgxLogLevel(int severity) { ngx_uint_t GetNgxLogLevel(int severity) {
switch (severity) { switch (severity) {
@@ -78,7 +78,7 @@ bool LogMessageHandler(int severity, const char* file, int line,
message.resize(last_msg_character_index); message.resize(last_msg_character_index);
} }
ngx_log_error(this_log_level, log, 0, "[ngx_pagespeed %s] %s", ngx_log_error(this_log_level, ngx_log, 0, "[ngx_pagespeed %s] %s",
net_instaweb::kModPagespeedVersion, net_instaweb::kModPagespeedVersion,
message.c_str()); message.c_str());
@@ -98,15 +98,13 @@ namespace net_instaweb {
namespace log_message_handler { namespace log_message_handler {
const int kDebugLogLevel = -2;
void Install(ngx_log_t* log_in) { void Install(ngx_log_t* log_in) {
log = log_in; ngx_log = log_in;
logging::SetLogMessageHandler(&LogMessageHandler); logging::SetLogMessageHandler(&LogMessageHandler);
// All VLOG(2) and higher will be displayed as DEBUG logs if the nginx log // All VLOG(2) and higher will be displayed as DEBUG logs if the nginx log
// level is DEBUG. // level is DEBUG.
if (log->log_level >= NGX_LOG_DEBUG) { if (ngx_log->log_level >= NGX_LOG_DEBUG) {
logging::SetMinLogLevel(-2); logging::SetMinLogLevel(-2);
} }
} }
+192 -87
View File
@@ -15,35 +15,156 @@
*/ */
// Author: jefftk@google.com (Jeff Kaufman) // Author: jefftk@google.com (Jeff Kaufman)
#include <unistd.h> //for usleep
#include "ngx_base_fetch.h" #include "ngx_base_fetch.h"
#include "ngx_event_connection.h"
#include "ngx_list_iterator.h" #include "ngx_list_iterator.h"
#include "ngx_pagespeed.h" #include "ngx_pagespeed.h"
#include "net/instaweb/http/public/response_headers.h"
#include "net/instaweb/rewriter/public/rewrite_stats.h" #include "net/instaweb/rewriter/public/rewrite_stats.h"
#include "net/instaweb/util/public/google_message_handler.h" #include "pagespeed/kernel/base/google_message_handler.h"
#include "net/instaweb/util/public/message_handler.h" #include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/posix_timer.h"
#include "pagespeed/kernel/http/response_headers.h"
namespace net_instaweb { namespace net_instaweb {
NgxBaseFetch::NgxBaseFetch(ngx_http_request_t* r, int pipe_fd, const char kHeadersComplete = 'H';
const char kFlush = 'F';
const char kDone = 'D';
NgxEventConnection* NgxBaseFetch::event_connection = NULL;
int NgxBaseFetch::active_base_fetches = 0;
NgxBaseFetch::NgxBaseFetch(ngx_http_request_t* r,
NgxServerContext* server_context, NgxServerContext* server_context,
const RequestContextPtr& request_ctx) const RequestContextPtr& request_ctx,
PreserveCachingHeaders preserve_caching_headers,
NgxBaseFetchType base_fetch_type)
: AsyncFetch(request_ctx), : AsyncFetch(request_ctx),
request_(r), request_(r),
server_context_(server_context), server_context_(server_context),
done_called_(false), done_called_(false),
last_buf_sent_(false), last_buf_sent_(false),
pipe_fd_(pipe_fd), references_(2),
references_(2) { base_fetch_type_(base_fetch_type),
preserve_caching_headers_(preserve_caching_headers),
detached_(false),
suppress_(false) {
if (pthread_mutex_init(&mutex_, NULL)) CHECK(0); if (pthread_mutex_init(&mutex_, NULL)) CHECK(0);
PopulateRequestHeaders(); __sync_add_and_fetch(&NgxBaseFetch::active_base_fetches, 1);
} }
NgxBaseFetch::~NgxBaseFetch() { NgxBaseFetch::~NgxBaseFetch() {
pthread_mutex_destroy(&mutex_); pthread_mutex_destroy(&mutex_);
__sync_add_and_fetch(&NgxBaseFetch::active_base_fetches, -1);
}
bool NgxBaseFetch::Initialize(ngx_cycle_t* cycle) {
CHECK(event_connection == NULL) << "event connection already set";
event_connection = new NgxEventConnection(ReadCallback);
return event_connection->Init(cycle);
}
void NgxBaseFetch::Terminate() {
if (event_connection != NULL) {
GoogleMessageHandler handler;
PosixTimer timer;
int64 timeout_us = Timer::kSecondUs * 30;
int64 end_us = timer.NowUs() + timeout_us;
static unsigned int sleep_microseconds = 100;
handler.Message(
kInfo,"NgxBaseFetch::Terminate rounding up %d active base fetches.",
NgxBaseFetch::active_base_fetches);
// Try to continue processing and get the active base fetch count to 0
// untill the timeout expires.
// TODO(oschaaf): This needs more work.
while (NgxBaseFetch::active_base_fetches > 0 && end_us > timer.NowUs()) {
event_connection->Drain();
usleep(sleep_microseconds);
}
if (NgxBaseFetch::active_base_fetches != 0) {
handler.Message(
kWarning,"NgxBaseFetch::Terminate timed out with %d active base fetches.",
NgxBaseFetch::active_base_fetches);
}
// Close down the named pipe.
event_connection->Shutdown();
delete event_connection;
event_connection = NULL;
}
}
const char* BaseFetchTypeToCStr(NgxBaseFetchType type) {
switch(type) {
case kPageSpeedResource:
return "ps resource";
case kHtmlTransform:
return "html transform";
case kAdminPage:
return "admin page";
case kIproLookup:
return "ipro lookup";
case kPageSpeedProxy:
return "pagespeed proxy";
}
CHECK(false);
return "can't get here";
}
void NgxBaseFetch::ReadCallback(const ps_event_data& data) {
NgxBaseFetch* base_fetch = reinterpret_cast<NgxBaseFetch*>(data.sender);
ngx_http_request_t* r = base_fetch->request();
bool detached = base_fetch->detached();
#if (NGX_DEBUG) // `type` is unused if NGX_DEBUG isn't set, needed for -Werror.
const char* type = BaseFetchTypeToCStr(base_fetch->base_fetch_type_);
#endif
int refcount = base_fetch->DecrementRefCount();
#if (NGX_DEBUG)
ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0,
"pagespeed [%p] event: %c. bf:%p (%s) - refcnt:%d - det: %c", r,
data.type, base_fetch, type, refcount, detached ? 'Y': 'N');
#endif
// If we ended up destructing the base fetch, or the request context is
// detached, skip this event.
if (refcount == 0 || detached) {
return;
}
ps_request_ctx_t* ctx = ps_get_request_context(r);
CHECK(data.sender == ctx->base_fetch);
CHECK(r->count > 0) << "r->count: " << r->count;
int rc;
// If we are unlucky enough to have our connection finalized mid-ipro-lookup,
// we must enter a different flow. Also see ps_in_place_check_header_filter().
if ((ctx->base_fetch->base_fetch_type_ != kIproLookup)
&& r->connection->error) {
ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0,
"pagespeed [%p] request already finalized", r);
rc = NGX_ERROR;
} else {
rc = ps_base_fetch::ps_base_fetch_handler(r);
}
#if (NGX_DEBUG)
ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0,
"pagespeed [%p] ps_base_fetch_handler() returned %d for %c",
r, rc, data.type);
#endif
ngx_connection_t* c = r->connection;
ngx_http_finalize_request(r, rc);
// See http://forum.nginx.org/read.php?2,253006,253061
ngx_http_run_posted_requests(c);
} }
void NgxBaseFetch::Lock() { void NgxBaseFetch::Lock() {
@@ -54,45 +175,6 @@ void NgxBaseFetch::Unlock() {
pthread_mutex_unlock(&mutex_); pthread_mutex_unlock(&mutex_);
} }
void NgxBaseFetch::PopulateRequestHeaders() {
CopyHeadersFromTable<RequestHeaders>(&request_->headers_in.headers,
request_headers());
}
void NgxBaseFetch::PopulateResponseHeaders() {
CopyHeadersFromTable<ResponseHeaders>(&request_->headers_out.headers,
response_headers());
response_headers()->set_status_code(request_->headers_out.status);
// Manually copy over the content type because it's not included in
// request_->headers_out.headers.
response_headers()->Add(
HttpAttributes::kContentType,
ngx_psol::str_to_string_piece(request_->headers_out.content_type));
// TODO(oschaaf): ComputeCaching should be called in setupforhtml()?
response_headers()->ComputeCaching();
}
template<class HeadersT>
void NgxBaseFetch::CopyHeadersFromTable(ngx_list_t* headers_from,
HeadersT* headers_to) {
// http_version is the version number of protocol; 1.1 = 1001. See
// NGX_HTTP_VERSION_* in ngx_http_request.h
headers_to->set_major_version(request_->http_version / 1000);
headers_to->set_minor_version(request_->http_version % 1000);
ngx_table_elt_t* header;
NgxListIterator it(&headers_from->part);
while ((header = it.Next()) != NULL) {
StringPiece key = ngx_psol::str_to_string_piece(header->key);
StringPiece value = ngx_psol::str_to_string_piece(header->value);
headers_to->Add(key, value);
}
}
bool NgxBaseFetch::HandleWrite(const StringPiece& sp, bool NgxBaseFetch::HandleWrite(const StringPiece& sp,
MessageHandler* handler) { MessageHandler* handler) {
Lock(); Lock();
@@ -101,12 +183,18 @@ bool NgxBaseFetch::HandleWrite(const StringPiece& sp,
return true; return true;
} }
// should only be called in nginx thread
ngx_int_t NgxBaseFetch::CopyBufferToNginx(ngx_chain_t** link_ptr) { ngx_int_t NgxBaseFetch::CopyBufferToNginx(ngx_chain_t** link_ptr) {
if (done_called_ && last_buf_sent_) { CHECK(!(done_called_ && last_buf_sent_))
return NGX_DECLINED; << "CopyBufferToNginx() was called after the last buffer was sent";
// there is no buffer to send
if (!done_called_ && buffer_.empty()) {
*link_ptr = NULL;
return NGX_AGAIN;
} }
int rc = ngx_psol::string_piece_to_buffer_chain( int rc = string_piece_to_buffer_chain(
request_->pool, buffer_, link_ptr, done_called_ /* send_last_buf */); request_->pool, buffer_, link_ptr, done_called_ /* send_last_buf */);
if (rc != NGX_OK) { if (rc != NGX_OK) {
return rc; return rc;
@@ -117,86 +205,103 @@ ngx_int_t NgxBaseFetch::CopyBufferToNginx(ngx_chain_t** link_ptr) {
if (done_called_) { if (done_called_) {
last_buf_sent_ = true; last_buf_sent_ = true;
return NGX_OK;
} }
return NGX_OK; return NGX_AGAIN;
} }
// There may also be a race condition if this is called between the last Write() // There may also be a race condition if this is called between the last Write()
// and Done() such that we're sending an empty buffer with last_buf set, which I // and Done() such that we're sending an empty buffer with last_buf set, which I
// think nginx will reject. // think nginx will reject.
ngx_int_t NgxBaseFetch::CollectAccumulatedWrites(ngx_chain_t** link_ptr) { ngx_int_t NgxBaseFetch::CollectAccumulatedWrites(ngx_chain_t** link_ptr) {
ngx_int_t rc;
Lock(); Lock();
ngx_int_t rc = CopyBufferToNginx(link_ptr); rc = CopyBufferToNginx(link_ptr);
Unlock(); Unlock();
if (rc == NGX_DECLINED) {
*link_ptr = NULL;
return NGX_OK;
}
return rc; return rc;
} }
ngx_int_t NgxBaseFetch::CollectHeaders(ngx_http_headers_out_t* headers_out) { ngx_int_t NgxBaseFetch::CollectHeaders(ngx_http_headers_out_t* headers_out) {
Lock();
const ResponseHeaders* pagespeed_headers = response_headers(); const ResponseHeaders* pagespeed_headers = response_headers();
Unlock();
return ngx_psol::copy_response_headers_to_ngx(request_, *pagespeed_headers); if (content_length_known()) {
headers_out->content_length = NULL;
headers_out->content_length_n = content_length();
}
return copy_response_headers_to_ngx(request_, *pagespeed_headers,
preserve_caching_headers_);
} }
void NgxBaseFetch::RequestCollection() { void NgxBaseFetch::RequestCollection(char type) {
int rc; if (suppress_) {
char c = 'A'; // What byte we write is arbitrary. return;
while (true) { }
rc = write(pipe_fd_, &c, 1);
if (rc == 1) {
break;
} else if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
// TODO(jefftk): is this rare enough that spinning isn't a problem? Could
// we get into a case where the pipe fills up and we spin forever?
} else { // We must optimistically increment the refcount, and decrement it
perror("NgxBaseFetch::RequestCollection"); // when we conclude we failed. If we only increment on a successfull write,
break; // there's a small chance that between writing and adding to the refcount
} // both pagespeed and nginx will release their refcount -- destructing
// this NgxBaseFetch instance.
IncrementRefCount();
if (!event_connection->WriteEvent(type, this)) {
DecrementRefCount();
} }
} }
void NgxBaseFetch::HandleHeadersComplete() { void NgxBaseFetch::HandleHeadersComplete() {
// If this is a 404 response we need to count it in the stats. int status_code = response_headers()->status_code();
if (response_headers()->status_code() == HttpStatus::kNotFound) { bool status_ok = (status_code != 0) && (status_code < 400);
server_context_->rewrite_stats()->resource_404_count()->Add(1);
if ((base_fetch_type_ != kIproLookup) || status_ok) {
// If this is a 404 response we need to count it in the stats.
if (response_headers()->status_code() == HttpStatus::kNotFound) {
server_context_->rewrite_stats()->resource_404_count()->Add(1);
}
} }
RequestCollection(); // Headers available. RequestCollection(kHeadersComplete); // Headers available.
// For the IPRO lookup, supress notification of the nginx side here.
// If we send both the headerscomplete event and the one from done, nasty
// stuff will happen if we loose the race with with the nginx side destructing
// this base fetch instance.
if (base_fetch_type_ == kIproLookup && !status_ok) {
suppress_ = true;
}
} }
bool NgxBaseFetch::HandleFlush(MessageHandler* handler) { bool NgxBaseFetch::HandleFlush(MessageHandler* handler) {
RequestCollection(); // A new part of the response body is available. RequestCollection(kFlush); // A new part of the response body is available
return true; return true;
} }
void NgxBaseFetch::Release() { int NgxBaseFetch::DecrementRefCount() {
DecrefAndDeleteIfUnreferenced(); return DecrefAndDeleteIfUnreferenced();
} }
void NgxBaseFetch::DecrefAndDeleteIfUnreferenced() { int NgxBaseFetch::IncrementRefCount() {
return __sync_add_and_fetch(&references_, 1);
}
int NgxBaseFetch::DecrefAndDeleteIfUnreferenced() {
// Creates a full memory barrier. // Creates a full memory barrier.
if (__sync_add_and_fetch(&references_, -1) == 0) { int r = __sync_add_and_fetch(&references_, -1);
if (r == 0) {
delete this; delete this;
} }
return r;
} }
void NgxBaseFetch::HandleDone(bool success) { void NgxBaseFetch::HandleDone(bool success) {
// TODO(jefftk): it's possible that instead of locking here we can just modify // TODO(jefftk): it's possible that instead of locking here we can just modify
// CopyBufferToNginx to only read done_called_ once. // CopyBufferToNginx to only read done_called_ once.
CHECK(!done_called_) << "Done already called!";
Lock(); Lock();
done_called_ = true; done_called_ = true;
Unlock(); Unlock();
RequestCollection(kDone);
close(pipe_fd_); // Indicates to nginx that we're done with the rewrite.
pipe_fd_ = -1;
DecrefAndDeleteIfUnreferenced(); DecrefAndDeleteIfUnreferenced();
} }
+79 -31
View File
@@ -17,22 +17,32 @@
// Author: jefftk@google.com (Jeff Kaufman) // Author: jefftk@google.com (Jeff Kaufman)
// //
// Collects output from pagespeed and buffers it until nginx asks for it. // Collects output from pagespeed and buffers it until nginx asks for it.
// Notifies nginx via pipe to call CollectAccumulatedWrites() on flush. // Notifies nginx via NgxEventConnection to call ReadCallback() when
// the headers are computed, when a flush should be performed, and when done.
// //
// - nginx creates a base fetch and passes it to a new proxy fetch. // - nginx creates a base fetch and passes it to a new proxy fetch.
// - The proxy fetch manages rewriting and thread complexity, and through // - The proxy fetch manages rewriting and thread complexity, and through
// several chained steps passes rewritten html to HandleWrite(). // several chained steps passes rewritten html to HandleWrite().
// - Written data is buffered. // - Written data is buffered.
// - When Flush() is called the base fetch writes a byte to a pipe nginx is // - When HandleHeadersComplete(), HandleFlush(), or HandleDone() is called by
// watching so nginx knows to call CollectAccumulatedWrites() to pick up the // PSOL, events are written to NgxEventConnection which will end up being
// rewritten html. // handled by ReadCallback() on nginx's thread.
// - When Done() is called the base fetch closes the pipe, which tells nginx to // When applicable, request processing will be continued via a call to
// make a final call to CollectAccumulatedWrites(). // ps_base_fetch_handler().
// - ps_base_fetch_handler() will pull the header and body bytes from PSOL
// via CollectAccumulatedWrites() and write those to the module's output.
// //
// This class is referred two in two places: the proxy fetch and nginx's // This class is referred to in three places: the proxy fetch, nginx's request,
// request. It must stay alive until both are finished. The proxy fetch will // and pending events written to the associated NgxEventConnection. It must stay
// call Done() to indicate this; nginx will call Release(). Once both Done() // alive until the proxy fetch and nginx request are finished, and no more
// and Release() have been called this class will delete itself. // events are pending.
// - The proxy fetch will call Done() to indicate this.
// - nginx will call Detach() when the associated request is handled
// completely (e.g. the request context is about to be destroyed).
// - ReadCallback() will call DecrementRefCount() on instances associated to
// events it handles.
//
// When the last reference is dropped, this class will delete itself.
#ifndef NGX_BASE_FETCH_H_ #ifndef NGX_BASE_FETCH_H_
#define NGX_BASE_FETCH_H_ #define NGX_BASE_FETCH_H_
@@ -45,26 +55,42 @@ extern "C" {
#include "ngx_pagespeed.h" #include "ngx_pagespeed.h"
#include "ngx_event_connection.h"
#include "ngx_server_context.h" #include "ngx_server_context.h"
#include "net/instaweb/http/public/async_fetch.h" #include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/headers.h" #include "pagespeed/kernel/base/string.h"
#include "net/instaweb/util/public/string.h" #include "pagespeed/kernel/http/headers.h"
namespace net_instaweb { namespace net_instaweb {
enum NgxBaseFetchType {
kIproLookup,
kHtmlTransform,
kPageSpeedResource,
kAdminPage,
kPageSpeedProxy
};
class NgxBaseFetch : public AsyncFetch { class NgxBaseFetch : public AsyncFetch {
public: public:
NgxBaseFetch(ngx_http_request_t* r, int pipe_fd, NgxBaseFetch(ngx_http_request_t* r, NgxServerContext* server_context,
NgxServerContext* server_context, const RequestContextPtr& request_ctx,
const RequestContextPtr& request_ctx); PreserveCachingHeaders preserve_caching_headers,
NgxBaseFetchType base_fetch_type);
virtual ~NgxBaseFetch(); virtual ~NgxBaseFetch();
// Copies the request headers out of request_->headers_in->headers. // Statically initializes event_connection, require for PSOL and nginx to
void PopulateRequestHeaders(); // communicate.
static bool Initialize(ngx_cycle_t* cycle);
// Copies the response headers out of request_->headers_out->headers. // Attempts to finish up request processing queued up in the named pipe and
void PopulateResponseHeaders(); // PSOL for a fixed amount of time. If time is up, a fast and rough shutdown
// is attempted.
// Statically terminates and NULLS event_connection.
static void Terminate();
static void ReadCallback(const ps_event_data& data);
// Puts a chain in link_ptr if we have any output data buffered. Returns // Puts a chain in link_ptr if we have any output data buffered. Returns
// NGX_OK on success, NGX_ERROR on errors. If there's no data to send, sends // NGX_OK on success, NGX_ERROR on errors. If there's no data to send, sends
@@ -82,8 +108,22 @@ class NgxBaseFetch : public AsyncFetch {
// time for resource fetches. Not called at all for proxy fetches. // time for resource fetches. Not called at all for proxy fetches.
ngx_int_t CollectHeaders(ngx_http_headers_out_t* headers_out); ngx_int_t CollectHeaders(ngx_http_headers_out_t* headers_out);
// Called by nginx when it's done with us. // Called by nginx to decrement the refcount.
void Release(); int DecrementRefCount();
// Called by pagespeed to increment the refcount.
int IncrementRefCount();
// Detach() is called when the nginx side releases this base fetch. It
// sets detached_ to true and decrements the refcount. We need to know
// this to be able to handle events which nginx request context has been
// released while the event was in-flight.
void Detach() { detached_ = true; DecrementRefCount(); }
bool detached() { return detached_; }
ngx_http_request_t* request() { return request_; }
NgxBaseFetchType base_fetch_type() { return base_fetch_type_; }
private: private:
virtual bool HandleWrite(const StringPiece& sp, MessageHandler* handler); virtual bool HandleWrite(const StringPiece& sp, MessageHandler* handler);
@@ -91,18 +131,15 @@ class NgxBaseFetch : public AsyncFetch {
virtual void HandleHeadersComplete(); virtual void HandleHeadersComplete();
virtual void HandleDone(bool success); virtual void HandleDone(bool success);
// Helper method for PopulateRequestHeaders and PopulateResponseHeaders.
template<class HeadersT>
void CopyHeadersFromTable(ngx_list_t* headers_from, HeadersT* headers_to);
// Indicate to nginx that we would like it to call // Indicate to nginx that we would like it to call
// CollectAccumulatedWrites(). // CollectAccumulatedWrites().
void RequestCollection(); void RequestCollection(char type);
// Lock must be acquired first. // Lock must be acquired first.
// Returns: // Returns:
// NGX_DECLINED: nothing to send, short circuit. Buffer not allocated. // NGX_ERROR: failure
// NGX_OK, NGX_ERROR: success, failure // NGX_AGAIN: still has buffer to send, need to checkout link_ptr
// NGX_OK: done, HandleDone has been called
// Allocates an nginx buffer, copies our buffer_ contents into it, clears // Allocates an nginx buffer, copies our buffer_ contents into it, clears
// buffer_. // buffer_.
ngx_int_t CopyBufferToNginx(ngx_chain_t** link_ptr); ngx_int_t CopyBufferToNginx(ngx_chain_t** link_ptr);
@@ -112,18 +149,29 @@ class NgxBaseFetch : public AsyncFetch {
// Called by Done() and Release(). Decrements our reference count, and if // Called by Done() and Release(). Decrements our reference count, and if
// it's zero we delete ourself. // it's zero we delete ourself.
void DecrefAndDeleteIfUnreferenced(); int DecrefAndDeleteIfUnreferenced();
static NgxEventConnection* event_connection;
// Live count of NgxBaseFetch instances that are currently in use.
static int active_base_fetches;
ngx_http_request_t* request_; ngx_http_request_t* request_;
GoogleString buffer_; GoogleString buffer_;
NgxServerContext* server_context_; NgxServerContext* server_context_;
bool done_called_; bool done_called_;
bool last_buf_sent_; bool last_buf_sent_;
int pipe_fd_;
// How many active references there are to this fetch. Starts at two, // How many active references there are to this fetch. Starts at two,
// decremented once when Done() is called and once when Release() is called. // decremented once when Done() is called and once when Detach() is called.
// Incremented for each event written by pagespeed for this NgxBaseFetch, and
// decremented on the nginx side for each event read for it.
int references_; int references_;
pthread_mutex_t mutex_; pthread_mutex_t mutex_;
NgxBaseFetchType base_fetch_type_;
PreserveCachingHeaders preserve_caching_headers_;
// Set to true just before the nginx side releases its reference
bool detached_;
bool suppress_;
DISALLOW_COPY_AND_ASSIGN(NgxBaseFetch); DISALLOW_COPY_AND_ASSIGN(NgxBaseFetch);
}; };
+4 -6
View File
@@ -23,18 +23,16 @@
namespace net_instaweb { namespace net_instaweb {
bool NgxCachingHeaders::Lookup(const GoogleString& key, bool NgxCachingHeaders::Lookup(const StringPiece& key,
StringPieceVector* values) { StringPieceVector* values) {
ngx_table_elt_t* header; ngx_table_elt_t* header;
NgxListIterator it(&(request_->headers_out.headers.part)); NgxListIterator it(&(request_->headers_out.headers.part));
while ((header = it.Next()) != NULL) { while ((header = it.Next()) != NULL) {
if (header->hash != 0 && if (header->hash != 0 && key == str_to_string_piece(header->key)) {
key == ngx_psol::str_to_string_piece(header->key)) {
// This will be called multiple times if there are multiple headers with // This will be called multiple times if there are multiple headers with
// this name. Each time it will append to values. // this name. Each time it will append to values.
SplitStringPieceToVector( SplitStringPieceToVector(str_to_string_piece(header->value), ",", values,
ngx_psol::str_to_string_piece(header->value), ",", values, true /* omit empty strings */);
true /* omit empty strings */);
} }
} }
+1 -1
View File
@@ -37,7 +37,7 @@ class NgxCachingHeaders : public CachingHeaders {
request_(request) { request_(request) {
} }
virtual bool Lookup(const GoogleString& key, StringPieceVector* values); virtual bool Lookup(const StringPiece& key, StringPieceVector* values);
virtual bool IsLikelyStaticResourceType() const { virtual bool IsLikelyStaticResourceType() const {
DCHECK(false); // not called in our use-case. DCHECK(false); // not called in our use-case.
+172
View File
@@ -0,0 +1,172 @@
/*
* Copyright 2014 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@we-amp.com (Otto van der Schaaf)
extern "C" {
#include <ngx_channel.h>
}
#include "ngx_event_connection.h"
#include "pagespeed/kernel/base/google_message_handler.h"
#include "pagespeed/kernel/base/message_handler.h"
namespace net_instaweb {
NgxEventConnection::NgxEventConnection(callbackPtr callback)
: event_handler_(callback) {
}
bool NgxEventConnection::Init(ngx_cycle_t* cycle) {
int file_descriptors[2];
if (pipe(file_descriptors) != 0) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "pagespeed: pipe() failed");
return false;
}
if (ngx_nonblocking(file_descriptors[0]) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_nonblocking_n "pagespeed: pipe[0] failed");
} else if (ngx_nonblocking(file_descriptors[1]) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
ngx_nonblocking_n "pagespeed: pipe[1] failed");
} else if (!CreateNgxConnection(cycle, file_descriptors[0])) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
"pagespeed: failed to create connection.");
} else {
pipe_read_fd_ = file_descriptors[0];
pipe_write_fd_ = file_descriptors[1];
return true;
}
close(file_descriptors[0]);
close(file_descriptors[1]);
return false;
}
bool NgxEventConnection::CreateNgxConnection(ngx_cycle_t* cycle,
ngx_fd_t pipe_fd) {
// pipe_fd (the read side of the pipe will end up as c->fd on the
// underlying ngx_connection_t that gets created here)
ngx_int_t rc = ngx_add_channel_event(cycle, pipe_fd, NGX_READ_EVENT,
&NgxEventConnection::ReadEventHandler);
return rc == NGX_OK;
}
void NgxEventConnection::ReadEventHandler(ngx_event_t* ev) {
ngx_connection_t* c = static_cast<ngx_connection_t*>(ev->data);
ngx_int_t result = ngx_handle_read_event(ev, 0);
if (result != NGX_OK) {
CHECK(false) << "pagespeed: ngx_handle_read_event error: " << result;
}
if (ev->timedout) {
ev->timedout = 0;
return;
}
if (!NgxEventConnection::ReadAndNotify(c->fd)) {
// This was copied from ngx_channel_handler(): for epoll, we need to call
// ngx_del_conn(). Sadly, no documentation as to why.
if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
ngx_del_conn(c, 0);
}
ngx_close_connection(c);
ngx_del_event(ev, NGX_READ_EVENT, 0);
}
}
// Deserialize ps_event_data's from the pipe as they become available.
// Subsequently do some bookkeeping, cleanup, and error checking to keep
// the mess out of ps_base_fetch_handler.
bool NgxEventConnection::ReadAndNotify(ngx_fd_t fd) {
while (true) {
// We read only one ps_event_data at a time for now:
// We can end up recursing all the way and end up calling ourselves here.
// If that happens in the middle of looping over multiple ps_event_data's we
// have obtained with read(), the results from the next read() will make us
// process events out of order. Which can give headaches.
// Alternatively, we could maintain a queue to make sure we process in
// sequence
ps_event_data data;
ngx_int_t size = read(fd, static_cast<void*>(&data), sizeof(data));
if (size == -1) {
if (errno == EINTR) {
continue;
// TODO(oschaaf): should we worry about spinning here?
} else if (ngx_errno == EAGAIN || ngx_errno == EWOULDBLOCK) {
return true;
}
}
if (size <= 0) {
return false;
}
data.connection->event_handler_(data);
return true;
}
}
bool NgxEventConnection::WriteEvent(void* sender) {
return WriteEvent('X' /* Anything char is fine */, sender);
}
bool NgxEventConnection::WriteEvent(char type, void* sender) {
ssize_t size = 0;
ps_event_data data;
ngx_memzero(&data, sizeof(data));
data.type = type;
data.sender = sender;
data.connection = this;
while (true) {
size = write(pipe_write_fd_,
static_cast<void*>(&data), sizeof(data));
if (size == sizeof(data)) {
return true;
} else if (size == -1) {
// TODO(oschaaf): should we worry about spinning here?
if (ngx_errno == EINTR || ngx_errno == EAGAIN
|| ngx_errno == EWOULDBLOCK) {
continue;
} else {
return false;
}
} else {
CHECK(false) << "pagespeed: unexpected return value from write(): "
<< size;
}
}
CHECK(false) << "Should not get here";
return false;
}
// Reads and processes what is available in the pipe.
void NgxEventConnection::Drain() {
NgxEventConnection::ReadAndNotify(pipe_read_fd_);
}
void NgxEventConnection::Shutdown() {
close(pipe_write_fd_);
close(pipe_read_fd_);
}
} // namespace net_instaweb
+84
View File
@@ -0,0 +1,84 @@
/*
* Copyright 2014 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@we-amp.com (Otto van der Schaaf)
//
// NgxEventConnection implements a means to send events from other threads to
// nginx's event loop, and is implemented by a named pipe under the hood.
// A single instance is used by NgxBaseFetch, and one instance is created per
// NgxUrlAsyncFetcher when native fetching is on.
#ifndef NGX_EVENT_CONNECTION_H_
#define NGX_EVENT_CONNECTION_H_
extern "C" {
#include <ngx_http.h>
}
#include <pthread.h>
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/http/headers.h"
namespace net_instaweb {
class NgxEventConnection;
// Represents a single event that can be written to or read from the pipe.
// Technically, sender is the only data we need to send. type and connection are
// included to provide a means to trace the events along with some more
// info.
typedef struct {
char type;
void* sender;
NgxEventConnection* connection;
} ps_event_data;
// Handler signature for receiving events
typedef void (*callbackPtr)(const ps_event_data&);
// Abstracts a connection to nginx through which events can be written.
class NgxEventConnection {
public:
explicit NgxEventConnection(callbackPtr handler);
// Creates the file descriptors and ngx_connection_t required for event
// messaging between pagespeed and nginx.
bool Init(ngx_cycle_t* cycle);
// Shuts down the underlying file descriptors and connection created in Init()
void Shutdown();
// Constructs a ps_event_data and writes it to the underlying named pipe.
bool WriteEvent(char type, void* sender);
// Convenience overload for clients that have a single event type.
bool WriteEvent(void* sender);
// Reads and processes what is available in the named pipe's buffer.
void Drain();
private:
static bool CreateNgxConnection(ngx_cycle_t* cycle, ngx_fd_t pipe_fd);
static void ReadEventHandler(ngx_event_t* e);
static bool ReadAndNotify(ngx_fd_t fd);
callbackPtr event_handler_;
// We own these file descriptors
ngx_fd_t pipe_write_fd_;
ngx_fd_t pipe_read_fd_;
DISALLOW_COPY_AND_ASSIGN(NgxEventConnection);
};
} // namespace net_instaweb
#endif // NGX_EVENT_CONNECTION_H_
+787 -446
View File
File diff suppressed because it is too large Load Diff
+166 -107
View File
@@ -16,136 +16,195 @@
// Author: x.dinic@gmail.com (Junmin Xiong) // Author: x.dinic@gmail.com (Junmin Xiong)
// //
// The fetch is started by the main thread. It will fetch the remote resource // PageSpeed needs some way to talk to the internet and request resources. For
// from the specific url asynchronously. // example, if it's optimizing www.example.com/index.html and it sees html with
// <img src="//images.example.com/cat.jpg"> and images.example.com is authorized
// for rewriting in the config, then it needs to fetch cat.jpg from
// images.example.com and optimize it. In apache (always) and nginx (by
// default) we use a fetcher called "serf". This works fine, but it does run
// its own event loop. To be more efficient, this is a "native" fetcher that
// uses nginx's event loop.
//
// The fetch is started by the main thread. It will fetch the remote resource
// from the specific url asynchronously.
#ifndef NET_INSTAWEB_NGX_FETCHER_H_ #ifndef NET_INSTAWEB_NGX_FETCH_H_
#define NET_INSTAWEB_NGX_FETCHER_H_ #define NET_INSTAWEB_NGX_FETCH_H_
extern "C" { extern "C" {
#include <ngx_config.h> #include <ngx_config.h>
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_http.h> #include <ngx_http.h>
typedef bool (*response_handler_pt)(ngx_connection_t* c);
} }
#include "ngx_url_async_fetcher.h" #include "ngx_url_async_fetcher.h"
#include <vector> #include <vector>
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/util/public/pool.h"
#include "net/instaweb/util/public/string.h"
#include "net/instaweb/http/public/url_async_fetcher.h" #include "net/instaweb/http/public/url_async_fetcher.h"
#include "net/instaweb/http/public/response_headers.h" #include "pagespeed/kernel/base/basictypes.h"
#include "net/instaweb/http/public/response_headers_parser.h" #include "pagespeed/kernel/base/pool.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/http/response_headers_parser.h"
#include "pagespeed/kernel/thread/pthread_mutex.h"
namespace net_instaweb { namespace net_instaweb {
class NgxUrlAsyncFetcher;
class NgxFetch : public PoolElement<NgxFetch> {
public:
NgxFetch(const GoogleString& url,
AsyncFetch* async_fetch,
MessageHandler* message_handler,
ngx_msec_t timeout_ms,
ngx_log_t* log);
~NgxFetch();
// Start the fetch typedef bool (*response_handler_pt)(ngx_connection_t* c);
bool Start(NgxUrlAsyncFetcher* fetcher);
// Show the completed url, for logging purpose
const char* str_url();
// This fetch task is done. Call the done of async_fetch.
// It will copy the buffer to cache.
void CallbackDone(bool success);
// Show the bytes received class NgxUrlAsyncFetcher;
size_t bytes_received(); class NgxConnection;
void bytes_received_add(int64 x);
int64 fetch_start_ms();
void set_fetch_start_ms(int64 start_ms);
int64 fetch_end_ms();
void set_fetch_end_ms(int64 end_ms);
MessageHandler* message_handler();
int get_major_version() {
return static_cast<int>(status_->http_version / 1000);
}
int get_minor_version() { class NgxConnection : public PoolElement<NgxConnection> {
return static_cast<int>(status_->http_version % 1000); public:
} NgxConnection(MessageHandler* handler, int max_keepalive_requests);
~NgxConnection();
void SetSock(u_char *sockaddr, socklen_t socklen) {
socklen_ = socklen;
ngx_memcpy(&sockaddr_, sockaddr, socklen);
}
// Close ensures that NgxConnection deletes itself at the appropriate time,
// which can be after receiving a non-keepalive response, or when the remote
// server closes the connection when the NgxConnection is pooled and idle.
void Close();
int get_status_code() { // Once keepalive is disabled, it can't be toggled back on.
return static_cast<int>(status_->code); void set_keepalive(bool k) { keepalive_ = keepalive_ && k; }
} bool keepalive() { return keepalive_; }
ngx_event_t* timeout_event() { typedef Pool<NgxConnection> NgxConnectionPool;
return timeout_event_;
};
void set_timeout_event(ngx_event_t* x) {
timeout_event_ = x;
};
private: static NgxConnection* Connect(ngx_peer_connection_t* pc,
response_handler_pt response_handler; MessageHandler* handler,
// Do the initialized work and start the resolver work. int max_keepalive_requests);
bool Init(); static void IdleWriteHandler(ngx_event_t* ev);
bool ParseUrl(); static void IdleReadHandler(ngx_event_t* ev);
// Prepare the request and write it to remote server. // Terminate will cleanup any idle connections upon shutdown.
int InitRequest(); static void Terminate();
// Create the connection with remote server.
int Connect();
void set_response_handler(response_handler_pt handler) {
response_handler = handler;
}
// Only the Static functions could be used in callbacks.
static void NgxFetchResolveDone(ngx_resolver_ctx_t* ctx);
// Write the request static NgxConnectionPool connection_pool;
static void NgxFetchWrite(ngx_event_t* wev); static PthreadMutex connection_pool_mutex;
// Wait for the response // c_ is owned by NgxConnection and freed in ::Close()
static void NgxFetchRead(ngx_event_t* rev); ngx_connection_t* c_;
// Read and parse the first status line static const int64 keepalive_timeout_ms;
static bool NgxFetchHandleStatusLine(ngx_connection_t* c); static const GoogleString ka_header;
// Read and parse the HTTP headers
static bool NgxFetchHandleHeader(ngx_connection_t* c);
// Read the response body
static bool NgxFetchHandleBody(ngx_connection_t* c);
// Cancel the fetch when it's timeout private:
static void NgxFetchTimeout(ngx_event_t* tev); int max_keepalive_requests_;
bool keepalive_;
socklen_t socklen_;
u_char sockaddr_[NGX_SOCKADDRLEN];
MessageHandler* handler_;
// Add the pagespeed User-Agent DISALLOW_COPY_AND_ASSIGN(NgxConnection);
void FixUserAgent(); };
void FixHost();
const GoogleString str_url_; class NgxFetch : public PoolElement<NgxFetch> {
ngx_url_t url_; public:
NgxUrlAsyncFetcher* fetcher_; NgxFetch(const GoogleString& url,
AsyncFetch* async_fetch_; AsyncFetch* async_fetch,
ResponseHeadersParser parser_; MessageHandler* message_handler,
MessageHandler* message_handler_; ngx_log_t* log);
size_t bytes_received_; ~NgxFetch();
int64 fetch_start_ms_;
int64 fetch_end_ms_;
int64 timeout_ms_;
bool done_;
int64 content_length_;
struct sockaddr_in sin_; // Start the fetch.
ngx_log_t* log_; bool Start(NgxUrlAsyncFetcher* fetcher);
ngx_buf_t* out_; // Show the completed url, for logging purposes.
ngx_buf_t* in_; const char* str_url();
ngx_pool_t* pool_; // This fetch task is done. Call Done() on the async_fetch. It will copy the
ngx_http_request_t* r_; // buffer to cache.
ngx_http_status_t* status_; void CallbackDone(bool success);
ngx_event_t* timeout_event_;
ngx_connection_t* connection_;
ngx_resolver_ctx_t* resolver_ctx_;
DISALLOW_COPY_AND_ASSIGN(NgxFetch); // Show the bytes received.
}; size_t bytes_received();
void bytes_received_add(int64 x);
int64 fetch_start_ms();
void set_fetch_start_ms(int64 start_ms);
int64 fetch_end_ms();
void set_fetch_end_ms(int64 end_ms);
MessageHandler* message_handler();
int get_major_version() {
return static_cast<int>(status_->http_version / 1000);
}
int get_minor_version() {
return static_cast<int>(status_->http_version % 1000);
}
int get_status_code() {
return static_cast<int>(status_->code);
}
ngx_event_t* timeout_event() {
return timeout_event_;
}
void set_timeout_event(ngx_event_t* x) {
timeout_event_ = x;
}
void release_resolver() {
if (resolver_ctx_ != NULL && resolver_ctx_ != NGX_NO_RESOLVER) {
ngx_resolve_name_done(resolver_ctx_);
resolver_ctx_ = NULL;
}
}
private:
response_handler_pt response_handler;
// Do the initialized work and start the resolver work.
bool Init();
bool ParseUrl();
// Prepare the request and write it to remote server.
int InitRequest();
// Create the connection with remote server.
int Connect();
void set_response_handler(response_handler_pt handler) {
response_handler = handler;
}
// Only the Static functions could be used in callbacks.
static void ResolveDoneHandler(ngx_resolver_ctx_t* ctx);
// Write the request.
static void ConnectionWriteHandler(ngx_event_t* wev);
// Wait for the response.
static void ConnectionReadHandler(ngx_event_t* rev);
// Read and parse the first status line.
static bool HandleStatusLine(ngx_connection_t* c);
// Read and parse the HTTP headers.
static bool HandleHeader(ngx_connection_t* c);
// Read the response body.
static bool HandleBody(ngx_connection_t* c);
// Cancel the fetch when it's timeout.
static void TimeoutHandler(ngx_event_t* tev);
// Add the pagespeed User-Agent.
void FixUserAgent();
void FixHost();
const GoogleString str_url_;
ngx_url_t url_;
NgxUrlAsyncFetcher* fetcher_;
AsyncFetch* async_fetch_;
ResponseHeadersParser parser_;
MessageHandler* message_handler_;
int64 bytes_received_;
int64 fetch_start_ms_;
int64 fetch_end_ms_;
bool done_;
int64 content_length_;
bool content_length_known_;
struct sockaddr_in sin_;
ngx_log_t* log_;
ngx_buf_t* out_;
ngx_buf_t* in_;
ngx_pool_t* pool_;
ngx_http_request_t* r_;
ngx_http_status_t* status_;
ngx_event_t* timeout_event_;
NgxConnection* connection_;
ngx_resolver_ctx_t* resolver_ctx_;
DISALLOW_COPY_AND_ASSIGN(NgxFetch);
};
} // namespace net_instaweb } // namespace net_instaweb
#endif // NET_INSTAWEB_NGX_FETCHER_H_ #endif // NET_INSTAWEB_NGX_FETCH_H_
+403
View File
@@ -0,0 +1,403 @@
/*
* Copyright 2014 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: kspoelstra@we-amp.com (Kees Spoelstra)
#include "ngx_gzip_setter.h"
#include <ngx_conf_file.h>
namespace net_instaweb {
NgxGZipSetter g_gzip_setter;
extern "C" {
// These functions replace the setters for:
// gzip
// gzip_types
// gzip_http_version
// gzip_vary
//
// If these functions are called it means there is an explicit gzip
// configuration. The gzip configuration set by pagespeed is then rolled
// back and pagespeed will stop enabling gzip automatically.
char* ngx_gzip_redirect_conf_set_flag_slot(
ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
if (g_gzip_setter.enabled()) {
g_gzip_setter.RollBackAndDisable(cf);
}
char* ret = ngx_conf_set_flag_slot(cf, cmd, conf);
return ret;
}
char* ngx_gzip_redirect_http_types_slot(
ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
if (g_gzip_setter.enabled()) {
g_gzip_setter.RollBackAndDisable(cf);
}
char* ret = ngx_http_types_slot(cf, cmd, conf);
return ret;
}
char* ngx_gzip_redirect_conf_set_enum_slot(
ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
if (g_gzip_setter.enabled()) {
g_gzip_setter.RollBackAndDisable(cf);
}
char* ret = ngx_conf_set_enum_slot(cf, cmd, conf);
return ret;
}
char* ngx_gzip_redirect_conf_set_bitmask_slot(
ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
if (g_gzip_setter.enabled()) {
g_gzip_setter.RollBackAndDisable(cf);
}
char* ret = ngx_conf_set_bitmask_slot(cf, cmd, conf);
return ret;
}
}
NgxGZipSetter::NgxGZipSetter() : enabled_(0) { }
NgxGZipSetter::~NgxGZipSetter() { }
// Helper functions to determine signature.
bool HasLocalConfig(ngx_command_t* command) {
return (!(command->type & (NGX_DIRECT_CONF|NGX_MAIN_CONF)) &&
command->conf == NGX_HTTP_LOC_CONF_OFFSET);
}
bool IsNgxFlagCommand(ngx_command_t* command) {
return (command->set == ngx_conf_set_flag_slot &&
HasLocalConfig(command));
}
bool IsNgxHttpTypesCommand(ngx_command_t* command) {
return (command->set == ngx_http_types_slot &&
HasLocalConfig(command));
}
bool IsNgxEnumCommand(ngx_command_t* command) {
return (command->set == ngx_conf_set_enum_slot &&
HasLocalConfig(command));
}
bool IsNgxBitmaskCommand(ngx_command_t* command) {
return (command->set == ngx_conf_set_bitmask_slot &&
HasLocalConfig(command));
}
// Initialize the NgxGzipSetter.
// Find the gzip, gzip_vary, gzip_http_version and gzip_types commands in the
// gzip module. Enable if the signature of the zip command matches with what we
// trust. Also sets up redirects for the configurations. These redirect handle
// a rollback if expicit configuration is found.
// If commands are not found the method will inform the user by logging.
void NgxGZipSetter::Init(ngx_conf_t* cf) {
#if (NGX_HTTP_GZIP)
bool gzip_signature_mismatch = false;
bool other_signature_mismatch = false;
for (int m = 0; ngx_modules[m] != NULL; m++) {
if (ngx_modules[m]->commands != NULL) {
for (int c = 0; ngx_modules[m]->commands[c].name.len; c++) {
ngx_command_t* current_command =& ngx_modules[m]->commands[c];
// We look for the gzip command, and the exact signature we trust
// this means configured as an config location offset
// and a ngx_flag_t setter.
// Also see:
// ngx_conf_handler in ngx_conf_file.c
// ngx_http_gzip_filter_commands in ngx_http_gzip_filter.c
if (gzip_command_.command_ == NULL &&
STR_EQ_LITERAL(current_command->name, "gzip")) {
if (IsNgxFlagCommand(current_command)) {
current_command->set = ngx_gzip_redirect_conf_set_flag_slot;
gzip_command_.command_ = current_command;
gzip_command_.module_ = ngx_modules[m];
enabled_ = 1;
} else {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0,
"pagespeed: cannot set gzip, signature mismatch");
gzip_signature_mismatch = true;
}
}
if (!gzip_http_version_command_.command_ &&
STR_EQ_LITERAL(current_command->name, "gzip_http_version")) {
if (IsNgxEnumCommand(current_command)) {
current_command->set = ngx_gzip_redirect_conf_set_enum_slot;
gzip_http_version_command_.command_ = current_command;
gzip_http_version_command_.module_ = ngx_modules[m];
} else {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0,
"pagespeed: cannot set gzip_http_version, signature mismatch");
other_signature_mismatch = true;
}
}
if (!gzip_proxied_command_.command_ &&
STR_EQ_LITERAL(current_command->name, "gzip_proxied")) {
if (IsNgxBitmaskCommand(current_command)) {
current_command->set = ngx_gzip_redirect_conf_set_bitmask_slot;
gzip_proxied_command_.command_ = current_command;
gzip_proxied_command_.module_ = ngx_modules[m];
} else {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0,
"pagespeed: cannot set gzip_proxied, signature mismatch");
other_signature_mismatch = true;
}
}
if (!gzip_http_types_command_.command_ &&
STR_EQ_LITERAL(current_command->name, "gzip_types")) {
if (IsNgxHttpTypesCommand(current_command)) {
current_command->set = ngx_gzip_redirect_http_types_slot;
gzip_http_types_command_.command_ = current_command;
gzip_http_types_command_.module_ = ngx_modules[m];
} else {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0,
"pagespeed: cannot set gzip_types, signature mismatch");
other_signature_mismatch = true;
}
}
if (!gzip_vary_command_.command_ &&
STR_EQ_LITERAL(current_command->name, "gzip_vary")) {
if (IsNgxFlagCommand(current_command)) {
current_command->set = ngx_gzip_redirect_conf_set_flag_slot;
gzip_vary_command_.command_ = current_command;
gzip_vary_command_.module_ = ngx_modules[m];
} else {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0,
"pagespeed: cannot set gzip_vary, signature mismatch");
other_signature_mismatch = true;
}
}
}
}
}
if (gzip_signature_mismatch) {
return; // Already logged error.
} else if (!enabled_) {
// Looked through all the available commands and didn't find the "gzip" one.
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0, "pagespeed: cannot set gzip, command not found");
return;
} else if (other_signature_mismatch) {
return; // Already logged error.
} else if (!gzip_vary_command_.command_) {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0, "pagespeed: missing gzip_vary");
return;
} else if (!gzip_http_types_command_.command_) {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0, "pagespeed: missing gzip_types");
return;
} else if (!gzip_http_version_command_.command_) {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0, "pagespeed: missing gzip_http_version");
return;
} else if (!gzip_proxied_command_.command_) {
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0, "pagespeed: missing gzip_proxied");
return;
} else {
return; // Success.
}
#else
ngx_conf_log_error(
NGX_LOG_WARN, cf, 0, "pagespeed: gzip not compiled into nginx");
return;
#endif
}
void* ngx_command_ctx::GetConfPtr(ngx_conf_t* cf) {
return GetModuleConfPtr(cf) + command_->offset;
}
char* ngx_command_ctx::GetModuleConfPtr(ngx_conf_t* cf) {
return reinterpret_cast<char*>(
ngx_http_conf_get_module_loc_conf(cf, (*(module_))));
}
void NgxGZipSetter::SetNgxConfFlag(ngx_conf_t* cf,
ngx_command_ctx* command_ctx,
ngx_flag_t value) {
ngx_flag_t* flag = reinterpret_cast<ngx_flag_t*>(command_ctx->GetConfPtr(cf));
*flag = value;
// Save the flag position for possible rollback.
ngx_flags_set_.push_back(flag);
}
void NgxGZipSetter::SetNgxConfEnum(ngx_conf_t* cf,
ngx_command_ctx* command_ctx,
ngx_uint_t value) {
ngx_uint_t* enum_to_set =
reinterpret_cast<ngx_uint_t*>(command_ctx->GetConfPtr(cf));
*enum_to_set = value;
ngx_uint_set_.push_back(enum_to_set);
}
void NgxGZipSetter::SetNgxConfBitmask(ngx_conf_t* cf,
ngx_command_ctx* command_ctx,
ngx_uint_t value) {
ngx_uint_t* enum_to_set =
reinterpret_cast<ngx_uint_t*>(command_ctx->GetConfPtr(cf));
*enum_to_set = value;
ngx_uint_set_.push_back(enum_to_set);
}
// These are the content types we want to compress.
ngx_str_t gzip_http_types[] = {
ngx_string("application/ecmascript"),
ngx_string("application/javascript"),
ngx_string("application/json"),
ngx_string("application/pdf"),
ngx_string("application/postscript"),
ngx_string("application/x-javascript"),
ngx_string("image/svg+xml"),
ngx_string("text/css"),
ngx_string("text/csv"),
// ngx_string("text/html"), // This is the default implied value.
ngx_string("text/javascript"),
ngx_string("text/plain"),
ngx_string("text/xml"),
ngx_null_string // Indicates end of array.
};
gzs_enable_result NgxGZipSetter::SetGZipForLocation(ngx_conf_t* cf,
bool value) {
if (!enabled_) {
return kEnableGZipNotEnabled;
}
if (gzip_command_.command_) {
SetNgxConfFlag(cf, &gzip_command_, value);
}
return kEnableGZipOk;
}
void NgxGZipSetter::EnableGZipForLocation(ngx_conf_t* cf) {
if (!enabled_) {
return;
}
// When we get called twice for the same location{}, we ignore the second call
// to prevent adding duplicate gzip http types and so on.
ngx_flag_t* flag =
reinterpret_cast<ngx_flag_t*>(gzip_command_.GetConfPtr(cf));
if (*flag == 1) {
return;
}
SetGZipForLocation(cf, true);
if (gzip_vary_command_.command_) {
SetNgxConfFlag(cf, &gzip_vary_command_, 1);
}
if (gzip_http_version_command_.command_) {
SetNgxConfEnum(cf, &gzip_http_version_command_, NGX_HTTP_VERSION_10);
}
if (gzip_proxied_command_.command_) {
SetNgxConfBitmask(
cf, &gzip_http_version_command_, NGX_HTTP_GZIP_PROXIED_ANY);
}
// This is actually the most prone to future API changes, because gzip_types
// is not a simple type like ngx_flag_t. The signature check should be enough
// to prevent problems.
AddGZipHTTPTypes(cf);
return;
}
void NgxGZipSetter::AddGZipHTTPTypes(ngx_conf_t* cf) {
if (gzip_http_types_command_.command_) {
// Following should not happen, but if it does return gracefully.
if (cf->args->nalloc < 2) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"pagespeed: unexpected small cf->args in gzip_types");
return;
}
ngx_command_t* command = gzip_http_types_command_.command_;
char* gzip_conf = reinterpret_cast<char* >(
gzip_http_types_command_.GetModuleConfPtr(cf));
// Backup the old settings.
ngx_str_t old_elt0 = reinterpret_cast<ngx_str_t*>(cf->args->elts)[0];
ngx_str_t old_elt1 = reinterpret_cast<ngx_str_t*>(cf->args->elts)[1];
ngx_uint_t old_nelts = cf->args->nelts;
// Setup first arg.
ngx_str_t gzip_types_string = ngx_string("gzip_types");
reinterpret_cast<ngx_str_t*>(cf->args->elts)[0] = gzip_types_string;
cf->args->nelts = 2;
ngx_str_t* http_types = gzip_http_types;
while (http_types->data) {
ngx_str_t d;
// We allocate the http type on the configuration pool and actually
// leak this if we rollback. This does not seem to be a big problem,
// because nginx also allocates tokens in ngx_conf_file.c and does not
// free them. This way they can be used safely by configurations.
// We must use a copy of gzip_http_types array here because nginx will
// manipulate the values.
// TODO(kspoelstra): better would be to allocate once on init and not
// every time we enable gzip. This needs further investigation, sharing
// tokens might be problematic.
// For now I think it is not a large problem. This might add up in case
// of a large multi server/location config with a lot of "pagespeed on"
// directives.
// Estimates are 300-400KB for 1000 times "pagespeed on".
d.data = reinterpret_cast<u_char*>(
ngx_pnalloc(cf->pool, http_types->len + 1));
snprintf(reinterpret_cast<char*>(d.data), http_types->len + 1, "%s",
reinterpret_cast<const char*>(http_types->data));
d.len = http_types->len;
reinterpret_cast<ngx_str_t*>(cf->args->elts)[1] = d;
// Call the original setter.
ngx_http_types_slot(cf, command, gzip_conf);
http_types++;
}
// Restore args.
cf->args->nelts = old_nelts;
reinterpret_cast<ngx_str_t*>(cf->args->elts)[1] = old_elt1;
reinterpret_cast<ngx_str_t*>(cf->args->elts)[0] = old_elt0;
// Backup configuration location for rollback.
ngx_httptypes_set_.push_back(gzip_conf + command->offset);
}
}
void NgxGZipSetter::RollBackAndDisable(ngx_conf_t* cf) {
ngx_conf_log_error(NGX_LOG_INFO, cf, 0,
"pagespeed: rollback gzip, explicit configuration");
for (std::vector<ngx_flag_t*>::iterator i = ngx_flags_set_.begin();
i != ngx_flags_set_.end(); ++i) {
*(*i)=NGX_CONF_UNSET;
}
for (std::vector<ngx_uint_t*>::iterator i = ngx_uint_set_.begin();
i != ngx_uint_set_.end(); ++i) {
*(*i)=NGX_CONF_UNSET_UINT;
}
for (std::vector<void*>::iterator i = ngx_httptypes_set_.begin();
i != ngx_httptypes_set_.end(); ++i) {
ngx_array_t** type_array = reinterpret_cast<ngx_array_t**>(*i);
ngx_array_destroy(*type_array);
*type_array = NULL;
}
enabled_ = 0;
}
} // namespace net_instaweb
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright 2014 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: kspoelstra@we-amp.com (Kees Spoelstra)
/*
* NgxGZipSetter sets up gzip for pagespeed
* with the following configuration:
* gzip on;
* gzip_vary on;
* gzip_types application/ecmascript;
* gzip_types application/javascript;
* gzip_types application/json;
* gzip_types application/pdf;
* gzip_types application/postscript;
* gzip_types application/x-javascript;
* gzip_types image/svg+xml;
* gzip_types text/css;
* gzip_types text/csv;
* gzip_types text/javascript;
* gzip_types text/plain;
* gzip_types text/xml;
* gzip_http_version 1.0;
*
* If there is an explicit gzip configuration in the nginx.conf
* pagespeed will rollback the set configuration and let the
* user decide what the configuration will be.
*
* It manipulates the configuration by manipulating ngx_flag_t
* and ngx_uint_t settings directly and using the nginx setter for
* gzip_http_types.
* This is probably a safe way to do it. If this mechanism
* changes all non nginx module setup & configuration will
* fail.
*/
#ifndef NGX_GZIP_SETTER_H_
#define NGX_GZIP_SETTER_H_
extern "C" {
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
}
#include <vector>
#include "ngx_pagespeed.h"
#include "pagespeed/kernel/base/basictypes.h"
namespace net_instaweb {
// We need this class because configuration for gzip is in different modules, so
// just saving the command will not work.
class ngx_command_ctx {
public:
ngx_command_ctx() : command_(NULL), module_(NULL) { }
void* GetConfPtr(ngx_conf_t* cf);
char* GetModuleConfPtr(ngx_conf_t* cf);
ngx_command_t* command_;
ngx_module_t* module_;
};
enum gzs_enable_result {
kEnableGZipOk,
kEnableGZipPartial,
kEnableGZipNotEnabled
};
class NgxGZipSetter {
std::vector<ngx_flag_t*> ngx_flags_set_;
std::vector<ngx_uint_t*> ngx_uint_set_;
std::vector<void*> ngx_httptypes_set_;
ngx_command_ctx gzip_command_;
ngx_command_ctx gzip_http_types_command_;
ngx_command_ctx gzip_proxied_command_;
ngx_command_ctx gzip_vary_command_;
ngx_command_ctx gzip_http_version_command_;
bool enabled_;
public:
NgxGZipSetter();
~NgxGZipSetter();
void Init(ngx_conf_t* cf);
void SetNgxConfFlag(ngx_conf_t* cf,
ngx_command_ctx* command_ctx,
ngx_flag_t value);
void SetNgxConfEnum(ngx_conf_t* cf,
ngx_command_ctx* command_ctx,
ngx_uint_t value);
void SetNgxConfBitmask(ngx_conf_t* cf,
ngx_command_ctx* command_ctx,
ngx_uint_t value);
void EnableGZipForLocation(ngx_conf_t* cf);
gzs_enable_result SetGZipForLocation(ngx_conf_t* cf, bool value);
void AddGZipHTTPTypes(ngx_conf_t* cf);
void RollBackAndDisable(ngx_conf_t* cf);
bool enabled() { return enabled_; }
private:
DISALLOW_COPY_AND_ASSIGN(NgxGZipSetter);
};
extern NgxGZipSetter g_gzip_setter;
} // namespace net_instaweb
#endif // NGX_GZIP_SETTER_H_
+1 -1
View File
@@ -33,7 +33,7 @@ namespace net_instaweb {
class NgxListIterator { class NgxListIterator {
public: public:
NgxListIterator(ngx_list_part_t* part); explicit NgxListIterator(ngx_list_part_t* part);
// Return the next element of the list if there is one, NULL otherwise. // Return the next element of the list if there is one, NULL otherwise.
ngx_table_elt_t* Next(); ngx_table_elt_t* Next();
+19 -65
View File
@@ -18,13 +18,13 @@
#include <signal.h> #include <signal.h>
#include "apr_time.h"
#include "net/instaweb/util/public/abstract_mutex.h"
#include "net/instaweb/util/public/debug.h"
#include "net/instaweb/util/public/shared_circular_buffer.h"
#include "net/instaweb/util/public/string_util.h"
#include "net/instaweb/public/version.h" #include "net/instaweb/public/version.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/debug.h"
#include "pagespeed/kernel/base/posix_timer.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/time_util.h"
#include "pagespeed/kernel/sharedmem/shared_circular_buffer.h"
namespace { namespace {
@@ -56,11 +56,9 @@ extern "C" {
namespace net_instaweb { namespace net_instaweb {
NgxMessageHandler::NgxMessageHandler(AbstractMutex* mutex) NgxMessageHandler::NgxMessageHandler(Timer* timer, AbstractMutex* mutex)
: mutex_(mutex), : SystemMessageHandler(timer, mutex),
buffer_(NULL),
log_(NULL) { log_(NULL) {
SetPidString(static_cast<int64>(getpid()));
} }
// Installs a signal handler for common crash signals, that tries to print // Installs a signal handler for common crash signals, that tries to print
@@ -73,14 +71,6 @@ void NgxMessageHandler::InstallCrashHandler(ngx_log_t* log) {
signal(SIGSEGV, signal_handler); signal(SIGSEGV, signal_handler);
} }
bool NgxMessageHandler::Dump(Writer* writer) {
// Can't dump before SharedCircularBuffer is set up.
if (buffer_ == NULL) {
return false;
}
return buffer_->Dump(writer, &handler_);
}
ngx_uint_t NgxMessageHandler::GetNgxLogLevel(MessageType type) { ngx_uint_t NgxMessageHandler::GetNgxLogLevel(MessageType type) {
switch (type) { switch (type) {
case kInfo: case kInfo:
@@ -98,65 +88,29 @@ ngx_uint_t NgxMessageHandler::GetNgxLogLevel(MessageType type) {
return NGX_LOG_ALERT; return NGX_LOG_ALERT;
} }
void NgxMessageHandler::set_buffer(SharedCircularBuffer* buff) { void NgxMessageHandler::MessageSImpl(MessageType type,
ScopedMutex lock(mutex_.get()); const GoogleString& message) {
buffer_ = buff;
}
void NgxMessageHandler::MessageVImpl(MessageType type, const char* msg,
va_list args) {
ngx_uint_t log_level = GetNgxLogLevel(type);
GoogleString formatted_message = Format(msg, args);
if (log_ != NULL) { if (log_ != NULL) {
ngx_uint_t log_level = GetNgxLogLevel(type);
ngx_log_error(log_level, log_, 0/*ngx_err_t*/, "[%s %s] %s", ngx_log_error(log_level, log_, 0/*ngx_err_t*/, "[%s %s] %s",
kModuleName, kModPagespeedVersion, formatted_message.c_str()); kModuleName, kModPagespeedVersion, message.c_str());
} else { } else {
GoogleMessageHandler::MessageVImpl(type, msg, args); GoogleMessageHandler::MessageSImpl(type, message);
} }
// Prepare a log message for the SharedCircularBuffer only. // Prepare a log message for the SharedCircularBuffer only.
// Prepend time and severity to message. AddMessageToBuffer(type, message);
// Format is [time] [severity] [pid] message.
GoogleString message;
char time_buffer[APR_CTIME_LEN + 1];
const char* time = time_buffer;
apr_status_t status = apr_ctime(time_buffer, apr_time_now());
if (status != APR_SUCCESS) {
time = "?";
}
StrAppend(&message, "[", time, "] ",
"[", MessageTypeToString(type), "] ");
StrAppend(&message, pid_string_, " ", formatted_message, "\n");
{
ScopedMutex lock(mutex_.get());
if (buffer_ != NULL) {
buffer_->Write(message);
}
}
} }
void NgxMessageHandler::FileMessageVImpl(MessageType type, const char* file, void NgxMessageHandler::FileMessageSImpl(
int line, const char* msg, MessageType type, const char* file, int line, const GoogleString& message) {
va_list args) {
ngx_uint_t log_level = GetNgxLogLevel(type);
GoogleString formatted_message = Format(msg, args);
if (log_ != NULL) { if (log_ != NULL) {
ngx_uint_t log_level = GetNgxLogLevel(type);
ngx_log_error(log_level, log_, 0/*ngx_err_t*/, "[%s %s] %s:%d:%s", ngx_log_error(log_level, log_, 0/*ngx_err_t*/, "[%s %s] %s:%d:%s",
kModuleName, kModPagespeedVersion, file, line, kModuleName, kModPagespeedVersion, file, line,
formatted_message.c_str()); message.c_str());
} else { } else {
GoogleMessageHandler::FileMessageVImpl(type, file, line, msg, args); GoogleMessageHandler::FileMessageSImpl(type, file, line, message);
} }
} }
// TODO(sligocki): It'd be nice not to do so much string copying.
GoogleString NgxMessageHandler::Format(const char* msg, va_list args) {
GoogleString buffer;
// Ignore the name of this routine: it formats with vsnprintf.
// See base/stringprintf.cc.
StringAppendV(&buffer, msg, args);
return buffer;
}
} // namespace net_instaweb } // namespace net_instaweb
+15 -32
View File
@@ -18,65 +18,48 @@
#define NGX_MESSAGE_HANDLER_H_ #define NGX_MESSAGE_HANDLER_H_
extern "C" { extern "C" {
#include <ngx_auto_config.h>
#if (NGX_THREADS)
#include <ngx_thread.h>
#endif
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_log.h> #include <ngx_log.h>
} }
#include <cstdarg> #include <cstdarg>
#include "net/instaweb/util/public/basictypes.h" #include "pagespeed/kernel/base/basictypes.h"
#include "net/instaweb/util/public/google_message_handler.h" #include "pagespeed/kernel/base/message_handler.h"
#include "net/instaweb/util/public/message_handler.h" #include "pagespeed/kernel/base/string.h"
#include "net/instaweb/util/public/scoped_ptr.h" #include "pagespeed/kernel/base/string_util.h"
#include "net/instaweb/util/public/string.h" #include "pagespeed/system/system_message_handler.h"
#include "net/instaweb/util/public/string_util.h"
namespace net_instaweb { namespace net_instaweb {
class AbstractMutex; class AbstractMutex;
class SharedCircularBuffer;
class Timer; class Timer;
class Writer;
// Implementation of a message handler that uses ngx_log_error() // Implementation of a message handler that uses ngx_log_error()
// logging to emit messages, with a fallback to GoogleMessageHandler // logging to emit messages, with a fallback to GoogleMessageHandler
class NgxMessageHandler : public GoogleMessageHandler { class NgxMessageHandler : public SystemMessageHandler {
public: public:
explicit NgxMessageHandler(AbstractMutex* mutex); explicit NgxMessageHandler(Timer* timer, AbstractMutex* mutex);
// Installs a signal handler for common crash signals that tries to print // Installs a signal handler for common crash signals that tries to print
// out a backtrace. // out a backtrace.
static void InstallCrashHandler(ngx_log_t* log); static void InstallCrashHandler(ngx_log_t* log);
// When NgxRewriteDriver instantiates the NgxMessageHandlers, the
// SharedCircularBuffer and ngx_log_t are not available yet. These
// will later be set in RootInit/Childinit
// Messages logged before that will be passed on to handler_;
void set_buffer(SharedCircularBuffer* buff);
void set_log(ngx_log_t* log) { log_ = log; } void set_log(ngx_log_t* log) { log_ = log; }
ngx_log_t* log() { return log_; }
void SetPidString(const int64 pid) {
pid_string_ = StrCat("[", Integer64ToString(pid), "]");
}
// Dump contents of SharedCircularBuffer.
bool Dump(Writer* writer);
protected: protected:
virtual void MessageVImpl(MessageType type, const char* msg, va_list args); virtual void MessageSImpl(MessageType type, const GoogleString& message);
virtual void FileMessageVImpl(MessageType type, const char* filename, virtual void FileMessageSImpl(MessageType type, const char* file,
int line, const char* msg, va_list args); int line, const GoogleString& message);
private: private:
ngx_uint_t GetNgxLogLevel(MessageType type); ngx_uint_t GetNgxLogLevel(MessageType type);
GoogleString Format(const char* msg, va_list args);
scoped_ptr<AbstractMutex> mutex_;
GoogleString pid_string_;
// handler_ is used as a fallback when we can not use ngx_log_errort
// It's also used when calling Dump on the internal SharedCircularBuffer
GoogleMessageHandler handler_;
SharedCircularBuffer* buffer_;
ngx_log_t* log_; ngx_log_t* log_;
DISALLOW_COPY_AND_ASSIGN(NgxMessageHandler); DISALLOW_COPY_AND_ASSIGN(NgxMessageHandler);
+1661 -1352
View File
File diff suppressed because it is too large Load Diff
+58 -20
View File
@@ -34,8 +34,8 @@ extern "C" {
} }
#include "base/logging.h" #include "base/logging.h"
#include "net/instaweb/http/public/response_headers.h" #include "pagespeed/kernel/base/string_util.h"
#include "net/instaweb/util/public/string_util.h" #include "pagespeed/kernel/http/response_headers.h"
namespace net_instaweb { namespace net_instaweb {
@@ -43,10 +43,9 @@ class GzipInflater;
class NgxBaseFetch; class NgxBaseFetch;
class ProxyFetch; class ProxyFetch;
class RewriteDriver; class RewriteDriver;
class RequestHeaders;
} // namespace net_instaweb class ResponseHeaders;
class InPlaceResourceRecorder;
namespace ngx_psol {
// Allocate chain links and buffers from the supplied pool, and copy over the // Allocate chain links and buffers from the supplied pool, and copy over the
// data from the string piece. If the string piece is empty, return // data from the string piece. If the string piece is empty, return
@@ -75,24 +74,63 @@ StringPiece str_to_string_piece(ngx_str_t s);
// Allocate memory out of the pool for the string piece, and copy the contents // Allocate memory out of the pool for the string piece, and copy the contents
// over. Returns NULL if we can't get memory. // over. Returns NULL if we can't get memory.
char* string_piece_to_pool_string(ngx_pool_t* pool, StringPiece sp); char* string_piece_to_pool_string(ngx_pool_t* pool, StringPiece sp);
ngx_int_t copy_response_headers_to_ngx(
ngx_http_request_t* r, enum PreserveCachingHeaders {
const net_instaweb::ResponseHeaders& pagespeed_headers); kPreserveAllCachingHeaders, // Cache-Control, ETag, Last-Modified, etc
kPreserveOnlyCacheControl, // Only Cache-Control.
kDontPreserveHeaders,
};
typedef struct { typedef struct {
net_instaweb::ProxyFetch* proxy_fetch; NgxBaseFetch* base_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; ngx_http_request_t* r;
bool is_resource_fetch;
bool sent_headers; bool html_rewrite;
bool write_pending; bool in_place;
net_instaweb::GzipInflater* inflater_;
PreserveCachingHeaders preserve_caching_headers;
// for html rewrite
ProxyFetch* proxy_fetch;
GzipInflater* inflater_;
// for in place resource
RewriteDriver* driver;
InPlaceResourceRecorder* recorder;
ResponseHeaders* ipro_response_headers;
// We need to remember the URL here as well since we may modify what NGX
// gets by stripping our special query params and honoring X-Forwarded-Proto.
GoogleString url_string;
// We need to remember if the upstream had headers_out->location set, because
// we should mirror that when we write it back. nginx may absolutify
// Location: headers that start with '/' without regarding X-Forwarded-Proto.
bool location_field_set;
} ps_request_ctx_t; } ps_request_ctx_t;
} // namespace ngx_psol ps_request_ctx_t* ps_get_request_context(ngx_http_request_t* r);
void copy_request_headers_from_ngx(const ngx_http_request_t* r,
RequestHeaders* headers);
void copy_response_headers_from_ngx(const ngx_http_request_t* r,
ResponseHeaders* headers);
ngx_int_t copy_response_headers_to_ngx(
ngx_http_request_t* r,
const ResponseHeaders& pagespeed_headers,
PreserveCachingHeaders preserve_caching_headers);
StringPiece ps_determine_host(ngx_http_request_t* r);
namespace ps_base_fetch {
ngx_int_t ps_base_fetch_handler(ngx_http_request_t* r);
} // namespace ps_base_fetch
} // namespace net_instaweb
#endif // NGX_PAGESPEED_H_ #endif // NGX_PAGESPEED_H_
-82
View File
@@ -1,82 +0,0 @@
/*
* 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,
Timer* timer,
ngx_http_request_t* r)
: RequestContext(logging_mutex, timer),
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.
bool port_set = false;
#if (NGX_HAVE_INET6)
if (r->connection->local_sockaddr->sa_family == AF_INET6) {
local_port_ = ntohs(reinterpret_cast<struct sockaddr_in6*>(
r->connection->local_sockaddr)->sin6_port);
port_set = true;
}
#endif
if (!port_set) {
local_port_ = ntohs(reinterpret_cast<struct sockaddr_in*>(
r->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(r->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
-64
View File
@@ -1,64 +0,0 @@
/*
* 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 Timer;
class NgxRequestContext : public RequestContext {
public:
NgxRequestContext(AbstractMutex* logging_mutex,
Timer* timer,
ngx_http_request_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_
+90 -260
View File
@@ -24,33 +24,32 @@
#include "ngx_message_handler.h" #include "ngx_message_handler.h"
#include "ngx_rewrite_options.h" #include "ngx_rewrite_options.h"
#include "ngx_server_context.h" #include "ngx_server_context.h"
#include "ngx_thread_system.h"
#include "ngx_url_async_fetcher.h" #include "ngx_url_async_fetcher.h"
#include "pthread_shared_mem.h"
#include "net/instaweb/http/public/content_type.h"
#include "net/instaweb/http/public/rate_controller.h" #include "net/instaweb/http/public/rate_controller.h"
#include "net/instaweb/http/public/rate_controlling_url_async_fetcher.h" #include "net/instaweb/http/public/rate_controlling_url_async_fetcher.h"
#include "net/instaweb/http/public/wget_url_fetcher.h" #include "net/instaweb/http/public/wget_url_fetcher.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h" #include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_driver_factory.h" #include "net/instaweb/rewriter/public/rewrite_driver_factory.h"
#include "net/instaweb/rewriter/public/server_context.h" #include "net/instaweb/rewriter/public/server_context.h"
#include "net/instaweb/rewriter/public/static_asset_manager.h"
#include "net/instaweb/system/public/serf_url_async_fetcher.h"
#include "net/instaweb/system/public/system_caches.h"
#include "net/instaweb/system/public/system_rewrite_options.h"
#include "net/instaweb/util/public/google_message_handler.h"
#include "net/instaweb/util/public/null_shared_mem.h"
#include "net/instaweb/util/public/posix_timer.h"
#include "net/instaweb/util/public/property_cache.h" #include "net/instaweb/util/public/property_cache.h"
#include "net/instaweb/util/public/scheduler_thread.h" #include "pagespeed/kernel/base/google_message_handler.h"
#include "net/instaweb/util/public/shared_circular_buffer.h" #include "pagespeed/kernel/base/null_shared_mem.h"
#include "net/instaweb/util/public/shared_mem_statistics.h" #include "pagespeed/kernel/base/posix_timer.h"
#include "net/instaweb/util/public/slow_worker.h" #include "pagespeed/kernel/base/stdio_file_system.h"
#include "net/instaweb/util/public/stdio_file_system.h" #include "pagespeed/kernel/base/string.h"
#include "net/instaweb/util/public/string.h" #include "pagespeed/kernel/base/string_util.h"
#include "net/instaweb/util/public/string_util.h" #include "pagespeed/kernel/base/thread_system.h"
#include "net/instaweb/util/public/thread_system.h" #include "pagespeed/kernel/http/content_type.h"
#include "pagespeed/kernel/sharedmem/shared_circular_buffer.h"
#include "pagespeed/kernel/sharedmem/shared_mem_statistics.h"
#include "pagespeed/kernel/thread/pthread_shared_mem.h"
#include "pagespeed/kernel/thread/scheduler_thread.h"
#include "pagespeed/kernel/thread/slow_worker.h"
#include "pagespeed/system/in_place_resource_recorder.h"
#include "pagespeed/system/serf_url_async_fetcher.h"
#include "pagespeed/system/system_caches.h"
#include "pagespeed/system/system_rewrite_options.h"
namespace net_instaweb { namespace net_instaweb {
@@ -63,36 +62,30 @@ class UrlAsyncFetcher;
class UrlFetcher; class UrlFetcher;
class Writer; class Writer;
const char NgxRewriteDriverFactory::kStaticAssetPrefix[] = class SharedCircularBuffer;
"/ngx_pagespeed_static/";
namespace {
const char kShutdownCount[] = "child_shutdown_count";
} // namespace
NgxRewriteDriverFactory::NgxRewriteDriverFactory( NgxRewriteDriverFactory::NgxRewriteDriverFactory(
NgxThreadSystem* ngx_thread_system) const ProcessContext& process_context,
: SystemRewriteDriverFactory(ngx_thread_system), SystemThreadSystem* system_thread_system, StringPiece hostname, int port)
ngx_thread_system_(ngx_thread_system), : SystemRewriteDriverFactory(process_context, system_thread_system,
// TODO(oschaaf): mod_pagespeed ifdefs this: NULL /* default shared memory runtime */, hostname, port),
shared_mem_runtime_(new ngx::PthreadSharedMem()),
main_conf_(NULL), main_conf_(NULL),
threads_started_(false), threads_started_(false),
use_per_vhost_statistics_(false), ngx_message_handler_(
is_root_process_(true), new NgxMessageHandler(timer(), thread_system()->NewMutex())),
ngx_message_handler_(new NgxMessageHandler(thread_system()->NewMutex())),
ngx_html_parse_message_handler_( ngx_html_parse_message_handler_(
new NgxMessageHandler(thread_system()->NewMutex())), new NgxMessageHandler(timer(), thread_system()->NewMutex())),
install_crash_handler_(false),
message_buffer_size_(0),
shared_circular_buffer_(NULL),
statistics_frozen_(false),
ngx_url_async_fetcher_(NULL),
log_(NULL), log_(NULL),
resolver_timeout_(NGX_CONF_UNSET_MSEC), resolver_timeout_(NGX_CONF_UNSET_MSEC),
use_native_fetcher_(false) { use_native_fetcher_(false),
// 100 Aligns to nginx's server-side default.
native_fetcher_max_keepalive_requests_(100),
ngx_shared_circular_buffer_(NULL),
hostname_(hostname.as_string()),
port_(port),
process_script_variables_(false),
process_script_variables_set_(false),
shut_down_(false) {
InitializeDefaultOptions(); InitializeDefaultOptions();
default_options()->set_beacon_url("/ngx_pagespeed_beacon"); default_options()->set_beacon_url("/ngx_pagespeed_beacon");
SystemRewriteOptions* system_options = dynamic_cast<SystemRewriteOptions*>( SystemRewriteOptions* system_options = dynamic_cast<SystemRewriteOptions*>(
@@ -101,85 +94,35 @@ NgxRewriteDriverFactory::NgxRewriteDriverFactory(
system_options->set_avoid_renaming_introspective_javascript(true); system_options->set_avoid_renaming_introspective_javascript(true);
set_message_handler(ngx_message_handler_); set_message_handler(ngx_message_handler_);
set_html_parse_message_handler(ngx_html_parse_message_handler_); set_html_parse_message_handler(ngx_html_parse_message_handler_);
// see https://code.google.com/p/modpagespeed/issues/detail?id=672
int thread_limit = 1;
caches_.reset(
new SystemCaches(this, shared_mem_runtime_.get(), thread_limit));
} }
NgxRewriteDriverFactory::~NgxRewriteDriverFactory() { NgxRewriteDriverFactory::~NgxRewriteDriverFactory() {
ShutDown(); ShutDown();
ngx_shared_circular_buffer_ = NULL;
CHECK(uninitialized_server_contexts_.empty() || is_root_process_);
STLDeleteElements(&uninitialized_server_contexts_); STLDeleteElements(&uninitialized_server_contexts_);
shared_mem_statistics_.reset(NULL);
} }
Hasher* NgxRewriteDriverFactory::NewHasher() { Hasher* NgxRewriteDriverFactory::NewHasher() {
return new MD5Hasher; return new MD5Hasher;
} }
UrlAsyncFetcher* NgxRewriteDriverFactory::DefaultAsyncUrlFetcher() { UrlAsyncFetcher* NgxRewriteDriverFactory::AllocateFetcher(
const char* fetcher_proxy = ""; SystemRewriteOptions* config) {
if (main_conf_ != NULL) {
fetcher_proxy = main_conf_->fetcher_proxy().c_str();
}
UrlAsyncFetcher* fetcher = NULL;
if (use_native_fetcher_) { if (use_native_fetcher_) {
ngx_url_async_fetcher_ = NgxUrlAsyncFetcher* fetcher = new NgxUrlAsyncFetcher(
new net_instaweb::NgxUrlAsyncFetcher( config->fetcher_proxy().c_str(),
fetcher_proxy, log_,
log_, resolver_timeout_,
resolver_timeout_, config->blocking_fetch_timeout_ms(),
25000, resolver_,
resolver_, native_fetcher_max_keepalive_requests_,
thread_system(), thread_system(),
message_handler()); message_handler());
fetcher = ngx_url_async_fetcher_; ngx_url_async_fetchers_.push_back(fetcher);
return fetcher;
} else { } else {
net_instaweb::SerfUrlAsyncFetcher* serf_fetcher = return SystemRewriteDriverFactory::AllocateFetcher(config);
new net_instaweb::SerfUrlAsyncFetcher(
fetcher_proxy,
NULL,
thread_system(),
statistics(),
timer(),
2500,
message_handler());
fetcher = serf_fetcher;
} }
SystemRewriteOptions* system_options = dynamic_cast<SystemRewriteOptions*>(
default_options());
if (rate_limit_background_fetches_) {
// Unfortunately, we need stats for load-shedding.
if (system_options->statistics_enabled()) {
// TODO(oschaaf): mps bases this multiplier on the configured
// num_rewrite_threads_ which we don't have (yet).
int multiplier = 4;
fetcher = new RateControllingUrlAsyncFetcher(
fetcher,
500 * multiplier /* max queue size */,
multiplier /* requests/host */,
500 * multiplier /* queued per host */,
thread_system(),
statistics());
if (ngx_url_async_fetcher_ == NULL) {
defer_cleanup(new Deleter<SerfUrlAsyncFetcher>(
static_cast<net_instaweb::SerfUrlAsyncFetcher*>(fetcher)));
} else {
defer_cleanup(new Deleter<net_instaweb::NgxUrlAsyncFetcher>(
ngx_url_async_fetcher_));
}
} else {
message_handler()->Message(
kError, "Can't enable fetch rate-limiting without statistics");
}
}
return fetcher;
} }
MessageHandler* NgxRewriteDriverFactory::DefaultHtmlParseMessageHandler() { MessageHandler* NgxRewriteDriverFactory::DefaultHtmlParseMessageHandler() {
@@ -203,46 +146,12 @@ NamedLockManager* NgxRewriteDriverFactory::DefaultLockManager() {
return NULL; return NULL;
} }
void NgxRewriteDriverFactory::SetupCaches(ServerContext* server_context) {
// TODO(anupama): Remove duplication wrt mod_pagespeed code.
caches_->SetupCaches(server_context);
server_context->set_enable_property_cache(true);
PropertyCache* pcache = server_context->page_property_cache();
const PropertyCache::Cohort* cohort =
pcache->AddCohort(RewriteDriver::kBeaconCohort);
server_context->set_beacon_cohort(cohort);
cohort = pcache->AddCohort(RewriteDriver::kDomCohort);
server_context->set_dom_cohort(cohort);
}
RewriteOptions* NgxRewriteDriverFactory::NewRewriteOptions() { RewriteOptions* NgxRewriteDriverFactory::NewRewriteOptions() {
NgxRewriteOptions* options = new NgxRewriteOptions(thread_system()); NgxRewriteOptions* options = new NgxRewriteOptions(thread_system());
options->SetRewriteLevel(RewriteOptions::kCoreFilters); options->SetRewriteLevel(RewriteOptions::kCoreFilters);
return options; return options;
} }
void NgxRewriteDriverFactory::InitStaticAssetManager(
StaticAssetManager* static_asset_manager) {
static_asset_manager->set_library_url_prefix(kStaticAssetPrefix);
}
void NgxRewriteDriverFactory::PrintMemCacheStats(GoogleString* out) {
// TODO(morlovich): Port the client code to proper API, so it gets
// shm stats, too.
caches_->PrintCacheStats(SystemCaches::kIncludeMemcached, out);
}
bool NgxRewriteDriverFactory::InitNgxUrlAsyncFetcher() {
if (ngx_url_async_fetcher_ == NULL) {
return true;
}
log_ = ngx_cycle->log;
return ngx_url_async_fetcher_->Init();
}
bool NgxRewriteDriverFactory::CheckResolver() { bool NgxRewriteDriverFactory::CheckResolver() {
if (use_native_fetcher_ && resolver_ == NULL) { if (use_native_fetcher_ && resolver_ == NULL) {
return false; return false;
@@ -250,52 +159,46 @@ bool NgxRewriteDriverFactory::CheckResolver() {
return true; return true;
} }
void NgxRewriteDriverFactory::StopCacheActivity() { NgxServerContext* NgxRewriteDriverFactory::MakeNgxServerContext(
RewriteDriverFactory::StopCacheActivity(); StringPiece hostname, int port) {
caches_->StopCacheActivity(); NgxServerContext* server_context = new NgxServerContext(this, hostname, port);
}
NgxServerContext* NgxRewriteDriverFactory::MakeNgxServerContext() {
NgxServerContext* server_context = new NgxServerContext(this);
uninitialized_server_contexts_.insert(server_context); uninitialized_server_contexts_.insert(server_context);
return server_context; return server_context;
} }
ServerContext* NgxRewriteDriverFactory::NewDecodingServerContext() {
ServerContext* sc = new NgxServerContext(this, hostname_, port_);
InitStubDecodingServerContext(sc);
return sc;
}
ServerContext* NgxRewriteDriverFactory::NewServerContext() { ServerContext* NgxRewriteDriverFactory::NewServerContext() {
LOG(DFATAL) << "MakeNgxServerContext should be used instead"; LOG(DFATAL) << "MakeNgxServerContext should be used instead";
return NULL; return NULL;
} }
void NgxRewriteDriverFactory::ShutDown() { void NgxRewriteDriverFactory::ShutDown() {
StopCacheActivity(); if (!shut_down_) {
if (!is_root_process_) { shut_down_ = true;
Variable* child_shutdown_count = statistics()->GetVariable(kShutdownCount); SystemRewriteDriverFactory::ShutDown();
child_shutdown_count->Add(1);
} }
}
RewriteDriverFactory::ShutDown(); void NgxRewriteDriverFactory::ShutDownMessageHandlers() {
caches_->ShutDown(message_handler());
ngx_message_handler_->set_buffer(NULL); ngx_message_handler_->set_buffer(NULL);
ngx_html_parse_message_handler_->set_buffer(NULL); ngx_html_parse_message_handler_->set_buffer(NULL);
for (NgxMessageHandlerSet::iterator p =
if (is_root_process_) { server_context_message_handlers_.begin();
// Cleanup statistics. p != server_context_message_handlers_.end(); ++p) {
// TODO(morlovich): This looks dangerous with async. (*p)->set_buffer(NULL);
if (shared_mem_statistics_.get() != NULL) {
shared_mem_statistics_->GlobalCleanup(message_handler());
}
if (shared_circular_buffer_ != NULL) {
shared_circular_buffer_->GlobalCleanup(message_handler());
}
} }
server_context_message_handlers_.clear();
} }
void NgxRewriteDriverFactory::StartThreads() { void NgxRewriteDriverFactory::StartThreads() {
if (threads_started_) { if (threads_started_) {
return; return;
} }
ngx_thread_system_->PermitThreadStarting();
// TODO(jefftk): use a native nginx timer instead of running our own thread. // TODO(jefftk): use a native nginx timer instead of running our own thread.
// See issue #111. // See issue #111.
SchedulerThread* thread = new SchedulerThread(thread_system(), scheduler()); SchedulerThread* thread = new SchedulerThread(thread_system(), scheduler());
@@ -305,107 +208,35 @@ void NgxRewriteDriverFactory::StartThreads() {
threads_started_ = true; threads_started_ = true;
} }
void NgxRewriteDriverFactory::ParentOrChildInit(ngx_log_t* log) { void NgxRewriteDriverFactory::LoggingInit(
if (install_crash_handler_) { ngx_log_t* log, bool may_install_crash_handler) {
log_ = log;
net_instaweb::log_message_handler::Install(log);
if (may_install_crash_handler && install_crash_handler()) {
NgxMessageHandler::InstallCrashHandler(log); NgxMessageHandler::InstallCrashHandler(log);
} }
ngx_message_handler_->set_log(log); ngx_message_handler_->set_log(log);
ngx_html_parse_message_handler_->set_log(log); ngx_html_parse_message_handler_->set_log(log);
SharedCircularBufferInit(is_root_process_);
} }
// TODO(jmarantz): make this per-vhost. void NgxRewriteDriverFactory::SetCircularBuffer(
void NgxRewriteDriverFactory::SharedCircularBufferInit(bool is_root) { SharedCircularBuffer* buffer) {
// Set buffer size to 0 means turning it off ngx_shared_circular_buffer_ = buffer;
if (shared_mem_runtime() != NULL && (message_buffer_size_ != 0)) { ngx_message_handler_->set_buffer(buffer);
// TODO(jmarantz): it appears that filename_prefix() is not actually ngx_html_parse_message_handler_->set_buffer(buffer);
// established at the time of this construction, calling into question
// whether we are naming our shared-memory segments correctly.
shared_circular_buffer_.reset(new SharedCircularBuffer(
shared_mem_runtime(),
message_buffer_size_,
filename_prefix().as_string(),
"foo.com" /*hostname_identifier()*/));
if (shared_circular_buffer_->InitSegment(is_root, message_handler())) {
ngx_message_handler_->set_buffer(shared_circular_buffer_.get());
ngx_html_parse_message_handler_->set_buffer(
shared_circular_buffer_.get());
}
}
} }
void NgxRewriteDriverFactory::RootInit(ngx_log_t* log) { void NgxRewriteDriverFactory::SetServerContextMessageHandler(
net_instaweb::log_message_handler::Install(log); ServerContext* server_context, ngx_log_t* log) {
NgxMessageHandler* handler = new NgxMessageHandler(
ParentOrChildInit(log); timer(), thread_system()->NewMutex());
handler->set_log(log);
// Let SystemCaches know about the various paths we have in configuration // The ngx_shared_circular_buffer_ will be NULL if MessageBufferSize hasn't
// first, as well as the memcached instances. // been raised from its default of 0.
for (NgxServerContextSet::iterator p = uninitialized_server_contexts_.begin(), handler->set_buffer(ngx_shared_circular_buffer_);
e = uninitialized_server_contexts_.end(); p != e; ++p) { server_context_message_handlers_.insert(handler);
NgxServerContext* server_context = *p; defer_cleanup(new Deleter<NgxMessageHandler>(handler));
caches_->RegisterConfig(server_context->config()); server_context->set_message_handler(handler);
}
caches_->RootInit();
}
void NgxRewriteDriverFactory::ChildInit(ngx_log_t* log) {
is_root_process_ = false;
ParentOrChildInit(log);
if (shared_mem_statistics_.get() != NULL) {
shared_mem_statistics_->Init(false, message_handler());
}
caches_->ChildInit();
for (NgxServerContextSet::iterator p = uninitialized_server_contexts_.begin(),
e = uninitialized_server_contexts_.end(); p != e; ++p) {
NgxServerContext* server_context = *p;
server_context->ChildInit();
}
uninitialized_server_contexts_.clear();
}
// Initializes global statistics object if needed, using factory to
// help with the settings if needed.
// Note: does not call set_statistics() on the factory.
Statistics* NgxRewriteDriverFactory::MakeGlobalSharedMemStatistics(
const NgxRewriteOptions& options) {
if (shared_mem_statistics_.get() == NULL) {
shared_mem_statistics_.reset(AllocateAndInitSharedMemStatistics(
"global", options));
}
DCHECK(!statistics_frozen_);
statistics_frozen_ = true;
SetStatistics(shared_mem_statistics_.get());
return shared_mem_statistics_.get();
}
SharedMemStatistics* NgxRewriteDriverFactory::
AllocateAndInitSharedMemStatistics(
const StringPiece& name,
const NgxRewriteOptions& options) {
GoogleString log_filename;
bool logging_enabled = false;
if (!options.log_dir().empty()) {
// Only enable statistics logging if a log_dir() is actually specified.
log_filename = StrCat(options.log_dir(), "/stats_log_", name);
logging_enabled = options.statistics_logging_enabled();
}
// Note that we create the statistics object in the parent process, and
// it stays around in the kids but gets reinitialized for them
// inside ChildInit(), called from pagespeed_child_init.
SharedMemStatistics* stats = new SharedMemStatistics(
options.statistics_logging_interval_ms(),
options.statistics_logging_max_file_size_kb(),
log_filename, logging_enabled,
StrCat(filename_prefix(), name), shared_mem_runtime(), message_handler(),
file_system(), timer());
InitStats(stats);
stats->Init(true, message_handler());
return stats;
} }
void NgxRewriteDriverFactory::InitStats(Statistics* statistics) { void NgxRewriteDriverFactory::InitStats(Statistics* statistics) {
@@ -416,8 +247,7 @@ void NgxRewriteDriverFactory::InitStats(Statistics* statistics) {
// Init Ngx-specific stats. // Init Ngx-specific stats.
NgxServerContext::InitStats(statistics); NgxServerContext::InitStats(statistics);
InPlaceResourceRecorder::InitStats(statistics);
statistics->AddVariable(kShutdownCount);
} }
} // namespace net_instaweb } // namespace net_instaweb
+58 -109
View File
@@ -20,6 +20,10 @@
#define NGX_REWRITE_DRIVER_FACTORY_H_ #define NGX_REWRITE_DRIVER_FACTORY_H_
extern "C" { extern "C" {
#include <ngx_auto_config.h>
#if (NGX_THREADS)
#include <ngx_thread.h>
#endif
#include <ngx_core.h> #include <ngx_core.h>
#include <ngx_http.h> #include <ngx_http.h>
#include <ngx_config.h> #include <ngx_config.h>
@@ -28,130 +32,66 @@ extern "C" {
#include <set> #include <set>
#include "apr_pools.h" #include "pagespeed/kernel/base/md5_hasher.h"
#include "net/instaweb/system/public/system_rewrite_driver_factory.h" #include "pagespeed/kernel/base/scoped_ptr.h"
#include "net/instaweb/util/public/md5_hasher.h" #include "pagespeed/system/system_rewrite_driver_factory.h"
#include "net/instaweb/util/public/scoped_ptr.h"
// TODO(oschaaf): We should reparent ApacheRewriteDriverFactory and
// NgxRewriteDriverFactory to a new class OriginRewriteDriverFactory and factor
// out as much as possible.
namespace net_instaweb { namespace net_instaweb {
class AbstractSharedMem;
class NgxMessageHandler; class NgxMessageHandler;
class NgxRewriteOptions; class NgxRewriteOptions;
class NgxServerContext; class NgxServerContext;
class NgxThreadSystem;
class NgxUrlAsyncFetcher; class NgxUrlAsyncFetcher;
class SharedCircularBuffer; class SharedCircularBuffer;
class SharedMemRefererStatistics; class SharedMemRefererStatistics;
class SharedMemStatistics;
class SlowWorker; class SlowWorker;
class StaticAssetManager;
class Statistics; class Statistics;
class SystemCaches; class SystemThreadSystem;
class NgxRewriteDriverFactory : public SystemRewriteDriverFactory { class NgxRewriteDriverFactory : public SystemRewriteDriverFactory {
public: public:
static const char kStaticAssetPrefix[];
// We take ownership of the thread system. // We take ownership of the thread system.
explicit NgxRewriteDriverFactory(NgxThreadSystem* ngx_thread_system); explicit NgxRewriteDriverFactory(
const ProcessContext& process_context,
SystemThreadSystem* system_thread_system, StringPiece hostname, int port);
virtual ~NgxRewriteDriverFactory(); virtual ~NgxRewriteDriverFactory();
virtual Hasher* NewHasher(); virtual Hasher* NewHasher();
virtual UrlAsyncFetcher* DefaultAsyncUrlFetcher(); virtual UrlAsyncFetcher* AllocateFetcher(SystemRewriteOptions* config);
virtual MessageHandler* DefaultHtmlParseMessageHandler(); virtual MessageHandler* DefaultHtmlParseMessageHandler();
virtual MessageHandler* DefaultMessageHandler(); virtual MessageHandler* DefaultMessageHandler();
virtual FileSystem* DefaultFileSystem(); virtual FileSystem* DefaultFileSystem();
virtual Timer* DefaultTimer(); virtual Timer* DefaultTimer();
virtual NamedLockManager* DefaultLockManager(); virtual NamedLockManager* DefaultLockManager();
virtual void SetupCaches(ServerContext* server_context);
// Create a new RewriteOptions. In this implementation it will be an // Create a new RewriteOptions. In this implementation it will be an
// NgxRewriteOptions. // NgxRewriteOptions.
virtual RewriteOptions* NewRewriteOptions(); virtual RewriteOptions* NewRewriteOptions();
// Initializes the StaticAssetManager. virtual ServerContext* NewDecodingServerContext();
virtual void InitStaticAssetManager(
StaticAssetManager* static_asset_manager);
// Print out details of all the connections to memcached servers.
void PrintMemCacheStats(GoogleString* out);
bool InitNgxUrlAsyncFetcher();
// Check resolver configured or not. // Check resolver configured or not.
bool CheckResolver(); bool CheckResolver();
// Release all the resources. It also calls the base class ShutDown to
// release the base class resources.
// Initializes all the statistics objects created transitively by // Initializes all the statistics objects created transitively by
// NgxRewriteDriverFactory, including nginx-specific and // NgxRewriteDriverFactory, including nginx-specific and
// platform-independent statistics. // platform-independent statistics.
static void InitStats(Statistics* statistics); static void InitStats(Statistics* statistics);
NgxServerContext* MakeNgxServerContext(StringPiece hostname, int port);
virtual ServerContext* NewServerContext();
virtual void ShutDown(); virtual void ShutDown();
virtual void StopCacheActivity();
NgxServerContext* MakeNgxServerContext();
ServerContext* NewServerContext();
AbstractSharedMem* shared_mem_runtime() const {
return shared_mem_runtime_.get();
}
SystemCaches* caches() { return caches_.get(); }
// Starts pagespeed threads if they've not been started already. Must be // Starts pagespeed threads if they've not been started already. Must be
// called after the caller has finished any forking it intends to do. // called after the caller has finished any forking it intends to do.
void StartThreads(); void StartThreads();
// This helper method contains init procedures invoked by both RootInit()
// and ChildInit()
void ParentOrChildInit(ngx_log_t* log);
// For shared memory resources the general setup we follow is to have the
// first running process (aka the root) create the necessary segments and
// fill in their shared data structures, while processes created to actually
// handle requests attach to already existing shared data structures.
//
// During normal server startup[1], RootInit() is called from the nginx hooks
// in the root process for the first task, and then ChildInit() is called in
// any child process.
//
// Keep in mind, however, that when fork() is involved a process may
// effectively see both calls, in which case the 'ChildInit' call would
// come second and override the previous root status. Both calls are also
// invoked in the debug single-process mode.
//
// [1] Besides normal startup, nginx also uses a temporary process to
// syntax check the config file. That basically looks like a complete
// normal startup and shutdown to the code.
bool is_root_process() const { return is_root_process_; }
void RootInit(ngx_log_t* log);
void ChildInit(ngx_log_t* log);
void SharedCircularBufferInit(bool is_root);
// Build global shared-memory statistics. This is invoked if at least
// one server context (global or VirtualHost) enables statistics.
Statistics* MakeGlobalSharedMemStatistics(const NgxRewriteOptions& options);
// Creates and ::Initializes a shared memory statistics object. void SetServerContextMessageHandler(ServerContext* server_context,
SharedMemStatistics* AllocateAndInitSharedMemStatistics( ngx_log_t* log);
const StringPiece& name, const NgxRewriteOptions& options);
NgxMessageHandler* ngx_message_handler() { return ngx_message_handler_; } NgxMessageHandler* ngx_message_handler() { return ngx_message_handler_; }
virtual void NonStaticInitStats(Statistics* statistics) {
InitStats(statistics);
}
void set_main_conf(NgxRewriteOptions* main_conf) { main_conf_ = main_conf; } void set_main_conf(NgxRewriteOptions* main_conf) { main_conf_ = main_conf; }
bool use_per_vhost_statistics() const {
return use_per_vhost_statistics_;
}
void set_use_per_vhost_statistics(bool x) {
use_per_vhost_statistics_ = x;
}
bool install_crash_handler() const {
return install_crash_handler_;
}
void set_install_crash_handler(bool x) {
install_crash_handler_ = x;
}
bool message_buffer_size() const {
return message_buffer_size_;
}
void set_message_buffer_size(int x) {
message_buffer_size_ = x;
}
void set_resolver(ngx_resolver_t* resolver) { void set_resolver(ngx_resolver_t* resolver) {
resolver_ = resolver; resolver_ = resolver;
} }
@@ -165,52 +105,61 @@ class NgxRewriteDriverFactory : public SystemRewriteDriverFactory {
void set_use_native_fetcher(bool x) { void set_use_native_fetcher(bool x) {
use_native_fetcher_ = x; use_native_fetcher_ = x;
} }
void set_rate_limit_background_fetches(bool x) { int native_fetcher_max_keepalive_requests() {
rate_limit_background_fetches_ = x; return native_fetcher_max_keepalive_requests_;
}
void set_native_fetcher_max_keepalive_requests(int x) {
native_fetcher_max_keepalive_requests_ = x;
}
bool process_script_variables() {
return process_script_variables_;
} }
// We use a beacon handler to collect data for critical images, void LoggingInit(ngx_log_t* log, bool may_install_crash_handler);
// css, etc., so filters should be configured accordingly.
// virtual void ShutDownMessageHandlers();
// TODO(jefftk): move to SystemRewriteDriverFactory
virtual bool UseBeaconResultsInFilters() const { virtual void SetCircularBuffer(SharedCircularBuffer* buffer);
return true;
bool SetProcessScriptVariables(bool process_script_variables) {
if (!process_script_variables_set_) {
process_script_variables_ = process_script_variables;
process_script_variables_set_ = true;
return true;
}
return false;
} }
private: private:
NgxThreadSystem* ngx_thread_system_;
Timer* timer_; Timer* timer_;
scoped_ptr<AbstractSharedMem> shared_mem_runtime_;
// main_conf will have only options set in the main block. It may be NULL, // main_conf will have only options set in the main block. It may be NULL,
// and we do not take ownership. // and we do not take ownership.
NgxRewriteOptions* main_conf_; NgxRewriteOptions* main_conf_;
typedef std::set<NgxServerContext*> NgxServerContextSet;
NgxServerContextSet uninitialized_server_contexts_;
// Manages all our caches & lock managers.
scoped_ptr<SystemCaches> caches_;
bool threads_started_; bool threads_started_;
// If true, we'll have a separate statistics object for each vhost
// (along with a global aggregate), rather than just a single object
// aggregating all of them.
bool use_per_vhost_statistics_;
bool is_root_process_;
NgxMessageHandler* ngx_message_handler_; NgxMessageHandler* ngx_message_handler_;
NgxMessageHandler* ngx_html_parse_message_handler_; NgxMessageHandler* ngx_html_parse_message_handler_;
bool install_crash_handler_;
int message_buffer_size_;
scoped_ptr<SharedCircularBuffer> shared_circular_buffer_;
scoped_ptr<SharedMemStatistics> shared_mem_statistics_;
bool statistics_frozen_;
NgxUrlAsyncFetcher* ngx_url_async_fetcher_; std::vector<NgxUrlAsyncFetcher*> ngx_url_async_fetchers_;
ngx_log_t* log_; ngx_log_t* log_;
ngx_msec_t resolver_timeout_; ngx_msec_t resolver_timeout_;
ngx_resolver_t* resolver_; ngx_resolver_t* resolver_;
bool use_native_fetcher_; bool use_native_fetcher_;
bool rate_limit_background_fetches_; int native_fetcher_max_keepalive_requests_;
typedef std::set<NgxMessageHandler*> NgxMessageHandlerSet;
NgxMessageHandlerSet server_context_message_handlers_;
// Owned by the superclass.
// TODO(jefftk): merge the nginx and apache ways of doing this.
SharedCircularBuffer* ngx_shared_circular_buffer_;
GoogleString hostname_;
int port_;
bool process_script_variables_;
bool process_script_variables_set_;
bool shut_down_;
DISALLOW_COPY_AND_ASSIGN(NgxRewriteDriverFactory); DISALLOW_COPY_AND_ASSIGN(NgxRewriteDriverFactory);
}; };
+366 -112
View File
@@ -30,19 +30,68 @@ extern "C" {
#include "net/instaweb/public/version.h" #include "net/instaweb/public/version.h"
#include "net/instaweb/rewriter/public/file_load_policy.h" #include "net/instaweb/rewriter/public/file_load_policy.h"
#include "net/instaweb/rewriter/public/rewrite_options.h" #include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/system/public/system_caches.h" #include "pagespeed/kernel/base/message_handler.h"
#include "net/instaweb/util/public/timer.h" #include "pagespeed/kernel/base/timer.h"
#include "pagespeed/system/system_caches.h"
namespace net_instaweb { namespace net_instaweb {
namespace { namespace {
const char kNgxPagespeedStatisticsHandlerPath[] = "/ngx_pagespeed_statistics"; const char kStatisticsPath[] = "StatisticsPath";
const char kGlobalStatisticsPath[] = "GlobalStatisticsPath";
const char kConsolePath[] = "ConsolePath";
const char kMessagesPath[] = "MessagesPath";
const char kAdminPath[] = "AdminPath";
const char kGlobalAdminPath[] = "GlobalAdminPath";
// These options are copied from mod_instaweb.cc, where APACHE_CONFIG_OPTIONX
// indicates that they can not be set at the directory/location level. They set
// options in the RewriteDriverFactory, so they're entirely global and do not
// appear in RewriteOptions. They are not alphabetized on purpose, but rather
// left in the same order as in mod_instaweb.cc in case we end up needing to
// compare.
// TODO(oschaaf): this duplication is a short term solution.
const char* const server_only_options[] = {
"FetcherTimeoutMs",
"FetchProxy",
"ForceCaching",
"GeneratedFilePrefix",
"ImgMaxRewritesAtOnce",
"InheritVHostConfig",
"InstallCrashHandler",
"MessageBufferSize",
"NumRewriteThreads",
"NumExpensiveRewriteThreads",
"StaticAssetPrefix",
"TrackOriginalContentLength",
"UsePerVHostStatistics", // TODO(anupama): What to do about "No longer used"
"BlockingRewriteRefererUrls",
"CreateSharedMemoryMetadataCache",
"LoadFromFile",
"LoadFromFileMatch",
"LoadFromFileRule",
"LoadFromFileRuleMatch",
"UseNativeFetcher",
"NativeFetcherMaxKeepaliveRequests"
};
// Options that can only be used in the main (http) option scope.
const char* const main_only_options[] = {
"UseNativeFetcher",
"NativeFetcherMaxKeepaliveRequests"
};
} // namespace } // namespace
RewriteOptions::Properties* NgxRewriteOptions::ngx_properties_ = NULL; RewriteOptions::Properties* NgxRewriteOptions::ngx_properties_ = NULL;
NgxRewriteOptions::NgxRewriteOptions(const StringPiece& description,
ThreadSystem* thread_system)
: SystemRewriteOptions(description, thread_system) {
Init();
}
NgxRewriteOptions::NgxRewriteOptions(ThreadSystem* thread_system) NgxRewriteOptions::NgxRewriteOptions(ThreadSystem* thread_system)
: SystemRewriteOptions(thread_system) { : SystemRewriteOptions(thread_system) {
Init(); Init();
@@ -51,30 +100,42 @@ NgxRewriteOptions::NgxRewriteOptions(ThreadSystem* thread_system)
void NgxRewriteOptions::Init() { void NgxRewriteOptions::Init() {
DCHECK(ngx_properties_ != NULL) DCHECK(ngx_properties_ != NULL)
<< "Call NgxRewriteOptions::Initialize() before construction"; << "Call NgxRewriteOptions::Initialize() before construction";
clear_inherited_scripts_ = false;
InitializeOptions(ngx_properties_); InitializeOptions(ngx_properties_);
// Nginx-specific default.
// TODO(sligocki): Get rid of this line and let both Apache and Nginx use
// /pagespeed_statistics as the handler.
statistics_handler_path_.set_default(kNgxPagespeedStatisticsHandlerPath);
} }
void NgxRewriteOptions::AddProperties() { void NgxRewriteOptions::AddProperties() {
// Nothing ngx-specific for now. // Nginx-specific options.
add_ngx_option(
"", &NgxRewriteOptions::statistics_path_, "nsp", kStatisticsPath,
kServerScope, "Set the statistics path. Ex: /ngx_pagespeed_statistics",
false);
add_ngx_option(
"", &NgxRewriteOptions::global_statistics_path_, "ngsp",
kGlobalStatisticsPath, kProcessScope,
"Set the global statistics path. Ex: /ngx_pagespeed_global_statistics",
false);
add_ngx_option(
"", &NgxRewriteOptions::console_path_, "ncp", kConsolePath, kServerScope,
"Set the console path. Ex: /pagespeed_console", false);
add_ngx_option(
"", &NgxRewriteOptions::messages_path_, "nmp", kMessagesPath,
kServerScope, "Set the messages path. Ex: /ngx_pagespeed_message",
false);
add_ngx_option(
"", &NgxRewriteOptions::admin_path_, "nap", kAdminPath,
kServerScope, "Set the admin path. Ex: /pagespeed_admin", false);
add_ngx_option(
"", &NgxRewriteOptions::global_admin_path_, "ngap", kGlobalAdminPath,
kProcessScope, "Set the global admin path. Ex: /pagespeed_global_admin",
false);
MergeSubclassProperties(ngx_properties_); MergeSubclassProperties(ngx_properties_);
// We create a dummy NgxRewriteOptions object here so that we can
// call InitializeSignaturesAndDefaults on it, and in turn get the // Default properties are global but to set them the current API requires
// global defaults (for say, X-Page-Speed header value) setup correctly. // a RewriteOptions instance and we're in a static method.
NgxRewriteOptions dummy_config(NULL); NgxRewriteOptions dummy_config(NULL);
dummy_config.InitializeSignaturesAndDefaults(); dummy_config.set_default_x_header_value(kModPagespeedVersion);
}
void NgxRewriteOptions::InitializeSignaturesAndDefaults() {
// Calls to foo_.DoNotUseForSignatureComputation() would go here.
// Set default header value.
set_default_x_header_value(kModPagespeedVersion);
} }
void NgxRewriteOptions::Initialize() { void NgxRewriteOptions::Initialize() {
@@ -95,6 +156,39 @@ bool NgxRewriteOptions::IsDirective(StringPiece config_directive,
return StringCaseEqual(config_directive, compare_directive); return StringCaseEqual(config_directive, compare_directive);
} }
RewriteOptions::OptionScope NgxRewriteOptions::GetOptionScope(
StringPiece option_name) {
ngx_uint_t i;
ngx_uint_t size = sizeof(main_only_options) / sizeof(char*);
for (i = 0; i < size; i++) {
if (StringCaseEqual(main_only_options[i], option_name)) {
return kProcessScopeStrict;
}
}
size = sizeof(server_only_options) / sizeof(char*);
for (i = 0; i < size; i++) {
if (StringCaseEqual(server_only_options[i], option_name)) {
return kServerScope;
}
}
// This could be made more efficient if RewriteOptions provided a map allowing
// access of options by their name. It's not too much of a worry at present
// since this is just during initialization.
for (OptionBaseVector::const_iterator it = all_options().begin();
it != all_options().end(); ++it) {
RewriteOptions::OptionBase* option = *it;
if (option->option_name() == option_name) {
// We treat kProcessScope as kProcessScopeStrict, failing to start if an
// option is out of place.
return option->scope() == kProcessScope ? kProcessScopeStrict
: option->scope();
}
}
return kDirectoryScope;
}
RewriteOptions::OptionSettingResult NgxRewriteOptions::ParseAndSetOptions0( RewriteOptions::OptionSettingResult NgxRewriteOptions::ParseAndSetOptions0(
StringPiece directive, GoogleString* msg, MessageHandler* handler) { StringPiece directive, GoogleString* msg, MessageHandler* handler) {
if (IsDirective(directive, "on")) { if (IsDirective(directive, "on")) {
@@ -109,31 +203,62 @@ RewriteOptions::OptionSettingResult NgxRewriteOptions::ParseAndSetOptions0(
return RewriteOptions::kOptionOk; return RewriteOptions::kOptionOk;
} }
RewriteOptions::OptionSettingResult RewriteOptions::OptionSettingResult
NgxRewriteOptions::ParseAndSetOptionFromEnum1( NgxRewriteOptions::ParseAndSetOptionFromName1(
OptionEnum directive, StringPiece arg, StringPiece name, StringPiece arg,
GoogleString* msg, MessageHandler* handler) { GoogleString* msg, MessageHandler* handler) {
// FileCachePath needs error checking. // FileCachePath needs error checking.
if (directive == kFileCachePath) { if (StringCaseEqual(name, kFileCachePath)) {
if (!StringCaseStartsWith(arg, "/")) { if (!StringCaseStartsWith(arg, "/")) {
*msg = "must start with a slash"; *msg = "must start with a slash";
return RewriteOptions::kOptionValueInvalid; return RewriteOptions::kOptionValueInvalid;
} }
} }
// TODO(jefftk): port these (no enums for them yet, even!) return SystemRewriteOptions::ParseAndSetOptionFromName1(
// DangerPermitFetchFromUnknownHosts, FetchWithGzip, ForceCaching name, arg, msg, handler);
return SystemRewriteOptions::ParseAndSetOptionFromEnum1(
directive, arg, msg, handler);
} }
template <class DriverFactoryT>
RewriteOptions::OptionSettingResult ParseAndSetOptionHelper(
StringPiece option_value,
DriverFactoryT* driver_factory,
void (DriverFactoryT::*set_option_method)(bool)) {
bool parsed_value;
if (StringCaseEqual(option_value, "on") ||
StringCaseEqual(option_value, "true")) {
parsed_value = true;
} else if (StringCaseEqual(option_value, "off") ||
StringCaseEqual(option_value, "false")) {
parsed_value = false;
} else {
return RewriteOptions::kOptionValueInvalid;
}
(driver_factory->*set_option_method)(parsed_value);
return RewriteOptions::kOptionOk;
}
namespace {
const char* ps_error_string_for_option(
ngx_pool_t* pool, StringPiece directive, StringPiece warning) {
GoogleString msg =
StrCat("\"", directive, "\" ", warning);
char* s = string_piece_to_pool_string(pool, msg);
if (s == NULL) {
return "failed to allocate memory";
}
return s;
}
} // namespace
// Very similar to apache/mod_instaweb::ParseDirective. // Very similar to apache/mod_instaweb::ParseDirective.
const char* const char* NgxRewriteOptions::ParseAndSetOptions(
NgxRewriteOptions::ParseAndSetOptions(
StringPiece* args, int n_args, ngx_pool_t* pool, MessageHandler* handler, StringPiece* args, int n_args, ngx_pool_t* pool, MessageHandler* handler,
NgxRewriteDriverFactory* driver_factory) { NgxRewriteDriverFactory* driver_factory,
RewriteOptions::OptionScope scope, ngx_conf_t* cf, bool compile_scripts) {
CHECK_GE(n_args, 1); CHECK_GE(n_args, 1);
StringPiece directive = args[0]; StringPiece directive = args[0];
@@ -144,111 +269,164 @@ NgxRewriteOptions::ParseAndSetOptions(
directive.remove_prefix(mod_pagespeed.size()); directive.remove_prefix(mod_pagespeed.size());
} }
if (GetOptionScope(directive) > scope) {
return ps_error_string_for_option(
pool, directive, "cannot be set at this scope.");
}
ScriptLine* script_line;
script_line = NULL;
// Note that LoadFromFile should not be scriptable on wildcard hosts,
// as browsers might be able to manipulate its natural use-case: $http_host.
if (!StringCaseStartsWith(directive, "LoadFromFile") &&
!StringCaseEqual(directive, "EnableFilters") &&
!StringCaseEqual(directive, "DisableFilters") &&
!StringCaseEqual(directive, "DownstreamCachePurgeLocationPrefix") &&
!StringCaseEqual(directive, "DownstreamCachePurgeMethod") &&
!StringCaseEqual(directive,
"DownstreamCacheRewrittenPercentageThreshold") &&
!StringCaseEqual(directive, "ShardDomain")){
compile_scripts = false;
}
if (n_args == 1 && StringCaseEqual(directive, "ClearInheritedScripts")) {
clear_inherited_scripts_ = true;
return NGX_CONF_OK;
}
if (compile_scripts) {
CHECK(cf != NULL);
int i;
// Skip the first arg which is always 'pagespeed'
for (i = 1; i < n_args; i++) {
ngx_str_t script_source;
script_source.len = args[i].as_string().length();
std::string tmp = args[i].as_string();
script_source.data = reinterpret_cast<u_char*>(
const_cast<char*>(tmp.c_str()));
if (ngx_http_script_variables_count(&script_source) > 0) {
ngx_http_script_compile_t* sc =
reinterpret_cast<ngx_http_script_compile_t*>(
ngx_pcalloc(cf->pool, sizeof(ngx_http_script_compile_t)));
sc->cf = cf;
sc->source = &script_source;
sc->lengths = reinterpret_cast<ngx_array_t**>(
ngx_pcalloc(cf->pool, sizeof(ngx_array_t*)));
sc->values = reinterpret_cast<ngx_array_t**>(
ngx_pcalloc(cf->pool, sizeof(ngx_array_t*)));
sc->variables = 1;
sc->complete_lengths = 1;
sc->complete_values = 1;
if (ngx_http_script_compile(sc) != NGX_OK) {
return ps_error_string_for_option(
pool, directive, "Failed to compile script variables");
} else {
if (script_line == NULL) {
script_line = new ScriptLine(args, n_args, scope);
}
script_line->AddScriptAndArgIndex(sc, i);
}
}
}
if (script_line != NULL) {
script_lines_.push_back(RefCountedPtr<ScriptLine>(script_line));
// We have found script variables in the current configuration line, and
// prepared the associated rewriteoptions for that.
// We will defer parsing, validation and processing of this line to
// request time. That means we are done handling this configuration line.
return NGX_CONF_OK;
}
}
GoogleString msg; GoogleString msg;
OptionSettingResult result; OptionSettingResult result;
if (n_args == 1) { if (n_args == 1) {
result = ParseAndSetOptions0(directive, &msg, handler); result = ParseAndSetOptions0(directive, &msg, handler);
} else if (n_args == 2) { } else if (n_args == 2) {
StringPiece arg = args[1]; StringPiece arg = args[1];
// TODO(morlovich): Remove these special hacks, and handle these via if (IsDirective(directive, "UseNativeFetcher")) {
// ParseAndSetOptionFromEnum1. result = ParseAndSetOptionHelper<NgxRewriteDriverFactory>(
if (IsDirective(directive, "UsePerVHostStatistics")) { arg, driver_factory,
// TODO(oschaaf): mod_pagespeed has a nicer way to do this. &NgxRewriteDriverFactory::set_use_native_fetcher);
if (IsDirective(arg, "on")) { } else if (IsDirective(directive, "NativeFetcherMaxKeepaliveRequests")) {
driver_factory->set_use_per_vhost_statistics(true); int max_keepalive_requests;
result = RewriteOptions::kOptionOk; if (StringToInt(arg, &max_keepalive_requests) &&
} else if (IsDirective(arg, "off")) { max_keepalive_requests > 0) {
driver_factory->set_use_per_vhost_statistics(false); driver_factory->set_native_fetcher_max_keepalive_requests(
result = RewriteOptions::kOptionOk; max_keepalive_requests);
} else { result = RewriteOptions::kOptionOk;
result = RewriteOptions::kOptionValueInvalid;
}
} else if (IsDirective(directive, "InstallCrashHandler")) {
// TODO(oschaaf): mod_pagespeed has a nicer way to do this.
if (IsDirective(arg, "on")) {
driver_factory->set_install_crash_handler(true);
result = RewriteOptions::kOptionOk;
} else if (IsDirective(arg, "off")) {
driver_factory->set_install_crash_handler(false);
result = RewriteOptions::kOptionOk;
} else {
result = RewriteOptions::kOptionValueInvalid;
}
} else if (IsDirective(directive, "MessageBufferSize")) {
// TODO(oschaaf): mod_pagespeed has a nicer way to do this.
int message_buffer_size;
bool ok = StringToInt(arg.as_string(), &message_buffer_size);
if (ok && message_buffer_size >= 0) {
driver_factory->set_message_buffer_size(message_buffer_size);
result = RewriteOptions::kOptionOk;
} else {
result = RewriteOptions::kOptionValueInvalid;
}
} else if (IsDirective(directive, "UseNativeFetcher")) {
// TODO(oschaaf): mod_pagespeed has a nicer way to do this.
if (IsDirective(arg, "on")) {
driver_factory->set_use_native_fetcher(true);
result = RewriteOptions::kOptionOk;
} else if (IsDirective(arg, "off")) {
driver_factory->set_use_native_fetcher(false);
result = RewriteOptions::kOptionOk;
} else {
result = RewriteOptions::kOptionValueInvalid;
}
} else if (IsDirective(directive, "RateLimitBackgroundFetches")) {
// TODO(oschaaf): mod_pagespeed has a nicer way to do this.
if (IsDirective(arg, "on")) {
driver_factory->set_rate_limit_background_fetches(true);
result = RewriteOptions::kOptionOk;
} else if (IsDirective(arg, "off")) {
driver_factory->set_rate_limit_background_fetches(false);
result = RewriteOptions::kOptionOk;
} else {
result = RewriteOptions::kOptionValueInvalid;
}
} else { } else {
result = ParseAndSetOptionFromName1(directive, args[1], &msg, handler);
}
} else if (n_args == 3) {
// Short-term special handling, until this moves to common code.
// TODO(morlovich): Clean this up.
if (StringCaseEqual(directive, "CreateSharedMemoryMetadataCache")) {
int64 kb = 0;
if (!StringToInt64(args[2], &kb) || kb < 0) {
result = RewriteOptions::kOptionValueInvalid; result = RewriteOptions::kOptionValueInvalid;
msg = "size_kb must be a positive 64-bit integer"; }
} else if (StringCaseEqual("ProcessScriptVariables", args[0])) {
if (scope == RewriteOptions::kProcessScopeStrict) {
if (StringCaseEqual(arg, "on")) {
if (driver_factory->SetProcessScriptVariables(true)) {
result = RewriteOptions::kOptionOk;
} else {
return const_cast<char*>(
"pagespeed ProcessScriptVariables: can only be set once");
}
} else if (StringCaseEqual(arg, "off")) {
if (driver_factory->SetProcessScriptVariables(false)) {
result = RewriteOptions::kOptionOk;
} else {
return const_cast<char*>(
"pagespeed ProcessScriptVariables: can only be set once");
}
} else {
return const_cast<char*>(
"pagespeed ProcessScriptVariables: invalid value");
}
} else { } else {
bool ok = driver_factory->caches()->CreateShmMetadataCache( return const_cast<char*>(
args[1].as_string(), kb, &msg); "ProcessScriptVariables is only allowed at the top level");
result = ok ? kOptionOk : kOptionValueInvalid;
} }
} else { } else {
result = ParseAndSetOptionFromName2(directive, args[1], args[2], result = ParseAndSetOptionFromName1(directive, arg, &msg, handler);
&msg, handler); if (result == RewriteOptions::kOptionNameUnknown) {
result = driver_factory->ParseAndSetOption1(
directive,
arg,
scope >= RewriteOptions::kProcessScope,
&msg,
handler);
}
}
} else if (n_args == 3) {
result = ParseAndSetOptionFromName2(directive, args[1], args[2],
&msg, handler);
if (result == RewriteOptions::kOptionNameUnknown) {
result = driver_factory->ParseAndSetOption2(
directive,
args[1],
args[2],
scope >= RewriteOptions::kProcessScope,
&msg,
handler);
} }
} else if (n_args == 4) { } else if (n_args == 4) {
result = ParseAndSetOptionFromName3( result = ParseAndSetOptionFromName3(
directive, args[1], args[2], args[3], &msg, handler); directive, args[1], args[2], args[3], &msg, handler);
} else { } else {
return "unknown option"; result = RewriteOptions::kOptionNameUnknown;
} }
switch (result) { switch (result) {
case RewriteOptions::kOptionOk: case RewriteOptions::kOptionOk:
return NGX_CONF_OK; return NGX_CONF_OK;
case RewriteOptions::kOptionNameUnknown: case RewriteOptions::kOptionNameUnknown:
return "unknown option"; return ps_error_string_for_option(
pool, directive, "not recognized or too many arguments");
case RewriteOptions::kOptionValueInvalid: { case RewriteOptions::kOptionValueInvalid: {
GoogleString full_directive = "\""; GoogleString full_directive;
for (int i = 0 ; i < n_args ; i++) { for (int i = 0 ; i < n_args ; i++) {
StrAppend(&full_directive, i == 0 ? "" : " ", args[i]); StrAppend(&full_directive, i == 0 ? "" : " ", args[i]);
} }
StrAppend(&full_directive, "\": ", msg); return ps_error_string_for_option(pool, full_directive, msg);
char* s = ngx_psol::string_piece_to_pool_string(pool, full_directive);
if (s == NULL) {
return "failed to allocate memory";
}
return s;
} }
} }
@@ -256,8 +434,84 @@ NgxRewriteOptions::ParseAndSetOptions(
return NULL; return NULL;
} }
// Execute all entries in the script_lines vector, and hand the result off to
// ParseAndSetOptions to obtain the final option values.
bool NgxRewriteOptions::ExecuteScriptVariables(
ngx_http_request_t* r, MessageHandler* handler,
NgxRewriteDriverFactory* driver_factory) {
bool script_error = false;
if (script_lines_.size() > 0) {
std::vector<RefCountedPtr<ScriptLine> >::iterator it;
for (it = script_lines_.begin() ; it != script_lines_.end(); ++it) {
ScriptLine* script_line = it->get();
StringPiece args[NGX_PAGESPEED_MAX_ARGS];
std::vector<ScriptArgIndex*>::iterator cs_it;
int i;
for (i = 0; i < script_line->n_args(); i++) {
args[i] = script_line->args()[i];
}
for (cs_it = script_line->data().begin();
cs_it != script_line->data().end(); cs_it++) {
ngx_http_script_compile_t* script;
ngx_array_t* values;
ngx_array_t* lengths;
ngx_str_t value;
script = (*cs_it)->script();
lengths = *script->lengths;
values = *script->values;
if (ngx_http_script_run(r, &value, lengths->elts, 0, values->elts)
== NULL) {
handler->Message(kError, "ngx_http_script_run error");
script_error = true;
break;
} else {
args[(*cs_it)->index()] = str_to_string_piece(value);
}
}
const char* status = ParseAndSetOptions(args, script_line->n_args(),
r->pool, handler, driver_factory, script_line->scope(), NULL /*cf*/,
false /*compile scripts*/);
if (status != NULL) {
script_error = true;
handler->Message(kWarning,
"Error setting option value from script: '%s'", status);
break;
}
}
}
if (script_error) {
handler->Message(kWarning,
"Script error(s) in configuration, disabling optimization");
set_enabled(RewriteOptions::kEnabledOff);
return false;
}
return true;
}
void NgxRewriteOptions::CopyScriptLinesTo(
NgxRewriteOptions* destination) const {
destination->script_lines_ = script_lines_;
}
void NgxRewriteOptions::AppendScriptLinesTo(
NgxRewriteOptions* destination) const {
destination->script_lines_.insert(destination->script_lines_.end(),
script_lines_.begin(), script_lines_.end());
}
NgxRewriteOptions* NgxRewriteOptions::Clone() const { NgxRewriteOptions* NgxRewriteOptions::Clone() const {
NgxRewriteOptions* options = new NgxRewriteOptions(thread_system()); NgxRewriteOptions* options = new NgxRewriteOptions(
StrCat("cloned from ", description()), thread_system());
this->CopyScriptLinesTo(options);
options->Merge(*this); options->Merge(*this);
return options; return options;
} }
+128 -9
View File
@@ -27,19 +27,89 @@ extern "C" {
#include <ngx_http.h> #include <ngx_http.h>
} }
#include <vector>
#include "net/instaweb/rewriter/public/rewrite_options.h" #include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/system/public/system_rewrite_options.h" #include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/ref_counted_ptr.h"
#include "pagespeed/kernel/base/stl_util.h" // for STLDeleteElements
#include "pagespeed/system/system_rewrite_options.h"
#define NGX_PAGESPEED_MAX_ARGS 10
namespace net_instaweb { namespace net_instaweb {
class NgxRewriteDriverFactory; class NgxRewriteDriverFactory;
class ScriptArgIndex {
public:
explicit ScriptArgIndex(ngx_http_script_compile_t* script, int index)
: script_(script), index_(index) {
CHECK(script != NULL);
CHECK(index > 0 && index < NGX_PAGESPEED_MAX_ARGS);
}
virtual ~ScriptArgIndex() {}
ngx_http_script_compile_t* script() { return script_; }
int index() { return index_; }
private:
// Not owned.
ngx_http_script_compile_t* script_;
int index_;
};
// Refcounted, because the ScriptArgIndexes inside data_ can be shared between
// different rewriteoptions.
class ScriptLine : public RefCounted<ScriptLine> {
public:
explicit ScriptLine(StringPiece* args, int n_args,
RewriteOptions::OptionScope scope)
: n_args_(n_args),
scope_(scope) {
for (int i = 0; i < n_args; i++) {
args_[i] = args[i];
}
}
virtual ~ScriptLine() {
STLDeleteElements(&data_);
data_.clear();
}
void AddScriptAndArgIndex(ngx_http_script_compile_t* script,
int script_index) {
CHECK(script != NULL);
CHECK(script_index < NGX_PAGESPEED_MAX_ARGS);
data_.push_back(new ScriptArgIndex(script, script_index));
}
int n_args() { return n_args_;}
StringPiece* args() { return args_;}
RewriteOptions::OptionScope scope() { return scope_; }
std::vector<ScriptArgIndex*>& data() {
return data_;
}
private:
StringPiece args_[NGX_PAGESPEED_MAX_ARGS];
int n_args_;
RewriteOptions::OptionScope scope_;
std::vector<ScriptArgIndex*> data_;
DISALLOW_COPY_AND_ASSIGN(ScriptLine);
};
class NgxRewriteOptions : public SystemRewriteOptions { class NgxRewriteOptions : public SystemRewriteOptions {
public: public:
// See rewrite_options::Initialize and ::Terminate // See rewrite_options::Initialize and ::Terminate
static void Initialize(); static void Initialize();
static void Terminate(); static void Terminate();
NgxRewriteOptions(const StringPiece& description,
ThreadSystem* thread_system);
explicit NgxRewriteOptions(ThreadSystem* thread_system); explicit NgxRewriteOptions(ThreadSystem* thread_system);
virtual ~NgxRewriteOptions() { } virtual ~NgxRewriteOptions() { }
@@ -54,9 +124,19 @@ class NgxRewriteOptions : public SystemRewriteOptions {
// on failure. // on failure.
// //
// pool is a memory pool for allocating error strings. // pool is a memory pool for allocating error strings.
// cf is only required when compile_scripts is true
// when compile_scripts is true, the rewrite_options will be prepared
// for replacing any script $variables encountered in args. when false,
// script variables will be substituted using the prepared rewrite options.
const char* ParseAndSetOptions( const char* ParseAndSetOptions(
StringPiece* args, int n_args, ngx_pool_t* pool, MessageHandler* handler, StringPiece* args, int n_args, ngx_pool_t* pool, MessageHandler* handler,
NgxRewriteDriverFactory* driver_factory, OptionScope scope,
ngx_conf_t* cf, bool compile_scripts);
bool ExecuteScriptVariables(
ngx_http_request_t* r, MessageHandler* handler,
NgxRewriteDriverFactory* driver_factory); NgxRewriteDriverFactory* driver_factory);
void CopyScriptLinesTo(NgxRewriteOptions* destination) const;
void AppendScriptLinesTo(NgxRewriteOptions* destination) const;
// Make an identical copy of these options and return it. // Make an identical copy of these options and return it.
virtual NgxRewriteOptions* Clone() const; virtual NgxRewriteOptions* Clone() const;
@@ -66,6 +146,30 @@ class NgxRewriteOptions : public SystemRewriteOptions {
static const NgxRewriteOptions* DynamicCast(const RewriteOptions* instance); static const NgxRewriteOptions* DynamicCast(const RewriteOptions* instance);
static NgxRewriteOptions* DynamicCast(RewriteOptions* instance); static NgxRewriteOptions* DynamicCast(RewriteOptions* instance);
const GoogleString& statistics_path() const {
return statistics_path_.value();
}
const GoogleString& global_statistics_path() const {
return global_statistics_path_.value();
}
const GoogleString& console_path() const {
return console_path_.value();
}
const GoogleString& messages_path() const {
return messages_path_.value();
}
const GoogleString& admin_path() const {
return admin_path_.value();
}
const GoogleString& global_admin_path() const {
return global_admin_path_.value();
}
const std::vector<RefCountedPtr<ScriptLine> >& script_lines() const {
return script_lines_;
}
const bool& clear_inherited_scripts() const {
return clear_inherited_scripts_;
}
private: private:
// Helper methods for ParseAndSetOptions(). Each can: // Helper methods for ParseAndSetOptions(). Each can:
@@ -85,9 +189,8 @@ class NgxRewriteOptions : public SystemRewriteOptions {
OptionSettingResult ParseAndSetOptions0( OptionSettingResult ParseAndSetOptions0(
StringPiece directive, GoogleString* msg, MessageHandler* handler); StringPiece directive, GoogleString* msg, MessageHandler* handler);
// These are called via RewriteOptions::ParseAndSetOptionFromName[123] virtual OptionSettingResult ParseAndSetOptionFromName1(
virtual OptionSettingResult ParseAndSetOptionFromEnum1( StringPiece name, StringPiece arg,
OptionEnum name, StringPiece arg,
GoogleString* msg, MessageHandler* handler); GoogleString* msg, MessageHandler* handler);
// We may want to override 2- and 3-argument versions as well in the future, // We may want to override 2- and 3-argument versions as well in the future,
@@ -102,21 +205,37 @@ class NgxRewriteOptions : public SystemRewriteOptions {
static Properties* ngx_properties_; static Properties* ngx_properties_;
static void AddProperties(); static void AddProperties();
void Init(); void Init();
void InitializeSignaturesAndDefaults();
// Add an option to ngx_properties_ // Add an option to ngx_properties_
template<class RewriteOptionsSubclass, class OptionClass> template<class OptionClass>
static void add_ngx_option(typename OptionClass::ValueType default_value, static void add_ngx_option(typename OptionClass::ValueType default_value,
OptionClass RewriteOptionsSubclass::*offset, OptionClass NgxRewriteOptions::*offset,
const char* id, const char* id,
OptionEnum option_enum) { StringPiece option_name,
AddProperty(default_value, offset, id, option_enum, ngx_properties_); OptionScope scope,
const char* help,
bool safe_to_print) {
AddProperty(default_value, offset, id, option_name, scope, help,
safe_to_print, ngx_properties_);
} }
Option<GoogleString> statistics_path_;
Option<GoogleString> global_statistics_path_;
Option<GoogleString> console_path_;
Option<GoogleString> messages_path_;
Option<GoogleString> admin_path_;
Option<GoogleString> global_admin_path_;
bool clear_inherited_scripts_;
std::vector<RefCountedPtr<ScriptLine> > script_lines_;
// Helper for ParseAndSetOptions. Returns whether the two directives equal, // Helper for ParseAndSetOptions. Returns whether the two directives equal,
// ignoring case. // ignoring case.
bool IsDirective(StringPiece config_directive, StringPiece compare_directive); bool IsDirective(StringPiece config_directive, StringPiece compare_directive);
// Returns a given option's scope.
RewriteOptions::OptionScope GetOptionScope(StringPiece option_name);
// TODO(jefftk): support fetch proxy in server and location blocks. // TODO(jefftk): support fetch proxy in server and location blocks.
DISALLOW_COPY_AND_ASSIGN(NgxRewriteOptions); DISALLOW_COPY_AND_ASSIGN(NgxRewriteOptions);
+45 -97
View File
@@ -18,120 +18,68 @@
#include "ngx_server_context.h" #include "ngx_server_context.h"
#include "ngx_request_context.h" extern "C" {
#include <ngx_http.h>
}
#include "ngx_pagespeed.h"
#include "ngx_message_handler.h"
#include "ngx_rewrite_driver_factory.h" #include "ngx_rewrite_driver_factory.h"
#include "ngx_rewrite_options.h" #include "ngx_rewrite_options.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h" #include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_stats.h" #include "pagespeed/system/add_headers_fetcher.h"
#include "net/instaweb/system/public/add_headers_fetcher.h" #include "pagespeed/system/loopback_route_fetcher.h"
#include "net/instaweb/system/public/loopback_route_fetcher.h" #include "pagespeed/system/system_request_context.h"
#include "net/instaweb/system/public/system_caches.h"
#include "net/instaweb/util/public/shared_mem_statistics.h"
#include "net/instaweb/util/public/split_statistics.h"
#include "net/instaweb/util/public/statistics.h"
namespace net_instaweb { namespace net_instaweb {
const char kCacheFlushCount[] = "cache_flush_count"; NgxServerContext::NgxServerContext(
const char kCacheFlushTimestampMs[] = "cache_flush_timestamp_ms"; NgxRewriteDriverFactory* factory, StringPiece hostname, int port)
: SystemServerContext(factory, hostname, port) {
// Statistics histogram names.
const char kHtmlRewriteTimeUsHistogram[] = "Html Time us Histogram";
NgxServerContext::NgxServerContext(NgxRewriteDriverFactory* factory)
: SystemServerContext(factory),
ngx_factory_(factory),
initialized_(false) {
} }
NgxServerContext::~NgxServerContext() { NgxServerContext::~NgxServerContext() { }
}
NgxRewriteOptions* NgxServerContext::config() { NgxRewriteOptions* NgxServerContext::config() {
return NgxRewriteOptions::DynamicCast(global_options()); return NgxRewriteOptions::DynamicCast(global_options());
} }
void NgxServerContext::ChildInit() { SystemRequestContext* NgxServerContext::NewRequestContext(
DCHECK(!initialized_); ngx_http_request_t* r) {
if (!initialized_) { // Based on ngx_http_variable_server_port.
initialized_ = true; bool port_set = false;
set_lock_manager(ngx_factory_->caches()->GetLockManager(config())); int local_port = 0;
#if (NGX_HAVE_INET6)
if (split_statistics_.get() != NULL) { if (r->connection->local_sockaddr->sa_family == AF_INET6) {
// Readjust the SHM stuff for the new process local_port = ntohs(reinterpret_cast<struct sockaddr_in6*>(
local_statistics_->Init(false, message_handler()); r->connection->local_sockaddr)->sin6_port);
port_set = true;
// Create local stats for the ServerContext, and fill in its
// statistics() and rewrite_stats() using them; if we didn't do this here
// they would get set to the factory's by the InitServerContext call
// below.
set_statistics(split_statistics_.get());
local_rewrite_stats_.reset(new RewriteStats(
split_statistics_.get(), ngx_factory_->thread_system(),
ngx_factory_->timer()));
set_rewrite_stats(local_rewrite_stats_.get());
}
ngx_factory_->InitServerContext(this);
// TODO(oschaaf): in mod_pagespeed, the ServerContext owns
// the fetchers, and sets up the UrlAsyncFetcherStats here
} }
} #endif
if (!port_set) {
void NgxServerContext::CreateLocalStatistics( local_port = ntohs(reinterpret_cast<struct sockaddr_in*>(
Statistics* global_statistics) { r->connection->local_sockaddr)->sin_port);
local_statistics_ =
ngx_factory_->AllocateAndInitSharedMemStatistics(
hostname_identifier(), *config());
split_statistics_.reset(new SplitStatistics(
ngx_factory_->thread_system(), local_statistics_, global_statistics));
// local_statistics_ was ::InitStat'd by AllocateAndInitSharedMemStatistics,
// but we need to take care of split_statistics_.
NgxRewriteDriverFactory::InitStats(split_statistics_.get());
}
void NgxServerContext::InitStats(Statistics* statistics) {
// TODO(oschaaf): we need to port the cache flush mechanism
statistics->AddVariable(kCacheFlushCount);
statistics->AddVariable(kCacheFlushTimestampMs);
Histogram* html_rewrite_time_us_histogram =
statistics->AddHistogram(kHtmlRewriteTimeUsHistogram);
// We set the boundary at 2 seconds which is about 2 orders of magnitude
// worse than anything we have reasonably seen, to make sure we don't
// cut off actual samples.
html_rewrite_time_us_histogram->SetMaxValue(2 * Timer::kSecondUs);
// TODO(oschaaf): Once the ServerContext owns the fetchers,
// 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 ngx_str_t local_ip;
// added u_char addr[NGX_SOCKADDR_STRLEN];
// TODO(oschaaf): in mod_pagespeed, LoopbackRouteFetcher is not added when local_ip.len = NGX_SOCKADDR_STRLEN;
// one of these is set: disable_loopback_routing, slurping_enabled, or local_ip.data = addr;
// test_proxy. ngx_int_t rc = ngx_connection_local_sockaddr(r->connection, &local_ip, 0);
if (rc != NGX_OK) {
// Note the port here is our port, not from the request, since local_ip.len = 0;
// 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()));
} }
return new SystemRequestContext(thread_system()->NewMutex(),
timer(),
ps_determine_host(r),
local_port,
str_to_string_piece(local_ip));
}
GoogleString NgxServerContext::FormatOption(StringPiece option_name,
StringPiece args) {
return StrCat("pagespeed ", option_name, " ", args, ";");
} }
} // namespace net_instaweb } // namespace net_instaweb
+20 -31
View File
@@ -21,56 +21,45 @@
#ifndef NGX_SERVER_CONTEXT_H_ #ifndef NGX_SERVER_CONTEXT_H_
#define NGX_SERVER_CONTEXT_H_ #define NGX_SERVER_CONTEXT_H_
#include "net/instaweb/system/public/system_server_context.h" #include "ngx_message_handler.h"
#include "pagespeed/system/system_server_context.h"
extern "C" {
#include <ngx_http.h>
}
namespace net_instaweb { namespace net_instaweb {
class NgxRewriteDriverFactory; class NgxRewriteDriverFactory;
class NgxRewriteOptions; class NgxRewriteOptions;
class RewriteStats; class SystemRequestContext;
class SharedMemStatistics;
class Statistics;
class NgxServerContext : public SystemServerContext { class NgxServerContext : public SystemServerContext {
public: public:
explicit NgxServerContext(NgxRewriteDriverFactory* factory); NgxServerContext(
NgxRewriteDriverFactory* factory, StringPiece hostname, int port);
virtual ~NgxServerContext(); virtual ~NgxServerContext();
// We expect to use ProxyFetch with HTML. // We don't allow ProxyFetch to fetch HTML via MapProxyDomain. We will call
virtual bool ProxiesHtml() const { return true; } // set_trusted_input() on any ProxyFetches we use to transform internal HTML.
virtual bool ProxiesHtml() const { return false; }
// Call only when you need an NgxRewriteOptions. If you don't need // Call only when you need an NgxRewriteOptions. If you don't need
// nginx-specific behavior, call global_options() instead which doesn't // nginx-specific behavior, call global_options() instead which doesn't
// downcast. // downcast.
NgxRewriteOptions* config(); NgxRewriteOptions* config();
// Should be called after the child process is forked.
void ChildInit();
// Initialize this ServerContext to have its own statistics domain.
// Must be called after global_statistics has been created and had
// ::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; }
NgxRewriteDriverFactory* ngx_rewrite_driver_factory() { return ngx_factory_; } NgxRewriteDriverFactory* ngx_rewrite_driver_factory() { return ngx_factory_; }
SystemRequestContext* NewRequestContext(ngx_http_request_t* r);
NgxMessageHandler* ngx_message_handler() {
return dynamic_cast<NgxMessageHandler*>(message_handler());
}
virtual GoogleString FormatOption(StringPiece option_name, StringPiece args);
private: private:
NgxRewriteDriverFactory* ngx_factory_; NgxRewriteDriverFactory* ngx_factory_;
// hostname_identifier_ is used to distinguish the name of shared memory
// segments associated with this ServerContext
GoogleString hostname_identifier_;
bool initialized_;
// Non-NULL if we have per-vhost stats.
scoped_ptr<Statistics> split_statistics_;
// May be NULL. Owned by *split_statistics_.
SharedMemStatistics* local_statistics_;
// These are non-NULL if we have per-vhost stats.
scoped_ptr<RewriteStats> local_rewrite_stats_;
DISALLOW_COPY_AND_ASSIGN(NgxServerContext); DISALLOW_COPY_AND_ASSIGN(NgxServerContext);
}; };
-46
View File
@@ -1,46 +0,0 @@
/*
* 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: jefftk@google.com (Jeff Kaufman)
#include "ngx_thread_system.h"
#include "apr_thread_proc.h"
namespace net_instaweb {
class Timer;
NgxThreadSystem::NgxThreadSystem() : may_start_threads_(false) {}
NgxThreadSystem::~NgxThreadSystem() {}
void NgxThreadSystem::PermitThreadStarting() {
CHECK(!may_start_threads_);
may_start_threads_ = true;
}
void NgxThreadSystem::BeforeThreadRunHook() {
// We disable all signals here, since the nginx worker process is expecting to
// catch them and pagespeed doesn't use signals.
apr_setup_signal_thread();
// If this fails you can get a backtrace from gdb by setting a breakpoint on
// "pthread_create".
CHECK(may_start_threads_);
}
} // namespace net_instaweb
-56
View File
@@ -1,56 +0,0 @@
/*
* 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: jefftk@google.com (Jeff Kaufman)
//
// See ApacheThreadSystem.
//
//
#ifndef NGX_THREAD_SYSTEM_H_
#define NGX_THREAD_SYSTEM_H_
#include "base/logging.h"
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/util/public/pthread_thread_system.h"
namespace net_instaweb {
class Timer;
class NgxThreadSystem : public PthreadThreadSystem {
public:
NgxThreadSystem();
virtual ~NgxThreadSystem();
// In nginx we may only start threads after forking a worker process. In
// order to enforce this, we call PermitThreadStarting() in the worker process
// right after forking, and CHECK-fail if something tries to start a thread
// before then.
void PermitThreadStarting();
protected:
virtual void BeforeThreadRunHook();
private:
bool may_start_threads_;
DISALLOW_COPY_AND_ASSIGN(NgxThreadSystem);
};
} // namespace net_instaweb
#endif // NGX_THREAD_SYSTEM_H_
+118 -143
View File
@@ -31,22 +31,22 @@ extern "C" {
#include <map> #include <map>
#include <set> #include <set>
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/http/public/async_fetch.h" #include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/inflating_fetch.h" #include "net/instaweb/http/public/inflating_fetch.h"
#include "net/instaweb/http/public/request_headers.h"
#include "net/instaweb/http/public/response_headers.h"
#include "net/instaweb/http/public/response_headers_parser.h"
#include "net/instaweb/public/version.h" #include "net/instaweb/public/version.h"
#include "net/instaweb/util/public/condvar.h" #include "pagespeed/kernel/base/basictypes.h"
#include "net/instaweb/util/public/message_handler.h" #include "pagespeed/kernel/base/condvar.h"
#include "net/instaweb/util/public/pool.h" #include "pagespeed/kernel/base/message_handler.h"
#include "net/instaweb/util/public/pool_element.h" #include "pagespeed/kernel/base/pool.h"
#include "net/instaweb/util/public/statistics.h" #include "pagespeed/kernel/base/pool_element.h"
#include "net/instaweb/util/public/string_util.h" #include "pagespeed/kernel/base/statistics.h"
#include "net/instaweb/util/public/thread_system.h" #include "pagespeed/kernel/base/string_util.h"
#include "net/instaweb/util/public/timer.h" #include "pagespeed/kernel/base/thread_system.h"
#include "net/instaweb/util/public/writer.h" #include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/base/writer.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/http/response_headers_parser.h"
namespace net_instaweb { namespace net_instaweb {
@@ -55,6 +55,7 @@ namespace net_instaweb {
ngx_msec_t resolver_timeout, ngx_msec_t resolver_timeout,
ngx_msec_t fetch_timeout, ngx_msec_t fetch_timeout,
ngx_resolver_t* resolver, ngx_resolver_t* resolver,
int max_keepalive_requests,
ThreadSystem* thread_system, ThreadSystem* thread_system,
MessageHandler* handler) MessageHandler* handler)
: fetchers_count_(0), : fetchers_count_(0),
@@ -63,23 +64,30 @@ namespace net_instaweb {
byte_count_(0), byte_count_(0),
thread_system_(thread_system), thread_system_(thread_system),
message_handler_(handler), message_handler_(handler),
mutex_(NULL) { mutex_(NULL),
max_keepalive_requests_(max_keepalive_requests),
event_connection_(NULL) {
resolver_timeout_ = resolver_timeout; resolver_timeout_ = resolver_timeout;
fetch_timeout_ = fetch_timeout; fetch_timeout_ = fetch_timeout;
ngx_memzero(&url_, sizeof(url_)); ngx_memzero(&proxy_, sizeof(proxy_));
if (proxy != NULL && *proxy != '\0') { if (proxy != NULL && *proxy != '\0') {
url_.url.data = reinterpret_cast<u_char*>(const_cast<char*>(proxy)); proxy_.url.data = reinterpret_cast<u_char*>(const_cast<char*>(proxy));
url_.url.len = ngx_strlen(proxy); proxy_.url.len = ngx_strlen(proxy);
} }
mutex_ = thread_system_->NewMutex(); mutex_ = thread_system_->NewMutex();
log_ = log; log_ = log;
pool_ = NULL; pool_ = NULL;
command_connection_ = NULL;
pipe_fd_ = -1;
resolver_ = resolver; resolver_ = resolver;
// If init fails, set shutdown_ so no fetches will be attempted.
if (!Init(const_cast<ngx_cycle_t*>(ngx_cycle))) {
shutdown_ = true;
message_handler_->Message(
kError, "NgxUrlAsyncFetcher failed to init, fetching disabled.");
}
} }
NgxUrlAsyncFetcher::~NgxUrlAsyncFetcher() { NgxUrlAsyncFetcher::~NgxUrlAsyncFetcher() {
DCHECK(shutdown_) << "Shut down before destructing NgxUrlAsyncFetcher.";
message_handler_->Message( message_handler_->Message(
kInfo, kInfo,
"Destruct NgxUrlAsyncFetcher with [%d] active fetchers", "Destruct NgxUrlAsyncFetcher with [%d] active fetchers",
@@ -87,25 +95,48 @@ namespace net_instaweb {
CancelActiveFetches(); CancelActiveFetches();
active_fetches_.DeleteAll(); active_fetches_.DeleteAll();
NgxConnection::Terminate();
if (pool_ != NULL) { if (pool_ != NULL) {
ngx_destroy_pool(pool_); ngx_destroy_pool(pool_);
pool_ = NULL; pool_ = NULL;
} }
if (command_connection_ != NULL) {
ngx_close_connection(command_connection_);
command_connection_ = NULL;
}
if (pipe_fd_ != -1) {
close(pipe_fd_);
pipe_fd_ = -1;
}
if (mutex_ != NULL) { if (mutex_ != NULL) {
delete mutex_; delete mutex_;
mutex_ = NULL; mutex_ = NULL;
} }
} }
bool NgxUrlAsyncFetcher::ParseUrl(ngx_url_t* url, ngx_pool_t* pool) {
size_t scheme_offset;
u_short port;
if (ngx_strncasecmp(url->url.data, reinterpret_cast<u_char*>(
const_cast<char*>("http://")), 7) == 0) {
scheme_offset = 7;
port = 80;
} else if (ngx_strncasecmp(url->url.data, reinterpret_cast<u_char*>(
const_cast<char*>("https://")), 8) == 0) {
scheme_offset = 8;
port = 443;
} else {
scheme_offset = 0;
port = 80;
}
url->url.data += scheme_offset;
url->url.len -= scheme_offset;
url->default_port = port;
// See: http://lxr.evanmiller.org/http/source/core/ngx_inet.c#L875
url->no_resolve = 0;
url->uri_part = 1;
if (ngx_parse_url(pool, url) == NGX_OK) {
return true;
}
return false;
}
// If there are still active requests, cancel them. // If there are still active requests, cancel them.
void NgxUrlAsyncFetcher::CancelActiveFetches() { void NgxUrlAsyncFetcher::CancelActiveFetches() {
// TODO(oschaaf): this seems tricky, this may end up calling // TODO(oschaaf): this seems tricky, this may end up calling
@@ -120,9 +151,13 @@ namespace net_instaweb {
// Create the pool for fetcher, create the pipe, add the read event for main // Create the pool for fetcher, create the pipe, add the read event for main
// thread. It should be called in the worker process. // thread. It should be called in the worker process.
bool NgxUrlAsyncFetcher::Init() { bool NgxUrlAsyncFetcher::Init(ngx_cycle_t* cycle) {
log_ = ngx_cycle->log; log_ = cycle->log;
CHECK(event_connection_ == NULL) << "event connection already set";
event_connection_ = new NgxEventConnection(ReadCallback);
if (!event_connection_->Init(cycle)) {
return false;
}
if (pool_ == NULL) { if (pool_ == NULL) {
pool_ = ngx_create_pool(4096, log_); pool_ = ngx_create_pool(4096, log_);
if (pool_ == NULL) { if (pool_ == NULL) {
@@ -132,58 +167,44 @@ namespace net_instaweb {
} }
} }
int pipe_fds[2]; if (proxy_.url.len == 0) {
int rc = pipe(pipe_fds);
if (rc != 0) {
ngx_log_error(NGX_LOG_ERR, log_, 0, "pipe() failed");
return false;
}
if (ngx_nonblocking(pipe_fds[0]) == -1) {
ngx_log_error(NGX_LOG_ERR, log_, 0, "nonblocking pipe[0] failed");
return false;
}
if (ngx_nonblocking(pipe_fds[1]) == -1) {
ngx_log_error(NGX_LOG_ERR, log_, 0, "nonblocking pipe[1] failed");
return false;
}
pipe_fd_ = pipe_fds[1];
command_connection_ = ngx_get_connection(pipe_fds[0], log_);
if (command_connection_ == NULL) {
close(pipe_fds[1]);
close(pipe_fds[0]);
pipe_fd_ = -1;
return false;
}
command_connection_->recv = ngx_recv;
command_connection_->send = ngx_send;
command_connection_->recv_chain = ngx_recv_chain;
command_connection_->send_chain = ngx_send_chain;
command_connection_->log = log_;
command_connection_->read->log = log_;
command_connection_->write->log = log_;
command_connection_->data = this;
command_connection_->read->handler = CommandHandler;
ngx_add_event(command_connection_->read, NGX_READ_EVENT, 0);
if (url_.url.len == 0) {
return true; return true;
} }
// TODO(oschaaf): shouldn't we do this earlier? Do we need to clean // TODO(oschaaf): shouldn't we do this earlier? Do we need to clean
// up when parsing the url failed? // up when parsing the url failed?
if (ngx_parse_url(pool_, &url_) != NGX_OK) { if (!ParseUrl(&proxy_, pool_)) {
ngx_log_error(NGX_LOG_ERR, log_, 0, ngx_log_error(NGX_LOG_ERR, log_, 0,
"NgxUrlAsyncFetcher::Init parse proxy[%V] failed", &url_.url); "NgxUrlAsyncFetcher::Init parse proxy[%V] failed", &proxy_.url);
return false; return false;
} }
return true; return true;
} }
void NgxUrlAsyncFetcher::ShutDown() { void NgxUrlAsyncFetcher::ShutDown() {
shutdown_ = true; shutdown_ = true;
SendCmd('S'); if (!pending_fetches_.empty()) {
for (Pool<NgxFetch>::iterator p = pending_fetches_.begin(),
e = pending_fetches_.end(); p != e; p++) {
NgxFetch* fetch = *p;
fetch->CallbackDone(false);
}
pending_fetches_.DeleteAll();
}
if (!active_fetches_.empty()) {
for (Pool<NgxFetch>::iterator p = active_fetches_.begin(),
e = active_fetches_.end(); p != e; p++) {
NgxFetch* fetch = *p;
fetch->CallbackDone(false);
}
active_fetches_.Clear();
}
if (event_connection_ != NULL) {
event_connection_->Shutdown();
delete event_connection_;
event_connection_ = NULL;
}
} }
// It's called in the rewrite thread. All the fetches are started at // It's called in the rewrite thread. All the fetches are started at
@@ -191,92 +212,46 @@ namespace net_instaweb {
void NgxUrlAsyncFetcher::Fetch(const GoogleString& url, void NgxUrlAsyncFetcher::Fetch(const GoogleString& url,
MessageHandler* message_handler, MessageHandler* message_handler,
AsyncFetch* async_fetch) { AsyncFetch* async_fetch) {
async_fetch = EnableInflation(async_fetch, NULL); // Don't accept new fetches when shut down. This flow is also entered when
// we did not initialize properly in ::Init().
if (shutdown_) {
async_fetch->Done(false);
return;
}
async_fetch = EnableInflation(async_fetch);
NgxFetch* fetch = new NgxFetch(url, async_fetch, NgxFetch* fetch = new NgxFetch(url, async_fetch,
message_handler, fetch_timeout_, log_); message_handler, log_);
ScopedMutex lock(mutex_); ScopedMutex lock(mutex_);
pending_fetches_.Add(fetch); pending_fetches_.Add(fetch);
SendCmd('F');
}
// send command to nginx main thread // TODO(oschaaf): thread safety on written vs shutdown.
// 'F' : start a fetch // It is possible that shutdown() is called after writing an event? In that
// 'S' : shutdown the fetcher // case, this could (rarely) fail when it shouldn't.
bool NgxUrlAsyncFetcher::SendCmd(const char command) { bool written = event_connection_->WriteEvent(this);
int rc; CHECK(written || shutdown_) << "NgxUrlAsyncFetcher: event write failure";
while (true) {
rc = write(pipe_fd_, &command, 1);
if (rc == 1) {
return true;
} else if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
// TODO(junmin): It's rare. But it need be fixed.
} else {
return false;
}
}
return true;
} }
// This is the read event which is called in the main thread. // This is the read event which is called in the main thread.
// It will do the real work. Add the work event and start the fetch. // It will do the real work. Add the work event and start the fetch.
void NgxUrlAsyncFetcher::CommandHandler(ngx_event_t *cmdev) { void NgxUrlAsyncFetcher::ReadCallback(const ps_event_data& data) {
char command; std::vector<NgxFetch*> to_start;
int rc; NgxUrlAsyncFetcher* fetcher = reinterpret_cast<NgxUrlAsyncFetcher*>(
ngx_connection_t* c = static_cast<ngx_connection_t*>(cmdev->data); data.sender);
NgxUrlAsyncFetcher* fetcher = static_cast<NgxUrlAsyncFetcher*>(c->data);
do {
rc = read(c->fd, &command, 1);
} while (rc == -1 && errno == EINTR);
CHECK(rc == -1 || rc == 0 || rc == 1); fetcher->mutex_->Lock();
fetcher->completed_fetches_.DeleteAll();
if (rc == -1 || rc == 0) { for (Pool<NgxFetch>::iterator p = fetcher->pending_fetches_.begin(),
// EAGAIN e = fetcher->pending_fetches_.end(); p != e; p++) {
return; NgxFetch* fetch = *p;
to_start.push_back(fetch);
} }
std::vector<NgxFetch*> to_start; fetcher->pending_fetches_.Clear();
fetcher->mutex_->Unlock();
switch (command) { for (size_t i = 0; i < to_start.size(); i++) {
// All the new fetches are appended in the pending_fetches. fetcher->StartFetch(to_start[i]);
// Start all these fetches.
case 'F':
fetcher->mutex_->Lock();
fetcher->completed_fetches_.DeleteAll();
for (Pool<NgxFetch>::iterator p = fetcher->pending_fetches_.begin(),
e = fetcher->pending_fetches_.end(); p != e; p++) {
NgxFetch* fetch = *p;
to_start.push_back(fetch);
}
fetcher->pending_fetches_.Clear();
fetcher->mutex_->Unlock();
for (size_t i = 0; i < to_start.size(); i++) {
fetcher->StartFetch(to_start[i]);
}
CHECK(ngx_handle_read_event(cmdev, 0) == NGX_OK);
break;
// Shutdown all the fetches.
case 'S':
if (!fetcher->pending_fetches_.empty()) {
fetcher->pending_fetches_.DeleteAll();
}
if (!fetcher->active_fetches_.empty()) {
for (Pool<NgxFetch>::iterator p = fetcher->active_fetches_.begin(),
e = fetcher->active_fetches_.end(); p != e; p++) {
NgxFetch* fetch = *p;
fetch->CallbackDone(false);
}
fetcher->active_fetches_.Clear();
}
CHECK(ngx_del_event(cmdev, NGX_READ_EVENT, 0) == NGX_OK);
break;
default:
break;
} }
return; return;
+18 -13
View File
@@ -33,11 +33,14 @@ extern "C" {
} }
#include <vector> #include <vector>
#include "ngx_event_connection.h"
#include "net/instaweb/http/public/url_async_fetcher.h" #include "net/instaweb/http/public/url_async_fetcher.h"
#include "net/instaweb/util/public/basictypes.h" #include "pagespeed/kernel/base/basictypes.h"
#include "net/instaweb/util/public/pool.h" #include "pagespeed/kernel/base/pool.h"
#include "net/instaweb/util/public/string.h" #include "pagespeed/kernel/base/string.h"
#include "net/instaweb/util/public/thread_system.h" #include "pagespeed/kernel/base/thread_system.h"
namespace net_instaweb { namespace net_instaweb {
@@ -53,27 +56,27 @@ class NgxUrlAsyncFetcher : public UrlAsyncFetcher {
NgxUrlAsyncFetcher( NgxUrlAsyncFetcher(
const char* proxy, ngx_log_t* log, ngx_msec_t resolver_timeout, const char* proxy, ngx_log_t* log, ngx_msec_t resolver_timeout,
ngx_msec_t fetch_timeout, ngx_resolver_t* resolver, ngx_msec_t fetch_timeout, ngx_resolver_t* resolver,
ThreadSystem* thread_system, MessageHandler* handler); int max_keepalive_requests, ThreadSystem* thread_system,
MessageHandler* handler);
~NgxUrlAsyncFetcher(); ~NgxUrlAsyncFetcher();
// It should be called in the module init_process callback function. Do some // It should be called in the module init_process callback function. Do some
// intializations which can't be done in the master process // intializations which can't be done in the master process
bool Init(); bool Init(ngx_cycle_t* cycle);
// shutdown all the fetches. // shutdown all the fetches.
virtual void ShutDown(); virtual void ShutDown();
// the read handler in the main thread
static void ReadCallback(const ps_event_data& data);
virtual bool SupportsHttps() const { return false; } virtual bool SupportsHttps() const { return false; }
virtual void Fetch(const GoogleString& url, virtual void Fetch(const GoogleString& url,
MessageHandler* message_handler, MessageHandler* message_handler,
AsyncFetch* callback); AsyncFetch* callback);
// send the command from the current thread to main thread
bool SendCmd(const char command);
// the read handler in the main thread
static void CommandHandler(ngx_event_t* cmdev);
bool StartFetch(NgxFetch* fetch); bool StartFetch(NgxFetch* fetch);
// Remove the completed fetch from the active fetch set, and put it into a // Remove the completed fetch from the active fetch set, and put it into a
@@ -115,13 +118,14 @@ class NgxUrlAsyncFetcher : public UrlAsyncFetcher {
private: private:
static void TimeoutHandler(ngx_event_t* tev); static void TimeoutHandler(ngx_event_t* tev);
static bool ParseUrl(ngx_url_t* url, ngx_pool_t* pool);
friend class NgxFetch; friend class NgxFetch;
NgxFetchPool active_fetches_; NgxFetchPool active_fetches_;
// Add the pending task to this list // Add the pending task to this list
NgxFetchPool pending_fetches_; NgxFetchPool pending_fetches_;
NgxFetchPool completed_fetches_; NgxFetchPool completed_fetches_;
ngx_url_t url_; ngx_url_t proxy_;
int fetchers_count_; int fetchers_count_;
bool shutdown_; bool shutdown_;
@@ -135,12 +139,13 @@ class NgxUrlAsyncFetcher : public UrlAsyncFetcher {
ngx_pool_t* pool_; ngx_pool_t* pool_;
ngx_log_t* log_; ngx_log_t* log_;
ngx_connection_t* command_connection_; // the command pipe
int pipe_fd_; // the write pipe end
ngx_resolver_t* resolver_; ngx_resolver_t* resolver_;
int max_keepalive_requests_;
ngx_msec_t resolver_timeout_; ngx_msec_t resolver_timeout_;
ngx_msec_t fetch_timeout_; ngx_msec_t fetch_timeout_;
NgxEventConnection* event_connection_;
DISALLOW_COPY_AND_ASSIGN(NgxUrlAsyncFetcher); DISALLOW_COPY_AND_ASSIGN(NgxUrlAsyncFetcher);
}; };
-257
View File
@@ -1,257 +0,0 @@
// Copyright 2011 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 "pthread_shared_mem.h"
#include <fcntl.h>
#include <pthread.h>
#include <sys/mman.h>
#include <unistd.h>
#include <cerrno>
#include <cstddef>
#include <map>
#include <utility>
#include "net/instaweb/util/public/abstract_shared_mem.h"
#include "net/instaweb/util/public/abstract_mutex.h"
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/util/public/message_handler.h"
#include "net/instaweb/util/public/string.h"
namespace net_instaweb {
namespace ngx {
namespace {
// This implementation relies on readonly copies of old memory and shared R/W
// mappings being kept across a fork. It simply stashes addresses of
// shared mmap segments into a map where kid processes can pick them up.
// close() a fd logging failure and dealing with EINTR.
void CheckedClose(int fd, MessageHandler* message_handler) {
while (close(fd) != 0) {
if (errno != EINTR) {
message_handler->Message(kWarning, "Problem closing SHM segment fd:%d",
errno);
return;
}
}
}
// Unlike PthreadMutex this doesn't own the lock, but rather refers to an
// external one.
class PthreadSharedMemMutex : public AbstractMutex {
public:
explicit PthreadSharedMemMutex(pthread_mutex_t* external_mutex)
: external_mutex_(external_mutex) {}
virtual bool TryLock() {
return (pthread_mutex_trylock(external_mutex_) == 0);
}
virtual void Lock() {
pthread_mutex_lock(external_mutex_);
}
virtual void Unlock() {
pthread_mutex_unlock(external_mutex_);
}
private:
pthread_mutex_t* external_mutex_;
DISALLOW_COPY_AND_ASSIGN(PthreadSharedMemMutex);
};
class PthreadSharedMemSegment : public AbstractSharedMemSegment {
public:
// We will be representing memory mapped in the [base, base + size) range.
PthreadSharedMemSegment(char* base, size_t size, MessageHandler* handler)
: base_(base),
size_(size) {
}
virtual ~PthreadSharedMemSegment() {
}
virtual volatile char* Base() {
return base_;
}
virtual size_t SharedMutexSize() const {
return sizeof(pthread_mutex_t);
}
virtual bool InitializeSharedMutex(size_t offset, MessageHandler* handler) {
pthread_mutexattr_t attr;
if (pthread_mutexattr_init(&attr) != 0) {
handler->Message(kError, "pthread_mutexattr_init failed with errno:%d",
errno);
return false;
}
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) != 0) {
pthread_mutexattr_destroy(&attr);
handler->Message(
kError, "pthread_mutexattr_setpshared failed with errno:%d", errno);
return false;
}
if (pthread_mutex_init(MutexPtr(offset), &attr) != 0) {
pthread_mutexattr_destroy(&attr);
handler->Message(kError, "pthread_mutex_init failed with errno:%d",
errno);
return false;
}
pthread_mutexattr_destroy(&attr);
return true;
}
virtual AbstractMutex* AttachToSharedMutex(size_t offset) {
return new PthreadSharedMemMutex(MutexPtr(offset));
}
private:
pthread_mutex_t* MutexPtr(size_t offset) {
return reinterpret_cast<pthread_mutex_t*>(base_ + offset);
}
char* const base_;
const size_t size_;
DISALLOW_COPY_AND_ASSIGN(PthreadSharedMemSegment);
};
pthread_mutex_t segment_bases_lock = PTHREAD_MUTEX_INITIALIZER;
} // namespace
size_t PthreadSharedMem::s_instance_count_ = 0;
PthreadSharedMem::SegmentBaseMap* PthreadSharedMem::segment_bases_ = NULL;
PthreadSharedMem::PthreadSharedMem() {
instance_number_ = ++s_instance_count_;
}
PthreadSharedMem::~PthreadSharedMem() {
}
size_t PthreadSharedMem::SharedMutexSize() const {
return sizeof(pthread_mutex_t);
}
AbstractSharedMemSegment* PthreadSharedMem::CreateSegment(
const GoogleString& name, size_t size, MessageHandler* handler) {
GoogleString prefixed_name = PrefixSegmentName(name);
// Create the memory
int fd = open("/dev/zero", O_RDWR);
if (fd == -1) {
handler->Message(kError, "Unable to create SHM segment %s, errno=%d.",
prefixed_name.c_str(), errno);
return NULL;
}
// map it
char* base = reinterpret_cast<char*>(
mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
CheckedClose(fd, handler);
if (base == MAP_FAILED) {
return NULL;
}
SegmentBaseMap* bases = AcquireSegmentBases();
(*bases)[prefixed_name] = base;
UnlockSegmentBases();
return new PthreadSharedMemSegment(base, size, handler);
}
AbstractSharedMemSegment* PthreadSharedMem::AttachToSegment(
const GoogleString& name, size_t size, MessageHandler* handler) {
GoogleString prefixed_name = PrefixSegmentName(name);
SegmentBaseMap* bases = AcquireSegmentBases();
SegmentBaseMap::const_iterator i = bases->find(prefixed_name);
if (i == bases->end()) {
handler->Message(kError, "Unable to find SHM segment %s to attach to.",
prefixed_name.c_str());
UnlockSegmentBases();
return NULL;
}
char* base = i->second;
UnlockSegmentBases();
return new PthreadSharedMemSegment(base, size, handler);
}
void PthreadSharedMem::DestroySegment(const GoogleString& name,
MessageHandler* handler) {
GoogleString prefixed_name = PrefixSegmentName(name);
// Note that in the process state children will not see any mutations
// we make here, so it acts mostly for checking in that case.
SegmentBaseMap* bases = AcquireSegmentBases();
SegmentBaseMap::iterator i = bases->find(prefixed_name);
if (i != bases->end()) {
bases->erase(i);
if (bases->empty()) {
delete segment_bases_;
segment_bases_ = NULL;
}
} else {
handler->Message(kError, "Attempt to destroy unknown SHM segment %s.",
prefixed_name.c_str());
}
UnlockSegmentBases();
}
PthreadSharedMem::SegmentBaseMap* PthreadSharedMem::AcquireSegmentBases() {
PthreadSharedMemMutex lock(&segment_bases_lock);
lock.Lock();
if (segment_bases_ == NULL) {
segment_bases_ = new SegmentBaseMap();
}
return segment_bases_;
}
void PthreadSharedMem::UnlockSegmentBases() {
PthreadSharedMemMutex lock(&segment_bases_lock);
lock.Unlock();
}
GoogleString PthreadSharedMem::PrefixSegmentName(const GoogleString& name) {
GoogleString res;
StrAppend(&res, "[", IntegerToString(instance_number_), "]", name);
return res;
}
void PthreadSharedMem::Terminate() {
// Clean up the local memory associated with the maps to shared memory
// storage.
PthreadSharedMemMutex lock(&segment_bases_lock);
lock.Lock();
if (segment_bases_ != NULL) {
delete segment_bases_;
segment_bases_ = NULL;
}
lock.Unlock();
}
} // namespace ngx
} // namespace net_instaweb
-88
View File
@@ -1,88 +0,0 @@
// Copyright 2011 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)
#ifndef NET_INSTAWEB_UTIL_PUBLIC_PTHREAD_SHARED_MEM_H_
#define NET_INSTAWEB_UTIL_PUBLIC_PTHREAD_SHARED_MEM_H_
#include <cstddef>
#include <map>
#include "net/instaweb/util/public/abstract_shared_mem.h"
#include "net/instaweb/util/public/basictypes.h"
#include "net/instaweb/util/public/string.h"
namespace net_instaweb {
class MessageHandler;
namespace ngx {
// POSIX shared memory support, using mmap/pthread_mutexattr_setpshared
// Supports both processes and threads, but processes that want to access it
// must be results of just fork (without exec), and all the CreateSegment
// calls must occur before the fork.
//
// This implementation is also not capable of deallocating segments except
// at exit, so it should not be used when the set of segments may be dynamic.
class PthreadSharedMem : public AbstractSharedMem {
public:
PthreadSharedMem();
virtual ~PthreadSharedMem();
virtual size_t SharedMutexSize() const;
virtual AbstractSharedMemSegment* CreateSegment(
const GoogleString& name, size_t size, MessageHandler* handler);
virtual AbstractSharedMemSegment* AttachToSegment(
const GoogleString& name, size_t size, MessageHandler* handler);
virtual void DestroySegment(const GoogleString& name,
MessageHandler* handler);
// Frees all lazy-initialized memory used to track shared-memory segments.
static void Terminate();
private:
typedef std::map<GoogleString, char*> SegmentBaseMap;
// Accessor for below. Note that the segment_bases_lock will be held at exit.
static SegmentBaseMap* AcquireSegmentBases();
static void UnlockSegmentBases();
// Prefixes the passed in segment name with the current instance number.
GoogleString PrefixSegmentName(const GoogleString& name);
// The root process stores segment locations here. Child processes will
// inherit a readonly copy of this map after the fork. Note that this is
// initialized in a thread-unsafe manner, given the above assumptions.
static SegmentBaseMap* segment_bases_;
// Holds the number of times a PthreadSharedMem has been created.
static size_t s_instance_count_;
// Used to prefix segment names, so that when two runtimes are active at the
// same moment they will not have overlapping segment names. This occurs in
// ngx_pagespeed during a configuration reload, where first a new factory is
// created, before destroying the old one.
size_t instance_number_;
DISALLOW_COPY_AND_ASSIGN(PthreadSharedMem);
};
} // namespace ngx
} // namespace net_instaweb
#endif // NET_INSTAWEB_UTIL_PUBLIC_PTHREAD_SHARED_MEM_H_
Executable → Regular
+678 -1002
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+22 -3
View File
@@ -23,9 +23,9 @@
# Exits with status 2 if command line args are wrong. # Exits with status 2 if command line args are wrong.
# #
# Usage: # Usage:
# ./run_tests.sh primary_port secondary_port mod_pagespeed_dir # ./run_tests.sh primary_port secondary_port mod_pagespeed_dir pagespeed_test_host
# Example: # Example:
# ./run_tests.sh 8050 8051 /path/to/mod_pagespeed # ./run_tests.sh 8050 8051 /path/to/mod_pagespeed www.modpagespeed.com
# #
# Normally we test only with the native fetcher off. Set # Normally we test only with the native fetcher off. Set
@@ -43,7 +43,7 @@ RUN_TESTS=${RUN_TESTS:-true}
# true. # true.
USE_VALGRIND=${USE_VALGRIND:-false} USE_VALGRIND=${USE_VALGRIND:-false}
if [ "$#" -ne 4 ] ; then if [ "$#" -ne 5 ] ; then
echo "Usage: $0 primary_port secondary_port mod_pagespeed_dir" echo "Usage: $0 primary_port secondary_port mod_pagespeed_dir"
echo " nginx_executable" echo " nginx_executable"
exit 2 exit 2
@@ -53,6 +53,14 @@ PRIMARY_PORT="$1"
SECONDARY_PORT="$2" SECONDARY_PORT="$2"
MOD_PAGESPEED_DIR="$3" MOD_PAGESPEED_DIR="$3"
NGINX_EXECUTABLE="$4" NGINX_EXECUTABLE="$4"
PAGESPEED_TEST_HOST="$5"
RCPORT1=9991
RCPORT2=9992
RCPORT3=9993
RCPORT4=9994
RCPORT5=9995
RCPORT6=9996
RCPORT7=9997
this_dir="$( cd $(dirname "$0") && pwd)" this_dir="$( cd $(dirname "$0") && pwd)"
@@ -62,7 +70,15 @@ function run_test_checking_failure() {
SECONDARY_PORT="$SECONDARY_PORT" \ SECONDARY_PORT="$SECONDARY_PORT" \
MOD_PAGESPEED_DIR="$MOD_PAGESPEED_DIR" \ MOD_PAGESPEED_DIR="$MOD_PAGESPEED_DIR" \
NGINX_EXECUTABLE="$NGINX_EXECUTABLE" \ NGINX_EXECUTABLE="$NGINX_EXECUTABLE" \
PAGESPEED_TEST_HOST="$PAGESPEED_TEST_HOST" \
RUN_TESTS="$RUN_TESTS" \ RUN_TESTS="$RUN_TESTS" \
RCPORT1="$RCPORT1" \
RCPORT2="$RCPORT2" \
RCPORT3="$RCPORT3" \
RCPORT4="$RCPORT4" \
RCPORT5="$RCPORT5" \
RCPORT6="$RCPORT6" \
RCPORT7="$RCPORT7" \
bash "$this_dir/nginx_system_test.sh" bash "$this_dir/nginx_system_test.sh"
STATUS=$? STATUS=$?
echo "With $@ setup." echo "With $@ setup."
@@ -73,6 +89,9 @@ function run_test_checking_failure() {
3) 3)
return # Only expected failures. return # Only expected failures.
;; ;;
4)
return # Return passing error code when running manually.
;;
*) *)
exit 1 # Real failure. exit 1 # Real failure.
esac esac
+165
View File
@@ -0,0 +1,165 @@
# 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@we-amp.com (Otto van der Schaaf)
# The first few suppressions can be found in other modules
# and easily found when searched for, and seem false positives.
{
<nginx false positive>
Memcheck:Param
socketcall.sendmsg(msg.msg_iov[i])
fun:__sendmsg_nocancel
fun:ngx_write_channel
fun:ngx_signal_worker_processes
fun:ngx_master_process_cycle
fun:main
}
{
<nginx false positive>
Memcheck:Param
socketcall.sendmsg(msg.msg_iov[i])
fun:__sendmsg_nocancel
fun:ngx_write_channel
fun:ngx_master_process_cycle
fun:main
}
{
<nginx false positive>
Memcheck:Param
socketcall.sendmsg(msg.msg_iov[i])
fun:__sendmsg_nocancel
fun:ngx_write_channel
fun:ngx_pass_open_channel
fun:ngx_start_cache_manager_processes
fun:ngx_master_process_cycle
fun:main
}
{
<nginx false positive>
Memcheck:Param
socketcall.sendmsg(msg.msg_iov[i])
fun:__sendmsg_nocancel
fun:ngx_write_channel
fun:ngx_pass_open_channel
fun:ngx_start_cache_manager_processes
fun:ngx_master_process_cycle
fun:main
}
{
<nginx false positive>
Memcheck:Leak
fun:malloc
fun:ngx_alloc
fun:ngx_event_process_init
fun:ngx_worker_process_init
fun:ngx_worker_process_cycle
fun:ngx_spawn_process
fun:ngx_start_worker_processes
fun:ngx_master_process_cycle
fun:main
}
{
<nginx false positive>
Memcheck:Param
socketcall.sendmsg(msg.msg_iov[i])
fun:__sendmsg_nocancel
fun:ngx_write_channel
fun:ngx_pass_open_channel
fun:ngx_start_worker_processes
fun:ngx_master_process_cycle
fun:main
}
# similar to http://trac.nginx.org/nginx/ticket/369
{
<nginx false positive>
Memcheck:Param
pwrite64(buf)
obj:/lib/x86_64-linux-gnu/libpthread-2.15.so
fun:ngx_write_file
fun:ngx_write_chain_to_file
fun:ngx_write_chain_to_temp_file
fun:ngx_event_pipe_write_chain_to_temp_file
fun:ngx_event_pipe
fun:ngx_http_upstream_process_upstream
fun:ngx_http_upstream_process_header
fun:ngx_http_upstream_handler
fun:ngx_epoll_process_events
fun:ngx_process_events_and_timers
fun:ngx_worker_process_cycle
}
# Mentioned in https://github.com/pagespeed/ngx_pagespeed/issues/103
# Assuming a false postives as the issue is closed.
{
<nginx false positive>
Memcheck:Param
write(buf)
obj:/lib/x86_64-linux-gnu/libpthread-2.15.so
fun:ngx_log_error_core
fun:ngx_http_parse_complex_uri
fun:ngx_http_process_request_uri
fun:ngx_http_process_request_line
fun:ngx_http_wait_request_handler
fun:ngx_epoll_process_events
fun:ngx_process_events_and_timers
fun:ngx_worker_process_cycle
fun:ngx_spawn_process
fun:ngx_start_worker_processes
fun:ngx_master_process_cycle
}
# Extra suppresions for testing in release mode:
{
<re2 uninitialised value in optimized code>
Memcheck:Cond
fun:_ZN3re24Prog8OptimizeEv
...
}
{
<re2 uninitialised value in optimized code>
Memcheck:Value8
fun:_ZN3re24Prog8OptimizeEv
...
}
{
<re2 uninitialised value in optimized code>
Memcheck:Cond
fun:_ZN3re2L4AddQEPNS_9SparseSetEi
...
}
{
<re2 uninitialised value in optimized code>
Memcheck:Value8
fun:_ZN3re2L4AddQEPNS_9SparseSetEi
...
}
{
<re2 uninitialized value in optimized code>
Memcheck:Value8
fun:_ZN3re23DFA10AddToQueueEPNS0_5WorkqEij
...
}
{
<re2 uninitialized value in optimized code>
Memcheck:Cond
fun:_ZN3re23DFA10AddToQueueEPNS0_5WorkqEij
...
}