Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c3bff67637 | |||
| 5a1a29ee8b | |||
| 61025c5e4f | |||
| d3e7900704 | |||
| 85e19c962b | |||
| 20fd7d18dd | |||
| 4667aa1fc3 | |||
| bfaf4268cf | |||
| 215071a383 | |||
| 630f7d848b | |||
| d90245af69 | |||
| c754cf1be0 | |||
| 9e4d26da5e | |||
| 027d481817 | |||
| 67106e920e | |||
| 207eb2d131 | |||
| d9e2142f31 | |||
| 33d006625e | |||
| 2dcaa95278 | |||
| f5252b569a | |||
| 4783144e7d | |||
| 83205c9c31 | |||
| 625e762961 | |||
| c20affe323 | |||
| 7a9e6de802 | |||
| 96cf9a22f7 | |||
| ab83a70a35 | |||
| 658b2cf7a9 | |||
| 092bbf2862 | |||
| f04c533df0 | |||
| 8468e4849a | |||
| df5736609d | |||
| 7fbb2c61ee | |||
| af772c2fe8 | |||
| a4bd9b9c13 | |||
| f87d0f7ae2 | |||
| 501742cb56 | |||
| a669be99b1 | |||
| 328d3afc9b | |||
| 2681c24ee0 | |||
| f86f47fda4 | |||
| 179c81afa3 | |||
| 8d7eb20c89 | |||
| 1fe6c54b94 | |||
| 1667879202 | |||
| 0076e45677 | |||
| 1f3560ea21 | |||
| 54352bff72 | |||
| 329985659c | |||
| db870f7023 | |||
| ed14455412 | |||
| be4d263d10 | |||
| 0bafd6b7e0 | |||
| 9bbe912bd7 | |||
| b78eb8a939 | |||
| e082a01912 | |||
| fa5815e1e8 | |||
| f12af2f03b | |||
| e22fae46bc | |||
| 53a599fbd4 | |||
| 70c47c13a4 | |||
| 8021751d69 | |||
| 6b29b5220d | |||
| 07286005a6 | |||
| 721c49dc71 | |||
| 658a30d836 | |||
| 94688bd1e5 | |||
| 26aaf221c7 | |||
| 530bf3c05e | |||
| dfedc6b025 | |||
| 4e3fe6f35f | |||
| af6706a4c9 | |||
| b6c3001df2 | |||
| b8ff84ed9b | |||
| b83bb636f0 | |||
| 7d6b6c4b4c | |||
| 2629865c59 | |||
| fd546f270b | |||
| 641fb971d1 | |||
| e40cde221c | |||
| f956ef92e9 | |||
| 687e0a7028 | |||
| 7c15cd83f4 | |||
| 8f6ac0660e | |||
| 422d5afa6b | |||
| f653094040 | |||
| 8430a6c40e | |||
| d4fa76463d | |||
| 1e5769df11 | |||
| f1a800d37f | |||
| ee4958e7dd | |||
| dbead4a62e | |||
| 2b2d19e78d | |||
| 9ed9fecc0f | |||
| 06e64dec7a | |||
| 420b58c346 | |||
| 36554ce92f | |||
| c5265b47cf | |||
| c29ac1e6a3 | |||
| 6e86835599 | |||
| f70eb5df40 | |||
| 4650aa4a3f | |||
| 34e3101edd | |||
| fdbdf11bab | |||
| db238e7705 | |||
| a196cfe071 | |||
| 442d319aef | |||
| a48c243e3e | |||
| 5c17cb671c | |||
| 94d004e72c | |||
| 21a9705b78 | |||
| 137182792e | |||
| 3dbb845603 | |||
| ac7a6bce2c | |||
| 9baf3d01d3 | |||
| 1db13030fa | |||
| be2fb57d85 | |||
| 3a99b9adff | |||
| 8cb48034f0 | |||
| 49c96c9202 | |||
| ad2ea9498b | |||
| 3a085e114d | |||
| 3fbb740101 | |||
| fa99ac39b4 | |||
| d0de777452 | |||
| eb9979f048 | |||
| c57c16c499 | |||
| 70284c987e | |||
| 64f2ab6591 | |||
| c739bf29c4 | |||
| bb1093e8b2 | |||
| 51eaeddfba | |||
| 122c234570 | |||
| ddf844b680 | |||
| a245f40bcf | |||
| cafb06c011 | |||
| cbfbb5b6d6 | |||
| 606a75a068 | |||
| 0c26aafc2f | |||
| 8bd4ed2ec2 | |||
| 9c5fb3107e | |||
| 1c86ab66be | |||
| f05e3cf281 | |||
| 177b70b995 | |||
| 3b2b28559a | |||
| 7e89db8fa1 | |||
| 9b3ab25cea | |||
| 54ef25214c | |||
| b9db498199 | |||
| 6503ebfb1a | |||
| baf35dc906 | |||
| f4466918f3 | |||
| 3b6caa38aa | |||
| ad6429d26f | |||
| 59cdafaf70 | |||
| 34ebc2d179 | |||
| 49c9de63cd | |||
| 502a604a26 | |||
| fca58f2d6f | |||
| b2bbdcc0df | |||
| bdb5de5a2f | |||
| 960d0940bb | |||
| e7a91c2f0a | |||
| e583afdb49 | |||
| 53138d7b34 | |||
| e45acf4613 | |||
| 47e3364332 | |||
| 49760f03a0 | |||
| 2f5afcddd1 | |||
| 67beee1444 | |||
| cd80e92df1 | |||
| e303c92041 | |||
| ccd36dd658 | |||
| 3a9953e25c | |||
| 311ea897cf | |||
| 4cc3e4def3 |
@@ -37,21 +37,22 @@ recompiling Tengine](https://github.com/pagespeed/ngx_pagespeed/wiki/Using-ngx_p
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cd ~
|
$ cd ~
|
||||||
$ wget https://github.com/pagespeed/ngx_pagespeed/archive/release-1.6.29.5-beta.zip
|
$ wget https://github.com/pagespeed/ngx_pagespeed/archive/v1.7.30.4-beta.zip
|
||||||
$ unzip release-1.6.29.5-beta.zip # or unzip release-1.6.29.5-beta
|
$ unzip v1.7.30.4-beta.zip # or unzip v1.7.30.4-beta
|
||||||
$ cd ngx_pagespeed-release-1.6.29.5-beta/
|
$ cd ngx_pagespeed-1.7.30.4-beta/
|
||||||
$ wget https://dl.google.com/dl/page-speed/psol/1.6.29.5.tar.gz
|
$ wget https://dl.google.com/dl/page-speed/psol/1.7.30.4.tar.gz
|
||||||
$ tar -xzvf 1.6.29.5.tar.gz # expands to psol/
|
$ tar -xzvf 1.7.30.4.tar.gz # expands to psol/
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Download and build nginx:
|
3. Download and build nginx:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
$ cd ~
|
||||||
$ # check http://nginx.org/en/download.html for the latest version
|
$ # check http://nginx.org/en/download.html for the latest version
|
||||||
$ wget http://nginx.org/download/nginx-1.4.1.tar.gz
|
$ wget http://nginx.org/download/nginx-1.4.6.tar.gz
|
||||||
$ tar -xvzf nginx-1.4.1.tar.gz
|
$ tar -xvzf nginx-1.4.6.tar.gz
|
||||||
$ cd nginx-1.4.1/
|
$ cd nginx-1.4.6/
|
||||||
$ ./configure --add-module=$HOME/ngx_pagespeed-release-1.6.29.5-beta
|
$ ./configure --add-module=$HOME/ngx_pagespeed-1.7.30.4-beta
|
||||||
$ make
|
$ make
|
||||||
$ sudo make install
|
$ sudo make install
|
||||||
```
|
```
|
||||||
@@ -72,9 +73,7 @@ In your `nginx.conf`, add to the main or server block:
|
|||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
pagespeed on;
|
pagespeed on;
|
||||||
|
pagespeed FileCachePath /var/ngx_pagespeed_cache; # Use tmpfs for best results.
|
||||||
# needs to exist and be writable by nginx
|
|
||||||
pagespeed FileCachePath /var/ngx_pagespeed_cache;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
In every server block where pagespeed is enabled add:
|
In every server block where pagespeed is enabled add:
|
||||||
@@ -86,6 +85,7 @@ location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { add_header "" ""
|
|||||||
location ~ "^/ngx_pagespeed_static/" { }
|
location ~ "^/ngx_pagespeed_static/" { }
|
||||||
location ~ "^/ngx_pagespeed_beacon$" { }
|
location ~ "^/ngx_pagespeed_beacon$" { }
|
||||||
location /ngx_pagespeed_statistics { allow 127.0.0.1; deny all; }
|
location /ngx_pagespeed_statistics { allow 127.0.0.1; deny all; }
|
||||||
|
location /ngx_pagespeed_global_statistics { allow 127.0.0.1; deny all; }
|
||||||
location /ngx_pagespeed_message { 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; }
|
location /pagespeed_console { allow 127.0.0.1; deny all; }
|
||||||
```
|
```
|
||||||
@@ -95,7 +95,7 @@ To confirm that the module is loaded, fetch a page and check that you see the
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ curl -I 'http://localhost:8050/some_page/' | grep X-Page-Speed
|
$ curl -I 'http://localhost:8050/some_page/' | grep X-Page-Speed
|
||||||
X-Page-Speed: 1.6.29.5-...
|
X-Page-Speed: 1.7.30.4-...
|
||||||
```
|
```
|
||||||
|
|
||||||
Looking at the source of a few pages you should see various changes, such as
|
Looking at the source of a few pages you should see various changes, such as
|
||||||
@@ -115,3 +115,20 @@ the progress of the project:
|
|||||||
list](https://groups.google.com/forum/#!forum/ngx-pagespeed-discuss)
|
list](https://groups.google.com/forum/#!forum/ngx-pagespeed-discuss)
|
||||||
- [ngx-pagespeed-announce mailing
|
- [ngx-pagespeed-announce mailing
|
||||||
list](https://groups.google.com/forum/#!forum/ngx-pagespeed-announce)
|
list](https://groups.google.com/forum/#!forum/ngx-pagespeed-announce)
|
||||||
|
|
||||||
|
Note: The
|
||||||
|
[canonicalize_javascript_libraries](https://developers.google.com/speed/pagespeed/module/filter-canonicalize-js)
|
||||||
|
depends on `pagespeed_libraries.conf` which is distributed in Apache's format.
|
||||||
|
To convert it to the Nginx format, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ scripts/pagespeed_libraries_generator.sh > ~/pagespeed_libraries.conf
|
||||||
|
$ sudo mv ~/pagespeed_libraries.conf /etc/nginx/
|
||||||
|
```
|
||||||
|
|
||||||
|
And then include it in your Nginx configuration by reference:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
include pagespeed_libraries.conf;
|
||||||
|
pagespeed EnableFilters canonicalize_javascript_libraries;
|
||||||
|
```
|
||||||
|
|||||||
@@ -27,8 +27,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.5.tar.gz"
|
echo " $ wget https://dl.google.com/dl/page-speed/psol/1.7.30.4.tar.gz"
|
||||||
echo " $ tar -xzvf 1.6.29.5.tar.gz # expands to psol/"
|
echo " $ tar -xzvf 1.7.30.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"
|
||||||
@@ -83,9 +83,31 @@ else
|
|||||||
buildtype=Release
|
buildtype=Release
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Building with HTTPS fetching enabled pulls in a version of OpenSSL that causes
|
# The compiler needs to know that __sync_add_and_fetch_4 is ok,
|
||||||
# linker errors, so disable it here.
|
# and this requires an instruction that didn't exist on i586 or i386.
|
||||||
CFLAGS="$CFLAGS -DSERF_HTTPS_FETCHING=0"
|
if [ "$uname_arch" = "i686" ]; then
|
||||||
|
FLAG_MARCH='-march=i686'
|
||||||
|
fi
|
||||||
|
|
||||||
|
CFLAGS="$CFLAGS $FLAG_MARCH"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
pagespeed_include="\
|
pagespeed_include="\
|
||||||
$mod_pagespeed_dir \
|
$mod_pagespeed_dir \
|
||||||
@@ -95,6 +117,7 @@ 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 \
|
||||||
@@ -103,17 +126,10 @@ ngx_feature_path="$pagespeed_include"
|
|||||||
|
|
||||||
if $build_from_source ; then
|
if $build_from_source ; then
|
||||||
psol_library_binaries="\
|
psol_library_binaries="\
|
||||||
$mod_pagespeed_dir/net/instaweb/automatic/pagespeed_automatic.a \
|
$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
|
else
|
||||||
psol_library_dir="$ngx_addon_dir/psol/lib/$buildtype/$os_name/$arch_name"
|
psol_library_dir="$ngx_addon_dir/psol/lib/$buildtype/$os_name/$arch_name"
|
||||||
psol_library_binaries="\
|
psol_library_binaries="$psol_library_dir/pagespeed_automatic.a"
|
||||||
$psol_library_dir/pagespeed_automatic.a \
|
|
||||||
$psol_library_dir/libserf.a \
|
|
||||||
$psol_library_dir/libaprutil.a \
|
|
||||||
$psol_library_dir/libapr.a"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pagespeed_libs="-lstdc++ $psol_library_binaries -lrt -pthread -lm"
|
pagespeed_libs="-lstdc++ $psol_library_binaries -lrt -pthread -lm"
|
||||||
@@ -150,13 +166,10 @@ if [ $ngx_found = yes ]; then
|
|||||||
$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"
|
|
||||||
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 \
|
||||||
@@ -165,18 +178,11 @@ if [ $ngx_found = yes ]; then
|
|||||||
$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 \
|
|
||||||
$ps_src/pthread_shared_mem.cc \
|
|
||||||
$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 \
|
|
||||||
$mod_pagespeed_dir/net/instaweb/system/add_headers_fetcher.cc \
|
|
||||||
$mod_pagespeed_dir/net/instaweb/system/loopback_route_fetcher.cc \
|
|
||||||
$mod_pagespeed_dir/net/instaweb/system/serf_url_async_fetcher.cc"
|
|
||||||
# Make pagespeed run immediately before gzip.
|
# Make pagespeed run immediately before gzip.
|
||||||
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_GZIP_FILTER_MODULE/$HTTP_GZIP_FILTER_MODULE $ngx_addon_name/")
|
||||||
@@ -185,9 +191,11 @@ if [ $ngx_found = yes ]; then
|
|||||||
sed "s/$HTTP_GZIP_FILTER_MODULE/ngx_pagespeed_etag_filter $HTTP_GZIP_FILTER_MODULE/")
|
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
|
END
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
Executable
+22
@@ -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://modpagespeed.googlecode.com/svn/trunk/src/"
|
||||||
|
URL+="net/instaweb/genfiles/conf/pagespeed_libraries.conf"
|
||||||
|
curl -s "$URL" \
|
||||||
|
| grep ModPagespeedLibrary \
|
||||||
|
| while read library size hash url ; do
|
||||||
|
echo " pagespeed Library $size $hash $url;"
|
||||||
|
done
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -98,8 +98,6 @@ 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;
|
log = log_in;
|
||||||
logging::SetLogMessageHandler(&LogMessageHandler);
|
logging::SetLogMessageHandler(&LogMessageHandler);
|
||||||
|
|||||||
+34
-58
@@ -30,16 +30,18 @@ namespace net_instaweb {
|
|||||||
|
|
||||||
NgxBaseFetch::NgxBaseFetch(ngx_http_request_t* r, int pipe_fd,
|
NgxBaseFetch::NgxBaseFetch(ngx_http_request_t* r, int pipe_fd,
|
||||||
NgxServerContext* server_context,
|
NgxServerContext* server_context,
|
||||||
const RequestContextPtr& request_ctx)
|
const RequestContextPtr& request_ctx,
|
||||||
|
PreserveCachingHeaders preserve_caching_headers)
|
||||||
: 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),
|
pipe_fd_(pipe_fd),
|
||||||
references_(2) {
|
references_(2),
|
||||||
|
handle_error_(true),
|
||||||
|
preserve_caching_headers_(preserve_caching_headers) {
|
||||||
if (pthread_mutex_init(&mutex_, NULL)) CHECK(0);
|
if (pthread_mutex_init(&mutex_, NULL)) CHECK(0);
|
||||||
PopulateRequestHeaders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NgxBaseFetch::~NgxBaseFetch() {
|
NgxBaseFetch::~NgxBaseFetch() {
|
||||||
@@ -54,45 +56,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 +64,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,31 +86,33 @@ 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() {
|
||||||
@@ -163,9 +134,14 @@ void NgxBaseFetch::RequestCollection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 (status_ok || handle_error_) {
|
||||||
|
// 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(); // Headers available.
|
||||||
|
|||||||
+8
-13
@@ -57,15 +57,10 @@ class NgxBaseFetch : public AsyncFetch {
|
|||||||
public:
|
public:
|
||||||
NgxBaseFetch(ngx_http_request_t* r, int pipe_fd,
|
NgxBaseFetch(ngx_http_request_t* r, int pipe_fd,
|
||||||
NgxServerContext* server_context,
|
NgxServerContext* server_context,
|
||||||
const RequestContextPtr& request_ctx);
|
const RequestContextPtr& request_ctx,
|
||||||
|
PreserveCachingHeaders preserve_caching_headers);
|
||||||
virtual ~NgxBaseFetch();
|
virtual ~NgxBaseFetch();
|
||||||
|
|
||||||
// Copies the request headers out of request_->headers_in->headers.
|
|
||||||
void PopulateRequestHeaders();
|
|
||||||
|
|
||||||
// Copies the response headers out of request_->headers_out->headers.
|
|
||||||
void PopulateResponseHeaders();
|
|
||||||
|
|
||||||
// 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
|
||||||
// data only if Done() has been called. Indicates the end of output by
|
// data only if Done() has been called. Indicates the end of output by
|
||||||
@@ -84,6 +79,7 @@ class NgxBaseFetch : public AsyncFetch {
|
|||||||
|
|
||||||
// Called by nginx when it's done with us.
|
// Called by nginx when it's done with us.
|
||||||
void Release();
|
void Release();
|
||||||
|
void set_handle_error(bool x) { handle_error_ = x; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool HandleWrite(const StringPiece& sp, MessageHandler* handler);
|
virtual bool HandleWrite(const StringPiece& sp, MessageHandler* handler);
|
||||||
@@ -91,18 +87,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();
|
||||||
|
|
||||||
// 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);
|
||||||
@@ -124,6 +117,8 @@ class NgxBaseFetch : public AsyncFetch {
|
|||||||
// decremented once when Done() is called and once when Release() is called.
|
// decremented once when Done() is called and once when Release() is called.
|
||||||
int references_;
|
int references_;
|
||||||
pthread_mutex_t mutex_;
|
pthread_mutex_t mutex_;
|
||||||
|
bool handle_error_;
|
||||||
|
PreserveCachingHeaders preserve_caching_headers_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(NgxBaseFetch);
|
DISALLOW_COPY_AND_ASSIGN(NgxBaseFetch);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 */);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
+87
-53
@@ -24,6 +24,10 @@
|
|||||||
// - The read handler parses the response. Add the response to the buffer at
|
// - The read handler parses the response. Add the response to the buffer at
|
||||||
// last.
|
// last.
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <nginx.h>
|
||||||
|
}
|
||||||
|
|
||||||
#include "ngx_fetch.h"
|
#include "ngx_fetch.h"
|
||||||
#include "net/instaweb/util/public/basictypes.h"
|
#include "net/instaweb/util/public/basictypes.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
@@ -66,7 +70,8 @@ namespace net_instaweb {
|
|||||||
fetch_start_ms_(0),
|
fetch_start_ms_(0),
|
||||||
fetch_end_ms_(0),
|
fetch_end_ms_(0),
|
||||||
done_(false),
|
done_(false),
|
||||||
content_length_(0) {
|
content_length_(-1),
|
||||||
|
content_length_known_(false) {
|
||||||
ngx_memzero(&url_, sizeof(url_));
|
ngx_memzero(&url_, sizeof(url_));
|
||||||
log_ = log;
|
log_ = log;
|
||||||
pool_ = NULL;
|
pool_ = NULL;
|
||||||
@@ -138,19 +143,26 @@ namespace net_instaweb {
|
|||||||
// The host is either a domain name or an IP address. First check
|
// The host is either a domain name or an IP address. First check
|
||||||
// if it's a valid IP address and only if that fails fall back to
|
// if it's a valid IP address and only if that fails fall back to
|
||||||
// using the DNS resolver.
|
// using the DNS resolver.
|
||||||
GoogleString s_ipaddress(reinterpret_cast<char*>(url_.host.data),
|
|
||||||
url_.host.len);
|
// Maybe we have a Proxy.
|
||||||
|
ngx_url_t* tmp_url = &url_;
|
||||||
|
if (0 != fetcher_->proxy_.url.len) {
|
||||||
|
tmp_url = &fetcher_->proxy_;
|
||||||
|
}
|
||||||
|
|
||||||
|
GoogleString s_ipaddress(reinterpret_cast<char*>(tmp_url->host.data),
|
||||||
|
tmp_url->host.len);
|
||||||
ngx_memzero(&sin_, sizeof(sin_));
|
ngx_memzero(&sin_, sizeof(sin_));
|
||||||
sin_.sin_family = AF_INET;
|
sin_.sin_family = AF_INET;
|
||||||
sin_.sin_port = htons(url_.port);
|
sin_.sin_port = htons(tmp_url->port);
|
||||||
sin_.sin_addr.s_addr = inet_addr(s_ipaddress.c_str());
|
sin_.sin_addr.s_addr = inet_addr(s_ipaddress.c_str());
|
||||||
|
|
||||||
if (sin_.sin_addr.s_addr == INADDR_NONE) {
|
if (sin_.sin_addr.s_addr == INADDR_NONE) {
|
||||||
// inet_addr returned INADDR_NONE, which means the hostname
|
// inet_addr returned INADDR_NONE, which means the hostname
|
||||||
// isn't a valid IP address. Check DNS.
|
// isn't a valid IP address. Check DNS.
|
||||||
ngx_resolver_ctx_t temp;
|
ngx_resolver_ctx_t temp;
|
||||||
temp.name.data = url_.host.data;
|
temp.name.data = tmp_url->host.data;
|
||||||
temp.name.len = url_.host.len;
|
temp.name.len = tmp_url->host.len;
|
||||||
resolver_ctx_ = ngx_resolve_start(fetcher_->resolver_, &temp);
|
resolver_ctx_ = ngx_resolve_start(fetcher_->resolver_, &temp);
|
||||||
if (resolver_ctx_ == NULL || resolver_ctx_ == NGX_NO_RESOLVER) {
|
if (resolver_ctx_ == NULL || resolver_ctx_ == NGX_NO_RESOLVER) {
|
||||||
// TODO(oschaaf): this spams the log, but is useful in the fetcher's
|
// TODO(oschaaf): this spams the log, but is useful in the fetcher's
|
||||||
@@ -162,9 +174,13 @@ namespace net_instaweb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resolver_ctx_->data = this;
|
resolver_ctx_->data = this;
|
||||||
resolver_ctx_->name.data = url_.host.data;
|
resolver_ctx_->name.data = tmp_url->host.data;
|
||||||
resolver_ctx_->name.len = url_.host.len;
|
resolver_ctx_->name.len = tmp_url->host.len;
|
||||||
|
|
||||||
|
#if (nginx_version < 1005008)
|
||||||
resolver_ctx_->type = NGX_RESOLVE_A;
|
resolver_ctx_->type = NGX_RESOLVE_A;
|
||||||
|
#endif
|
||||||
|
|
||||||
resolver_ctx_->handler = NgxFetchResolveDone;
|
resolver_ctx_->handler = NgxFetchResolveDone;
|
||||||
resolver_ctx_->timeout = fetcher_->resolver_timeout_;
|
resolver_ctx_->timeout = fetcher_->resolver_timeout_;
|
||||||
|
|
||||||
@@ -255,39 +271,14 @@ namespace net_instaweb {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
str_url_.copy(reinterpret_cast<char*>(url_.url.data), str_url_.length(), 0);
|
str_url_.copy(reinterpret_cast<char*>(url_.url.data), str_url_.length(), 0);
|
||||||
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;
|
return NgxUrlAsyncFetcher::ParseUrl(&url_, pool_);
|
||||||
url_.url.len -= scheme_offset;
|
|
||||||
url_.default_port = port;
|
|
||||||
// TODO(oschaaf): no_resolve was set to 0, which is why url_.port
|
|
||||||
// would always be '0' after parsing it. 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue a request after the resolver is done
|
// Issue a request after the resolver is done
|
||||||
void NgxFetch::NgxFetchResolveDone(ngx_resolver_ctx_t* resolver_ctx) {
|
void NgxFetch::NgxFetchResolveDone(ngx_resolver_ctx_t* resolver_ctx) {
|
||||||
NgxFetch* fetch = static_cast<NgxFetch*>(resolver_ctx->data);
|
NgxFetch* fetch = static_cast<NgxFetch*>(resolver_ctx->data);
|
||||||
|
NgxUrlAsyncFetcher* fetcher = fetch->fetcher_;
|
||||||
if (resolver_ctx->state != NGX_OK) {
|
if (resolver_ctx->state != NGX_OK) {
|
||||||
if (fetch->timeout_event() != NULL && fetch->timeout_event()->timer_set) {
|
if (fetch->timeout_event() != NULL && fetch->timeout_event()->timer_set) {
|
||||||
ngx_del_timer(fetch->timeout_event());
|
ngx_del_timer(fetch->timeout_event());
|
||||||
@@ -301,9 +292,25 @@ namespace net_instaweb {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ngx_memzero(&fetch->sin_, sizeof(fetch->sin_));
|
ngx_memzero(&fetch->sin_, sizeof(fetch->sin_));
|
||||||
|
|
||||||
|
#if (nginx_version < 1005008)
|
||||||
|
fetch->sin_.sin_addr.s_addr = resolver_ctx->addrs[0];
|
||||||
|
#else
|
||||||
|
|
||||||
|
struct sockaddr_in *sin;
|
||||||
|
sin = reinterpret_cast<struct sockaddr_in *>(
|
||||||
|
resolver_ctx->addrs[0].sockaddr);
|
||||||
|
fetch->sin_.sin_family = sin->sin_family;
|
||||||
|
fetch->sin_.sin_addr.s_addr = sin->sin_addr.s_addr;
|
||||||
|
#endif
|
||||||
|
|
||||||
fetch->sin_.sin_family = AF_INET;
|
fetch->sin_.sin_family = AF_INET;
|
||||||
fetch->sin_.sin_port = htons(fetch->url_.port);
|
fetch->sin_.sin_port = htons(fetch->url_.port);
|
||||||
fetch->sin_.sin_addr.s_addr = resolver_ctx->addrs[0];
|
|
||||||
|
// Maybe we have Proxy
|
||||||
|
if (0 != fetcher->proxy_.url.len) {
|
||||||
|
fetch->sin_.sin_port = htons(fetcher->proxy_.port);
|
||||||
|
}
|
||||||
|
|
||||||
char* ip_address = inet_ntoa(fetch->sin_.sin_addr);
|
char* ip_address = inet_ntoa(fetch->sin_.sin_addr);
|
||||||
|
|
||||||
@@ -335,7 +342,13 @@ namespace net_instaweb {
|
|||||||
bool have_host = false;
|
bool have_host = false;
|
||||||
GoogleString port;
|
GoogleString port;
|
||||||
|
|
||||||
size = sizeof("GET ") - 1 + url_.uri.len + sizeof(" HTTP/1.0\r\n") - 1;
|
const char* method = request_headers->method_string();
|
||||||
|
size_t method_len = strlen(method);
|
||||||
|
|
||||||
|
size = (method_len +
|
||||||
|
1 /* for the space */ +
|
||||||
|
url_.uri.len +
|
||||||
|
sizeof(" HTTP/1.0\r\n") - 1);
|
||||||
|
|
||||||
for (int i = 0; i < request_headers->NumAttributes(); i++) {
|
for (int i = 0; i < request_headers->NumAttributes(); i++) {
|
||||||
// if no explicit host header is given in the request headers,
|
// if no explicit host header is given in the request headers,
|
||||||
@@ -363,7 +376,8 @@ namespace net_instaweb {
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_->last = ngx_cpymem(out_->last, "GET ", 4);
|
out_->last = ngx_cpymem(out_->last, method, method_len);
|
||||||
|
out_->last = ngx_cpymem(out_->last, " ", 1);
|
||||||
out_->last = ngx_cpymem(out_->last, url_.uri.data, url_.uri.len);
|
out_->last = ngx_cpymem(out_->last, url_.uri.data, url_.uri.len);
|
||||||
out_->last = ngx_cpymem(out_->last, " HTTP/1.0\r\n", 11);
|
out_->last = ngx_cpymem(out_->last, " HTTP/1.0\r\n", 11);
|
||||||
|
|
||||||
@@ -413,12 +427,16 @@ namespace net_instaweb {
|
|||||||
pc.rcvbuf = -1;
|
pc.rcvbuf = -1;
|
||||||
|
|
||||||
int rc = ngx_event_connect_peer(&pc);
|
int rc = ngx_event_connect_peer(&pc);
|
||||||
|
if (rc == NGX_ERROR || rc == NGX_DECLINED || rc == NGX_BUSY) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
connection_ = pc.connection;
|
connection_ = pc.connection;
|
||||||
connection_->write->handler = NgxFetchWrite;
|
connection_->write->handler = NgxFetchWrite;
|
||||||
connection_->read->handler = NgxFetchRead;
|
connection_->read->handler = NgxFetchRead;
|
||||||
connection_->data = this;
|
connection_->data = this;
|
||||||
|
|
||||||
// TODO(junmin): set connect timeout when rc == NGX_AGAIN
|
// Timer set in Init() is still in effect.
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,10 +452,10 @@ namespace net_instaweb {
|
|||||||
if (n >= 0) {
|
if (n >= 0) {
|
||||||
out->pos += n;
|
out->pos += n;
|
||||||
} else if (n == NGX_AGAIN) {
|
} else if (n == NGX_AGAIN) {
|
||||||
// TODO(junmin): set write event timeout
|
|
||||||
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
|
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
|
||||||
fetch->CallbackDone(false);
|
fetch->CallbackDone(false);
|
||||||
}
|
}
|
||||||
|
// Timer set in Init() is still in effect.
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
c->error = 1;
|
c->error = 1;
|
||||||
@@ -467,9 +485,16 @@ namespace net_instaweb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
// connection is closed prematurely by remote server,
|
// If the content length was not known, we assume that we have read
|
||||||
// or the content-length was 0
|
// all if we at least parsed the headers.
|
||||||
fetch->CallbackDone(fetch->content_length_ == 0);
|
// If we do know the content length, having a mismatch on the bytes read
|
||||||
|
// will be interpreted as an error.
|
||||||
|
if (fetch->content_length_known_) {
|
||||||
|
fetch->CallbackDone(fetch->content_length_ == fetch->bytes_received_);
|
||||||
|
} else {
|
||||||
|
fetch->CallbackDone(fetch->parser_.headers_complete());
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if (n > 0) {
|
} else if (n > 0) {
|
||||||
fetch->in_->pos = fetch->in_->start;
|
fetch->in_->pos = fetch->in_->start;
|
||||||
@@ -499,7 +524,7 @@ namespace net_instaweb {
|
|||||||
fetch->CallbackDone(false);
|
fetch->CallbackDone(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(junmin): set read event timeout
|
// Timer set in Init() is still in effect.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the status line: "HTTP/1.1 200 OK\r\n"
|
// Parse the status line: "HTTP/1.1 200 OK\r\n"
|
||||||
@@ -536,13 +561,21 @@ namespace net_instaweb {
|
|||||||
if (n > size) {
|
if (n > size) {
|
||||||
return false;
|
return false;
|
||||||
} else if (fetch->parser_.headers_complete()) {
|
} else if (fetch->parser_.headers_complete()) {
|
||||||
int64 content_length = -1;
|
if (fetch->async_fetch_->response_headers()->FindContentLength(
|
||||||
fetch->async_fetch_->response_headers()->FindContentLength(
|
&fetch->content_length_)) {
|
||||||
&content_length);
|
if (fetch->content_length_ < 0) {
|
||||||
fetch->content_length_ = content_length;
|
fetch->message_handler_->Message(
|
||||||
if (fetch->fetcher_->track_original_content_length()) {
|
kError, "Negative content-length in response header");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
fetch->content_length_known_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fetch->fetcher_->track_original_content_length()
|
||||||
|
&& fetch->content_length_known_) {
|
||||||
fetch->async_fetch_->response_headers()->SetOriginalContentLength(
|
fetch->async_fetch_->response_headers()->SetOriginalContentLength(
|
||||||
content_length);
|
fetch->content_length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch->in_->pos += n;
|
fetch->in_->pos += n;
|
||||||
@@ -561,11 +594,12 @@ namespace net_instaweb {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch->bytes_received_add(static_cast<int64>(size));
|
fetch->bytes_received_add(size);
|
||||||
|
|
||||||
if (fetch->async_fetch_->Write(StringPiece(data, size),
|
if (fetch->async_fetch_->Write(StringPiece(data, size),
|
||||||
fetch->message_handler())) {
|
fetch->message_handler())) {
|
||||||
fetch->content_length_ -= size;
|
if (fetch->content_length_known_ &&
|
||||||
if (fetch->content_length_ <= 0) {
|
fetch->bytes_received_ == fetch->content_length_) {
|
||||||
fetch->done_ = true;
|
fetch->done_ = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+102
-105
@@ -16,18 +16,16 @@
|
|||||||
|
|
||||||
// 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
|
// The fetch is started by the main thread. It will fetch the remote resource
|
||||||
// from the specific url asynchronously.
|
// 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"
|
||||||
@@ -40,112 +38,111 @@ extern "C" {
|
|||||||
#include "net/instaweb/http/public/response_headers_parser.h"
|
#include "net/instaweb/http/public/response_headers_parser.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 NgxFetch : public PoolElement<NgxFetch> {
|
||||||
void bytes_received_add(int64 x);
|
public:
|
||||||
int64 fetch_start_ms();
|
NgxFetch(const GoogleString& url,
|
||||||
void set_fetch_start_ms(int64 start_ms);
|
AsyncFetch* async_fetch,
|
||||||
int64 fetch_end_ms();
|
MessageHandler* message_handler,
|
||||||
void set_fetch_end_ms(int64 end_ms);
|
ngx_msec_t timeout_ms,
|
||||||
MessageHandler* message_handler();
|
ngx_log_t* log);
|
||||||
int get_major_version() {
|
~NgxFetch();
|
||||||
return static_cast<int>(status_->http_version / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_minor_version() {
|
// Start the fetch.
|
||||||
return static_cast<int>(status_->http_version % 1000);
|
bool Start(NgxUrlAsyncFetcher* fetcher);
|
||||||
}
|
// Show the completed url, for logging purposes.
|
||||||
|
const char* str_url();
|
||||||
|
// This fetch task is done. Call Done() on the async_fetch. It will copy the
|
||||||
|
// buffer to cache.
|
||||||
|
void CallbackDone(bool success);
|
||||||
|
|
||||||
int get_status_code() {
|
// Show the bytes received.
|
||||||
return static_cast<int>(status_->code);
|
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();
|
||||||
|
|
||||||
ngx_event_t* timeout_event() {
|
int get_major_version() {
|
||||||
return timeout_event_;
|
return static_cast<int>(status_->http_version / 1000);
|
||||||
};
|
}
|
||||||
void set_timeout_event(ngx_event_t* x) {
|
int get_minor_version() {
|
||||||
timeout_event_ = x;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
response_handler_pt response_handler;
|
response_handler_pt response_handler;
|
||||||
// Do the initialized work and start the resolver work.
|
// Do the initialized work and start the resolver work.
|
||||||
bool Init();
|
bool Init();
|
||||||
bool ParseUrl();
|
bool ParseUrl();
|
||||||
// Prepare the request and write it to remote server.
|
// Prepare the request and write it to remote server.
|
||||||
int InitRequest();
|
int InitRequest();
|
||||||
// Create the connection with remote server.
|
// Create the connection with remote server.
|
||||||
int Connect();
|
int Connect();
|
||||||
void set_response_handler(response_handler_pt handler) {
|
void set_response_handler(response_handler_pt handler) {
|
||||||
response_handler = handler;
|
response_handler = handler;
|
||||||
}
|
}
|
||||||
// Only the Static functions could be used in callbacks.
|
// Only the Static functions could be used in callbacks.
|
||||||
static void NgxFetchResolveDone(ngx_resolver_ctx_t* ctx);
|
static void NgxFetchResolveDone(ngx_resolver_ctx_t* ctx);
|
||||||
|
// Write the request.
|
||||||
|
static void NgxFetchWrite(ngx_event_t* wev);
|
||||||
|
// Wait for the response.
|
||||||
|
static void NgxFetchRead(ngx_event_t* rev);
|
||||||
|
// Read and parse the first status line.
|
||||||
|
static bool NgxFetchHandleStatusLine(ngx_connection_t* c);
|
||||||
|
// 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.
|
||||||
|
static void NgxFetchTimeout(ngx_event_t* tev);
|
||||||
|
|
||||||
// Write the request
|
// Add the pagespeed User-Agent.
|
||||||
static void NgxFetchWrite(ngx_event_t* wev);
|
void FixUserAgent();
|
||||||
|
void FixHost();
|
||||||
|
|
||||||
// Wait for the response
|
const GoogleString str_url_;
|
||||||
static void NgxFetchRead(ngx_event_t* rev);
|
ngx_url_t url_;
|
||||||
// Read and parse the first status line
|
NgxUrlAsyncFetcher* fetcher_;
|
||||||
static bool NgxFetchHandleStatusLine(ngx_connection_t* c);
|
AsyncFetch* async_fetch_;
|
||||||
// Read and parse the HTTP headers
|
ResponseHeadersParser parser_;
|
||||||
static bool NgxFetchHandleHeader(ngx_connection_t* c);
|
MessageHandler* message_handler_;
|
||||||
// Read the response body
|
int64 bytes_received_;
|
||||||
static bool NgxFetchHandleBody(ngx_connection_t* c);
|
int64 fetch_start_ms_;
|
||||||
|
int64 fetch_end_ms_;
|
||||||
|
int64 timeout_ms_;
|
||||||
|
bool done_;
|
||||||
|
int64 content_length_;
|
||||||
|
bool content_length_known_;
|
||||||
|
|
||||||
// Cancel the fetch when it's timeout
|
struct sockaddr_in sin_;
|
||||||
static void NgxFetchTimeout(ngx_event_t* tev);
|
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_;
|
||||||
|
ngx_connection_t* connection_;
|
||||||
|
ngx_resolver_ctx_t* resolver_ctx_;
|
||||||
|
|
||||||
// Add the pagespeed User-Agent
|
DISALLOW_COPY_AND_ASSIGN(NgxFetch);
|
||||||
void FixUserAgent();
|
};
|
||||||
void FixHost();
|
|
||||||
|
|
||||||
const GoogleString str_url_;
|
|
||||||
ngx_url_t url_;
|
|
||||||
NgxUrlAsyncFetcher* fetcher_;
|
|
||||||
AsyncFetch* async_fetch_;
|
|
||||||
ResponseHeadersParser parser_;
|
|
||||||
MessageHandler* message_handler_;
|
|
||||||
size_t bytes_received_;
|
|
||||||
int64 fetch_start_ms_;
|
|
||||||
int64 fetch_end_ms_;
|
|
||||||
int64 timeout_ms_;
|
|
||||||
bool done_;
|
|
||||||
int64 content_length_;
|
|
||||||
|
|
||||||
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_;
|
|
||||||
ngx_connection_t* 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_
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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/abstract_mutex.h"
|
||||||
#include "net/instaweb/util/public/debug.h"
|
#include "net/instaweb/util/public/debug.h"
|
||||||
#include "net/instaweb/util/public/shared_circular_buffer.h"
|
#include "net/instaweb/util/public/shared_circular_buffer.h"
|
||||||
#include "net/instaweb/util/public/string_util.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/posix_timer.h"
|
||||||
|
#include "pagespeed/kernel/base/time_util.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -118,10 +118,9 @@ void NgxMessageHandler::MessageVImpl(MessageType type, const char* msg,
|
|||||||
// Prepend time and severity to message.
|
// Prepend time and severity to message.
|
||||||
// Format is [time] [severity] [pid] message.
|
// Format is [time] [severity] [pid] message.
|
||||||
GoogleString message;
|
GoogleString message;
|
||||||
char time_buffer[APR_CTIME_LEN + 1];
|
GoogleString time;
|
||||||
const char* time = time_buffer;
|
PosixTimer timer;
|
||||||
apr_status_t status = apr_ctime(time_buffer, apr_time_now());
|
if (!ConvertTimeToString(timer.NowMs(), &time)) {
|
||||||
if (status != APR_SUCCESS) {
|
|
||||||
time = "?";
|
time = "?";
|
||||||
}
|
}
|
||||||
StrAppend(&message, "[", time, "] ",
|
StrAppend(&message, "[", time, "] ",
|
||||||
@@ -149,14 +148,4 @@ void NgxMessageHandler::FileMessageVImpl(MessageType type, const char* file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class NgxMessageHandler : public GoogleMessageHandler {
|
|||||||
// Messages logged before that will be passed on to handler_;
|
// Messages logged before that will be passed on to handler_;
|
||||||
void set_buffer(SharedCircularBuffer* buff);
|
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) {
|
void SetPidString(const int64 pid) {
|
||||||
pid_string_ = StrCat("[", Integer64ToString(pid), "]");
|
pid_string_ = StrCat("[", Integer64ToString(pid), "]");
|
||||||
@@ -69,7 +70,6 @@ class NgxMessageHandler : public GoogleMessageHandler {
|
|||||||
|
|
||||||
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_;
|
scoped_ptr<AbstractMutex> mutex_;
|
||||||
GoogleString pid_string_;
|
GoogleString pid_string_;
|
||||||
|
|||||||
+1309
-1194
File diff suppressed because it is too large
Load Diff
+46
-16
@@ -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,55 @@ 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_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 in_place;
|
||||||
|
|
||||||
bool write_pending;
|
bool write_pending;
|
||||||
net_instaweb::GzipInflater* inflater_;
|
bool fetch_done;
|
||||||
|
|
||||||
|
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;
|
||||||
} ps_request_ctx_t;
|
} ps_request_ctx_t;
|
||||||
|
|
||||||
} // namespace ngx_psol
|
|
||||||
|
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 net_instaweb
|
||||||
|
|
||||||
#endif // NGX_PAGESPEED_H_
|
#endif // NGX_PAGESPEED_H_
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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_
|
|
||||||
@@ -24,9 +24,7 @@
|
|||||||
#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/content_type.h"
|
||||||
#include "net/instaweb/http/public/rate_controller.h"
|
#include "net/instaweb/http/public/rate_controller.h"
|
||||||
@@ -36,6 +34,7 @@
|
|||||||
#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/rewriter/public/static_asset_manager.h"
|
||||||
|
#include "net/instaweb/system/public/in_place_resource_recorder.h"
|
||||||
#include "net/instaweb/system/public/serf_url_async_fetcher.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_caches.h"
|
||||||
#include "net/instaweb/system/public/system_rewrite_options.h"
|
#include "net/instaweb/system/public/system_rewrite_options.h"
|
||||||
@@ -51,6 +50,7 @@
|
|||||||
#include "net/instaweb/util/public/string.h"
|
#include "net/instaweb/util/public/string.h"
|
||||||
#include "net/instaweb/util/public/string_util.h"
|
#include "net/instaweb/util/public/string_util.h"
|
||||||
#include "net/instaweb/util/public/thread_system.h"
|
#include "net/instaweb/util/public/thread_system.h"
|
||||||
|
#include "pagespeed/kernel/thread/pthread_shared_mem.h"
|
||||||
|
|
||||||
namespace net_instaweb {
|
namespace net_instaweb {
|
||||||
|
|
||||||
@@ -66,33 +66,26 @@ class Writer;
|
|||||||
const char NgxRewriteDriverFactory::kStaticAssetPrefix[] =
|
const char NgxRewriteDriverFactory::kStaticAssetPrefix[] =
|
||||||
"/ngx_pagespeed_static/";
|
"/ngx_pagespeed_static/";
|
||||||
|
|
||||||
namespace {
|
class SharedCircularBuffer;
|
||||||
|
|
||||||
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),
|
use_per_vhost_statistics_(false),
|
||||||
is_root_process_(true),
|
|
||||||
ngx_message_handler_(new NgxMessageHandler(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(thread_system()->NewMutex())),
|
||||||
install_crash_handler_(false),
|
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),
|
||||||
|
ngx_shared_circular_buffer_(NULL),
|
||||||
|
hostname_(hostname.as_string()),
|
||||||
|
port_(port) {
|
||||||
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,34 @@ 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_,
|
thread_system(),
|
||||||
thread_system(),
|
message_handler());
|
||||||
message_handler());
|
ngx_url_async_fetchers_.push_back(fetcher);
|
||||||
fetcher = ngx_url_async_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,44 +145,25 @@ 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(
|
void NgxRewriteDriverFactory::InitStaticAssetManager(
|
||||||
StaticAssetManager* static_asset_manager) {
|
StaticAssetManager* static_asset_manager) {
|
||||||
static_asset_manager->set_library_url_prefix(kStaticAssetPrefix);
|
static_asset_manager->set_library_url_prefix(kStaticAssetPrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NgxRewriteDriverFactory::PrintMemCacheStats(GoogleString* out) {
|
bool NgxRewriteDriverFactory::InitNgxUrlAsyncFetchers() {
|
||||||
// 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;
|
log_ = ngx_cycle->log;
|
||||||
return ngx_url_async_fetcher_->Init();
|
for (size_t i = 0; i < ngx_url_async_fetchers_.size(); ++i) {
|
||||||
|
if (!ngx_url_async_fetchers_[i]->Init()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NgxRewriteDriverFactory::CheckResolver() {
|
bool NgxRewriteDriverFactory::CheckResolver() {
|
||||||
@@ -250,52 +173,39 @@ 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::ShutDownMessageHandlers() {
|
||||||
StopCacheActivity();
|
|
||||||
if (!is_root_process_) {
|
|
||||||
Variable* child_shutdown_count = statistics()->GetVariable(kShutdownCount);
|
|
||||||
child_shutdown_count->Add(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
RewriteDriverFactory::ShutDown();
|
|
||||||
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 +215,33 @@ void NgxRewriteDriverFactory::StartThreads() {
|
|||||||
threads_started_ = true;
|
threads_started_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NgxRewriteDriverFactory::ParentOrChildInit(ngx_log_t* log) {
|
void NgxRewriteDriverFactory::LoggingInit(ngx_log_t* log) {
|
||||||
|
net_instaweb::log_message_handler::Install(log);
|
||||||
if (install_crash_handler_) {
|
if (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);
|
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 +252,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
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ extern "C" {
|
|||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "apr_pools.h"
|
|
||||||
#include "net/instaweb/system/public/system_rewrite_driver_factory.h"
|
#include "net/instaweb/system/public/system_rewrite_driver_factory.h"
|
||||||
#include "net/instaweb/util/public/md5_hasher.h"
|
#include "net/instaweb/util/public/md5_hasher.h"
|
||||||
#include "net/instaweb/util/public/scoped_ptr.h"
|
#include "net/instaweb/util/public/scoped_ptr.h"
|
||||||
@@ -39,99 +38,64 @@ extern "C" {
|
|||||||
|
|
||||||
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 StaticAssetManager;
|
||||||
class Statistics;
|
class Statistics;
|
||||||
class SystemCaches;
|
class SystemThreadSystem;
|
||||||
|
|
||||||
class NgxRewriteDriverFactory : public SystemRewriteDriverFactory {
|
class NgxRewriteDriverFactory : public SystemRewriteDriverFactory {
|
||||||
public:
|
public:
|
||||||
static const char kStaticAssetPrefix[];
|
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.
|
// Initializes the StaticAssetManager.
|
||||||
virtual void InitStaticAssetManager(
|
virtual void InitStaticAssetManager(
|
||||||
StaticAssetManager* static_asset_manager);
|
StaticAssetManager* static_asset_manager);
|
||||||
// Print out details of all the connections to memcached servers.
|
virtual ServerContext* NewDecodingServerContext();
|
||||||
void PrintMemCacheStats(GoogleString* out);
|
bool InitNgxUrlAsyncFetchers();
|
||||||
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);
|
||||||
virtual void ShutDown();
|
NgxServerContext* MakeNgxServerContext(StringPiece hostname, int port);
|
||||||
virtual void StopCacheActivity();
|
virtual ServerContext* NewServerContext();
|
||||||
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 {
|
bool use_per_vhost_statistics() const {
|
||||||
@@ -146,12 +110,6 @@ class NgxRewriteDriverFactory : public SystemRewriteDriverFactory {
|
|||||||
void set_install_crash_handler(bool x) {
|
void set_install_crash_handler(bool x) {
|
||||||
install_crash_handler_ = 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;
|
||||||
}
|
}
|
||||||
@@ -177,40 +135,43 @@ class NgxRewriteDriverFactory : public SystemRewriteDriverFactory {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoggingInit(ngx_log_t* log);
|
||||||
|
|
||||||
|
virtual void ShutDownMessageHandlers();
|
||||||
|
|
||||||
|
virtual void SetCircularBuffer(SharedCircularBuffer* buffer);
|
||||||
|
|
||||||
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
|
// If true, we'll have a separate statistics object for each vhost
|
||||||
// (along with a global aggregate), rather than just a single object
|
// (along with a global aggregate), rather than just a single object
|
||||||
// aggregating all of them.
|
// aggregating all of them.
|
||||||
bool use_per_vhost_statistics_;
|
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_;
|
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_;
|
bool rate_limit_background_fetches_;
|
||||||
|
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_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(NgxRewriteDriverFactory);
|
DISALLOW_COPY_AND_ASSIGN(NgxRewriteDriverFactory);
|
||||||
};
|
};
|
||||||
|
|||||||
+168
-93
@@ -37,12 +37,49 @@ namespace net_instaweb {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char kNgxPagespeedStatisticsHandlerPath[] = "/ngx_pagespeed_statistics";
|
// 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 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",
|
||||||
|
"TrackOriginalContentLength",
|
||||||
|
"UsePerVHostStatistics", // TODO(anupama): What to do about "No longer used"
|
||||||
|
"BlockingRewriteRefererUrls",
|
||||||
|
"CreateSharedMemoryMetadataCache",
|
||||||
|
"LoadFromFile",
|
||||||
|
"LoadFromFileMatch",
|
||||||
|
"LoadFromFileRule",
|
||||||
|
"LoadFromFileRuleMatch",
|
||||||
|
"UseNativeFetcher"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Options that can only be used in the main (http) option scope.
|
||||||
|
const char* const main_only_options[] = {
|
||||||
|
"UseNativeFetcher"
|
||||||
|
};
|
||||||
|
|
||||||
} // 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();
|
||||||
@@ -52,29 +89,17 @@ void NgxRewriteOptions::Init() {
|
|||||||
DCHECK(ngx_properties_ != NULL)
|
DCHECK(ngx_properties_ != NULL)
|
||||||
<< "Call NgxRewriteOptions::Initialize() before construction";
|
<< "Call NgxRewriteOptions::Initialize() before construction";
|
||||||
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.
|
// Nothing ngx-specific for now.
|
||||||
|
|
||||||
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 +120,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 +167,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) {
|
||||||
CHECK_GE(n_args, 1);
|
CHECK_GE(n_args, 1);
|
||||||
|
|
||||||
StringPiece directive = args[0];
|
StringPiece directive = args[0];
|
||||||
@@ -144,6 +233,11 @@ 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.");
|
||||||
|
}
|
||||||
|
|
||||||
GoogleString msg;
|
GoogleString msg;
|
||||||
OptionSettingResult result;
|
OptionSettingResult result;
|
||||||
if (n_args == 1) {
|
if (n_args == 1) {
|
||||||
@@ -153,62 +247,45 @@ NgxRewriteOptions::ParseAndSetOptions(
|
|||||||
// TODO(morlovich): Remove these special hacks, and handle these via
|
// TODO(morlovich): Remove these special hacks, and handle these via
|
||||||
// ParseAndSetOptionFromEnum1.
|
// ParseAndSetOptionFromEnum1.
|
||||||
if (IsDirective(directive, "UsePerVHostStatistics")) {
|
if (IsDirective(directive, "UsePerVHostStatistics")) {
|
||||||
// TODO(oschaaf): mod_pagespeed has a nicer way to do this.
|
result = ParseAndSetOptionHelper<NgxRewriteDriverFactory>(
|
||||||
if (IsDirective(arg, "on")) {
|
arg, driver_factory,
|
||||||
driver_factory->set_use_per_vhost_statistics(true);
|
&NgxRewriteDriverFactory::set_use_per_vhost_statistics);
|
||||||
result = RewriteOptions::kOptionOk;
|
} else if (IsDirective(directive, "InstallCrashHandler")) {
|
||||||
} else if (IsDirective(arg, "off")) {
|
result = ParseAndSetOptionHelper<NgxRewriteDriverFactory>(
|
||||||
driver_factory->set_use_per_vhost_statistics(false);
|
arg, driver_factory,
|
||||||
result = RewriteOptions::kOptionOk;
|
&NgxRewriteDriverFactory::set_install_crash_handler);
|
||||||
} else {
|
} else if (IsDirective(directive, "MessageBufferSize")) {
|
||||||
result = RewriteOptions::kOptionValueInvalid;
|
int message_buffer_size;
|
||||||
}
|
bool ok = StringToInt(arg.as_string(), &message_buffer_size);
|
||||||
} else if (IsDirective(directive, "InstallCrashHandler")) {
|
if (ok && message_buffer_size >= 0) {
|
||||||
// TODO(oschaaf): mod_pagespeed has a nicer way to do this.
|
driver_factory->set_message_buffer_size(message_buffer_size);
|
||||||
if (IsDirective(arg, "on")) {
|
result = RewriteOptions::kOptionOk;
|
||||||
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);
|
result = RewriteOptions::kOptionValueInvalid;
|
||||||
}
|
}
|
||||||
|
} else if (IsDirective(directive, "UseNativeFetcher")) {
|
||||||
|
result = ParseAndSetOptionHelper<NgxRewriteDriverFactory>(
|
||||||
|
arg, driver_factory,
|
||||||
|
&NgxRewriteDriverFactory::set_use_native_fetcher);
|
||||||
|
} else if (IsDirective(directive, "RateLimitBackgroundFetches")) {
|
||||||
|
result = ParseAndSetOptionHelper<NgxRewriteDriverFactory>(
|
||||||
|
arg, driver_factory,
|
||||||
|
&NgxRewriteDriverFactory::set_rate_limit_background_fetches);
|
||||||
|
} else if (IsDirective(directive, "ForceCaching")) {
|
||||||
|
result = ParseAndSetOptionHelper<SystemRewriteDriverFactory>(
|
||||||
|
arg, driver_factory,
|
||||||
|
&SystemRewriteDriverFactory::set_force_caching);
|
||||||
|
} else if (IsDirective(directive, "ListOutstandingUrlsOnError")) {
|
||||||
|
result = ParseAndSetOptionHelper<SystemRewriteDriverFactory>(
|
||||||
|
arg, driver_factory,
|
||||||
|
&SystemRewriteDriverFactory::list_outstanding_urls_on_error);
|
||||||
|
} else if (IsDirective(directive, "TrackOriginalContentLength")) {
|
||||||
|
result = ParseAndSetOptionHelper<SystemRewriteDriverFactory>(
|
||||||
|
arg, driver_factory,
|
||||||
|
&SystemRewriteDriverFactory::set_track_original_content_length);
|
||||||
|
} else {
|
||||||
|
result = ParseAndSetOptionFromName1(directive, args[1], &msg, handler);
|
||||||
|
}
|
||||||
} else if (n_args == 3) {
|
} else if (n_args == 3) {
|
||||||
// Short-term special handling, until this moves to common code.
|
// Short-term special handling, until this moves to common code.
|
||||||
// TODO(morlovich): Clean this up.
|
// TODO(morlovich): Clean this up.
|
||||||
@@ -230,25 +307,22 @@ NgxRewriteOptions::ParseAndSetOptions(
|
|||||||
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";
|
return ps_error_string_for_option(
|
||||||
|
pool, directive, "not recognized or too many arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +331,8 @@ NgxRewriteOptions::ParseAndSetOptions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
NgxRewriteOptions* NgxRewriteOptions::Clone() const {
|
NgxRewriteOptions* NgxRewriteOptions::Clone() const {
|
||||||
NgxRewriteOptions* options = new NgxRewriteOptions(thread_system());
|
NgxRewriteOptions* options = new NgxRewriteOptions(
|
||||||
|
StrCat("cloned from ", description()), thread_system());
|
||||||
options->Merge(*this);
|
options->Merge(*this);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ class NgxRewriteOptions : public SystemRewriteOptions {
|
|||||||
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() { }
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ class NgxRewriteOptions : public SystemRewriteOptions {
|
|||||||
// pool is a memory pool for allocating error strings.
|
// pool is a memory pool for allocating error strings.
|
||||||
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);
|
NgxRewriteDriverFactory* driver_factory, OptionScope scope);
|
||||||
|
|
||||||
// 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;
|
||||||
@@ -85,9 +87,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 +103,23 @@ 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_);
|
AddProperty(default_value, offset, id, option_name, ngx_properties_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
|
|||||||
+38
-95
@@ -18,120 +18,63 @@
|
|||||||
|
|
||||||
#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 "net/instaweb/system/public/add_headers_fetcher.h"
|
#include "net/instaweb/system/public/add_headers_fetcher.h"
|
||||||
#include "net/instaweb/system/public/loopback_route_fetcher.h"
|
#include "net/instaweb/system/public/loopback_route_fetcher.h"
|
||||||
#include "net/instaweb/system/public/system_caches.h"
|
#include "net/instaweb/system/public/system_request_context.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;
|
||||||
|
#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));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace net_instaweb
|
} // namespace net_instaweb
|
||||||
|
|||||||
+14
-28
@@ -21,19 +21,23 @@
|
|||||||
#ifndef NGX_SERVER_CONTEXT_H_
|
#ifndef NGX_SERVER_CONTEXT_H_
|
||||||
#define NGX_SERVER_CONTEXT_H_
|
#define NGX_SERVER_CONTEXT_H_
|
||||||
|
|
||||||
|
#include "ngx_message_handler.h"
|
||||||
#include "net/instaweb/system/public/system_server_context.h"
|
#include "net/instaweb/system/public/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 expect to use ProxyFetch with HTML.
|
||||||
@@ -43,34 +47,16 @@ class NgxServerContext : public SystemServerContext {
|
|||||||
// 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());
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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_
|
|
||||||
@@ -66,10 +66,10 @@ namespace net_instaweb {
|
|||||||
mutex_(NULL) {
|
mutex_(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;
|
||||||
@@ -106,6 +106,36 @@ namespace net_instaweb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
@@ -167,15 +197,15 @@ namespace net_instaweb {
|
|||||||
command_connection_->read->handler = CommandHandler;
|
command_connection_->read->handler = CommandHandler;
|
||||||
ngx_add_event(command_connection_->read, NGX_READ_EVENT, 0);
|
ngx_add_event(command_connection_->read, NGX_READ_EVENT, 0);
|
||||||
|
|
||||||
if (url_.url.len == 0) {
|
if (proxy_.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;
|
||||||
@@ -191,7 +221,7 @@ 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);
|
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, fetch_timeout_, log_);
|
||||||
ScopedMutex lock(mutex_);
|
ScopedMutex lock(mutex_);
|
||||||
|
|||||||
@@ -115,13 +115,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_;
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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_
|
|
||||||
+1147
-226
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
|||||||
worker_processes 1;
|
worker_processes 1;
|
||||||
|
|
||||||
daemon @@DAEMON@@;
|
daemon @@DAEMON@@;
|
||||||
master_process @@MASTER_PROCESS@@;
|
master_process on;
|
||||||
|
|
||||||
error_log "@@ERROR_LOG@@" debug;
|
error_log "@@ERROR_LOG@@" debug;
|
||||||
pid "@@TEST_TMP@@/nginx.pid";
|
pid "@@TEST_TMP@@/nginx.pid";
|
||||||
@@ -28,9 +28,22 @@ http {
|
|||||||
proxy_temp_path "@@TMP_PROXY_CACHE@@";
|
proxy_temp_path "@@TMP_PROXY_CACHE@@";
|
||||||
|
|
||||||
root "@@SERVER_ROOT@@";
|
root "@@SERVER_ROOT@@";
|
||||||
pagespeed UsePerVHostStatistics on;
|
|
||||||
|
|
||||||
|
# Block 5a: Decide on Cache-Control header value to use for outgoing
|
||||||
|
# response.
|
||||||
|
# Map new_cache_control_header_val to "no-cache, max-age=0" if the
|
||||||
|
# content is html and use the original Cache-Control header value
|
||||||
|
# in all other cases.
|
||||||
|
map $upstream_http_content_type $new_cache_control_header_val {
|
||||||
|
default $upstream_http_cache_control;
|
||||||
|
"~*text/html" "no-cache, max-age=0";
|
||||||
|
}
|
||||||
|
|
||||||
|
pagespeed UsePerVHostStatistics on;
|
||||||
|
pagespeed InPlaceResourceOptimization on;
|
||||||
pagespeed CreateSharedMemoryMetadataCache "@@SHM_CACHE@@" 8192;
|
pagespeed CreateSharedMemoryMetadataCache "@@SHM_CACHE@@" 8192;
|
||||||
|
pagespeed PreserveUrlRelativity on;
|
||||||
|
pagespeed BlockingRewriteKey psatest;
|
||||||
|
|
||||||
# CriticalImagesBeaconEnabled is now on by default, but we disable in testing.
|
# CriticalImagesBeaconEnabled is now on by default, but we disable in testing.
|
||||||
# With this option enabled, the inline image system test will currently fail.
|
# With this option enabled, the inline image system test will currently fail.
|
||||||
@@ -39,6 +52,11 @@ http {
|
|||||||
# critical images to be inlined, so we just disable the option here.
|
# critical images to be inlined, so we just disable the option here.
|
||||||
pagespeed CriticalImagesBeaconEnabled false;
|
pagespeed CriticalImagesBeaconEnabled false;
|
||||||
|
|
||||||
|
# By default, resources will not be used for inlining without explicit
|
||||||
|
# authorization. Supported values are off or a comma-separated list of strings
|
||||||
|
# from {Script,Stylesheet}.
|
||||||
|
pagespeed InlineResourcesWithoutExplicitAuthorization off;
|
||||||
|
|
||||||
pagespeed Statistics on;
|
pagespeed Statistics on;
|
||||||
pagespeed StatisticsLogging on;
|
pagespeed StatisticsLogging on;
|
||||||
pagespeed LogDir "@@TEST_TMP@@/logdir";
|
pagespeed LogDir "@@TEST_TMP@@/logdir";
|
||||||
@@ -52,7 +70,6 @@ http {
|
|||||||
server_name max-cacheable-content-length.example.com;
|
server_name max-cacheable-content-length.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
pagespeed BlockingRewriteKey psatest;
|
|
||||||
|
|
||||||
pagespeed RewriteLevel PassThrough;
|
pagespeed RewriteLevel PassThrough;
|
||||||
pagespeed EnableFilters rewrite_javascript;
|
pagespeed EnableFilters rewrite_javascript;
|
||||||
@@ -63,6 +80,7 @@ http {
|
|||||||
@@RESOLVER@@
|
@@RESOLVER@@
|
||||||
|
|
||||||
server {
|
server {
|
||||||
|
# Block 1: Basic port, server_name definitions.
|
||||||
# This server represents the external caching layer server which
|
# This server represents the external caching layer server which
|
||||||
# receives user requests and proxies them to the upstream server
|
# receives user requests and proxies them to the upstream server
|
||||||
# running on the PRIMARY_PORT when the response is not available in
|
# running on the PRIMARY_PORT when the response is not available in
|
||||||
@@ -71,58 +89,149 @@ http {
|
|||||||
server_name proxy_cache.example.com;
|
server_name proxy_cache.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
|
# Disable PageSpeed on this server.
|
||||||
pagespeed off;
|
pagespeed off;
|
||||||
|
|
||||||
set $ua_dependent_ps_capability_list "";
|
# Block 2: Define prefix for proxy_cache_key based on the UserAgent.
|
||||||
set $bypass_cache 1;
|
|
||||||
|
# Define placeholder PS-CapabilityList header values for large and small
|
||||||
|
# screens with no UA dependent optimizations. Note that these placeholder
|
||||||
|
# values should not contain any of ll, ii, dj, jw or ws, since these
|
||||||
|
# codes will end up representing optimizations to be supported for the
|
||||||
|
# request.
|
||||||
|
set $default_ps_capability_list_for_large_screens "LargeScreen.SkipUADependentOptimizations";
|
||||||
|
set $default_ps_capability_list_for_small_screens "TinyScreen.SkipUADependentOptimizations";
|
||||||
|
|
||||||
|
# As a fallback, the PS-CapabilityList header that is sent to the upstream
|
||||||
|
# PageSpeed server should be for a large screen device with no browser
|
||||||
|
# specific optimizations.
|
||||||
|
set $ps_capability_list $default_ps_capability_list_for_large_screens;
|
||||||
|
|
||||||
|
# Cache-fragment 1: Desktop User-Agents that support lazyload_images (ll),
|
||||||
|
# inline_images (ii) and defer_javascript (dj).
|
||||||
|
# Note: Wget is added for testing purposes only.
|
||||||
if ($http_user_agent ~* "Chrome/|Firefox/|MSIE |Safari|Wget") {
|
if ($http_user_agent ~* "Chrome/|Firefox/|MSIE |Safari|Wget") {
|
||||||
# User Agents that support lazyload-images (ll), inline-images (ii) and
|
set $ps_capability_list "ll,ii,dj:";
|
||||||
# defer-javascript (dj).
|
|
||||||
set $ua_dependent_ps_capability_list "ll,ii,dj:";
|
|
||||||
set $bypass_cache 0;
|
|
||||||
}
|
}
|
||||||
|
# Cache-fragment 2: Desktop User-Agents that support lazyload_images (ll),
|
||||||
|
# inline_images (ii), defer_javascript (dj), webp (jw) and lossless_webp
|
||||||
|
# (ws).
|
||||||
if ($http_user_agent ~*
|
if ($http_user_agent ~*
|
||||||
"Chrome/[2][3-9]+\.|Chrome/[[3-9][0-9]+\.|Chrome/[0-9]{3,}\.") {
|
"Chrome/[2][3-9]+\.|Chrome/[[3-9][0-9]+\.|Chrome/[0-9]{3,}\.") {
|
||||||
# User Agents that support lazyload-images (ll), inline-images (ii),
|
set $ps_capability_list "ll,ii,dj,jw,ws:";
|
||||||
# defer-javascript (dj), webp (jw) and webp-lossless (ws).
|
}
|
||||||
set $ua_dependent_ps_capability_list "ll,ii,dj,jw,ws:";
|
# Cache-fragment 3: This fragment contains (a) Desktop User-Agents that
|
||||||
set $bypass_cache 0;
|
# match fragments 1 or 2 but should not because they represent older
|
||||||
|
# versions of certain browsers or bots and (b) Tablet User-Agents that
|
||||||
|
# correspond to large screens. These will only get optimizations that work
|
||||||
|
# on all browsers and use image compression qualities applicable to large
|
||||||
|
# screens. Note that even Tablets that are capable of supporting inline or
|
||||||
|
# webp images, e.g. Android 4.1.2, will not get these advanced
|
||||||
|
# optimizations.
|
||||||
|
if ($http_user_agent ~* "Firefox/[1-2]\.|MSIE [5-8]\.|bot|Yahoo!|Ruby|RPT-HTTPClient|(Google \(\+https\:\/\/developers\.google\.com\/\+\/web\/snippet\/\))|Android|iPad|TouchPad|Silk-Accelerated|Kindle Fire") {
|
||||||
|
set $ps_capability_list $default_ps_capability_list_for_large_screens;
|
||||||
|
}
|
||||||
|
# Cache-fragment 4: Mobiles and small screen Tablets will use image compression
|
||||||
|
# qualities applicable to small screens, but all other optimizations will be
|
||||||
|
# those that work on all browsers.
|
||||||
|
if ($http_user_agent ~* "Mozilla.*Android.*Mobile*|iPhone|BlackBerry|Opera Mobi|Opera Mini|SymbianOS|UP.Browser|J-PHONE|Profile/MIDP|portalmmm|DoCoMo|Obigo|Galaxy Nexus|GT-I9300|GT-N7100|HTC One|Nexus [4|7|S]|Xoom|XT907") {
|
||||||
|
set $ps_capability_list $default_ps_capability_list_for_small_screens;
|
||||||
}
|
}
|
||||||
|
|
||||||
# All User Agents that represent
|
# Block 3a: Bypass the cache for .pagespeed. resource. PageSpeed has its own
|
||||||
# 1) mobiles
|
# cache for these, and these could bloat up the caching layer.
|
||||||
# 2) tablets
|
if ($uri ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+") {
|
||||||
# 3) desktop browsers that do not have defer-javascript capability at a minimum
|
set $bypass_cache "1";
|
||||||
# are made to go to the pagespeed server directly bypassing the proxy_cache.
|
|
||||||
if ($http_user_agent ~* "Firefox/[1-2]\.|MSIE [5-8]\.") {
|
|
||||||
set $ua_dependent_ps_capability_list "";
|
|
||||||
set $bypass_cache 1;
|
|
||||||
}
|
}
|
||||||
if ($http_user_agent ~* "Mozilla.*Android.*Mobile*|iPhone|BlackBerry|Opera Mobi|Opera Mini|SymbianOS|UP.Browser|J-PHONE|Profile/MIDP|portalmmm|DoCoMo|Obigo") {
|
|
||||||
# These are Mobile User Agents. We don't cache responses for these.
|
set_random $rand 0 100;
|
||||||
set $ua_dependent_ps_capability_list "";
|
set $should_beacon_header_val "";
|
||||||
set $bypass_cache 1;
|
if ($rand ~* "^[0-4]$") {
|
||||||
}
|
set $should_beacon_header_val "random_rebeaconing_key";
|
||||||
if ($http_user_agent ~* "Android|iPad|TouchPad|Silk-Accelerated|Kindle Fire") {
|
|
||||||
# These are Tablet User Agents. We don't cache responses for these.
|
|
||||||
set $ua_dependent_ps_capability_list "";
|
|
||||||
set $bypass_cache 1;
|
set $bypass_cache 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Block 3b: Only cache responses to clients that support gzip. Most clients
|
||||||
|
# do, and the cache holds much more if it stores gzipped responses.
|
||||||
|
if ($http_accept_encoding !~* gzip) {
|
||||||
|
set $bypass_cache "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Block 4: Location block for purge requests.
|
||||||
location ~ /purge(/.*) {
|
location ~ /purge(/.*) {
|
||||||
allow all;
|
allow 127.0.0.1;
|
||||||
proxy_cache_purge htmlcache $ua_dependent_ps_capability_list$1$is_args$args;
|
deny all;
|
||||||
|
proxy_cache_purge htmlcache $ps_capability_list$1$is_args$args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Block 6: Location block with proxy_cache directives.
|
||||||
location /mod_pagespeed_test/cachable_rewritten_html/ {
|
location /mod_pagespeed_test/cachable_rewritten_html/ {
|
||||||
|
# 1: Upstream PageSpeed server is running at localhost:8050.
|
||||||
proxy_pass http://localhost:@@PRIMARY_PORT@@;
|
proxy_pass http://localhost:@@PRIMARY_PORT@@;
|
||||||
proxy_set_header Host $host;
|
# 2: Use htmlcache as the zone for caching.
|
||||||
proxy_cache_valid 200 30s;
|
|
||||||
proxy_cache htmlcache;
|
proxy_cache htmlcache;
|
||||||
proxy_ignore_headers Cache-Control;
|
# 3: Bypass requests that correspond to .pagespeed. resources
|
||||||
add_header X-Cache $upstream_cache_status;
|
# or clients that do not support gzip etc.
|
||||||
proxy_cache_key $ua_dependent_ps_capability_list$uri$is_args$args;
|
|
||||||
proxy_cache_bypass $bypass_cache;
|
proxy_cache_bypass $bypass_cache;
|
||||||
|
# 4: Use the redefined proxy_cache_key and make sure the /purge/
|
||||||
|
# block uses the same key.
|
||||||
|
proxy_cache_key $ps_capability_list$uri$is_args$args;
|
||||||
|
# 5: Forward Host header to upstream server.
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
# 6: Set the PS-CapabilityList header for PageSpeed server to respect.
|
||||||
|
proxy_set_header PS-CapabilityList $ps_capability_list;
|
||||||
|
add_header PS-CapabilityList $ps_capability_list;
|
||||||
|
# 7: Add a header for identifying cache hits/misses/expires. This is
|
||||||
|
# for debugging purposes only and can be commented out in production.
|
||||||
|
add_header X-Cache $upstream_cache_status;
|
||||||
|
|
||||||
|
# Block 5b: Override Cache-Control headers as needed.
|
||||||
|
# Hide the upstream cache control header.
|
||||||
|
proxy_hide_header Cache-Control;
|
||||||
|
# Add the inferred Cache-Control header.
|
||||||
|
add_header Cache-Control $new_cache_control_header_val;
|
||||||
|
|
||||||
|
proxy_set_header PS-ShouldBeacon $should_beacon_header_val;
|
||||||
|
proxy_hide_header PS-ShouldBeacon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name if-in-server.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@";
|
||||||
|
|
||||||
|
pagespeed RewriteLevel PassThrough;
|
||||||
|
set $inline_javascript "No";
|
||||||
|
|
||||||
|
if ($http_x_custom_header_inline_js) {
|
||||||
|
# TODO(jefftk): Turn on NGX_HTTP_SIF_CONF and figure out how to get
|
||||||
|
# pagespeed directives inside of a server location block to be respected,
|
||||||
|
# then uncomment the following line and duplicate the if-in-location test
|
||||||
|
# for if-in-server.
|
||||||
|
#pagespeed EnableFilters inline_javascript;
|
||||||
|
set $inline_javascript "Yes";
|
||||||
|
}
|
||||||
|
|
||||||
|
add_header "X-Inline-Javascript" $inline_javascript;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name if-in-location.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@";
|
||||||
|
|
||||||
|
|
||||||
|
location / {
|
||||||
|
set $inline_javascript "No";
|
||||||
|
pagespeed RewriteLevel PassThrough;
|
||||||
|
|
||||||
|
if ($http_x_custom_header_inline_js) {
|
||||||
|
pagespeed EnableFilters inline_javascript;
|
||||||
|
set $inline_javascript "Yes";
|
||||||
|
}
|
||||||
|
|
||||||
|
add_header "X-Inline-Javascript" $inline_javascript;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +249,7 @@ http {
|
|||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
server_name experiment.example.com;
|
server_name experiment.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
pagespeed InPlaceResourceOptimization off;
|
||||||
|
|
||||||
pagespeed RunExperiment on;
|
pagespeed RunExperiment on;
|
||||||
pagespeed AnalyticsID "123-45-6734";
|
pagespeed AnalyticsID "123-45-6734";
|
||||||
@@ -147,6 +257,7 @@ http {
|
|||||||
pagespeed ExperimentSpec
|
pagespeed ExperimentSpec
|
||||||
"id=7;enable=recompress_images;disable=convert_jpeg_to_progressive;percent=50";
|
"id=7;enable=recompress_images;disable=convert_jpeg_to_progressive;percent=50";
|
||||||
pagespeed ExperimentSpec "id=2;enable=recompress_images;percent=50";
|
pagespeed ExperimentSpec "id=2;enable=recompress_images;percent=50";
|
||||||
|
pagespeed ExperimentSpec "id=3;default;percent=0";
|
||||||
}
|
}
|
||||||
server {
|
server {
|
||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
@@ -158,6 +269,7 @@ http {
|
|||||||
pagespeed ExperimentSpec
|
pagespeed ExperimentSpec
|
||||||
"id=7;enable=recompress_images;disable=convert_jpeg_to_progressive;percent=50";
|
"id=7;enable=recompress_images;disable=convert_jpeg_to_progressive;percent=50";
|
||||||
pagespeed ExperimentSpec "id=2;enable=recompress_images;percent=50";
|
pagespeed ExperimentSpec "id=2;enable=recompress_images;percent=50";
|
||||||
|
pagespeed ExperimentSpec "id=3;default;percent=0";
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
@@ -199,6 +311,87 @@ http {
|
|||||||
pagespeed CriticalImagesBeaconEnabled true;
|
pagespeed CriticalImagesBeaconEnabled true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
# Setup a vhost with the critical image beacon enabled to make sure that
|
||||||
|
# downstream caches and rebeaconing interact correctly.
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name downstreamcacherebeacon.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
|
pagespeed RewriteLevel PassThrough;
|
||||||
|
pagespeed CriticalImagesBeaconEnabled true;
|
||||||
|
# Enable the downstream caching feature and specify a rebeaconing key.
|
||||||
|
pagespeed DownstreamCachePurgeLocationPrefix "http://localhost:@@SECONDARY_PORT@@/purge";
|
||||||
|
pagespeed DownstreamCacheRebeaconingKey random_rebeaconing_key;
|
||||||
|
location ~ .*[.]html {
|
||||||
|
add_header Cache-Control "private, max-age=3000";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name renderedimagebeacon.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
|
pagespeed RewriteLevel PassThrough;
|
||||||
|
pagespeed EnableFilters resize_rendered_image_dimensions;
|
||||||
|
pagespeed CriticalImagesBeaconEnabled true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Build a configuration hierarchy where at the root we have turned on
|
||||||
|
# OptimizeForBandwidth, and in various subdirectories we override settings
|
||||||
|
# to make them more aggressive.
|
||||||
|
#
|
||||||
|
# In Apache we can do this all with Directory blocks, but to get the same
|
||||||
|
# inheretence in Nginx we need to have location blocks inside a server block.
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name optimizeforbandwidth.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
|
pagespeed RewriteLevel OptimizeForBandwidth;
|
||||||
|
pagespeed DisableFilters add_instrumentation;
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/optimize_for_bandwidth/inline_css {
|
||||||
|
pagespeed EnableFilters inline_css;
|
||||||
|
}
|
||||||
|
location /mod_pagespeed_test/optimize_for_bandwidth/css_urls {
|
||||||
|
pagespeed CssPreserveURLs off;
|
||||||
|
}
|
||||||
|
location /mod_pagespeed_test/optimize_for_bandwidth/image_urls {
|
||||||
|
pagespeed ImagePreserveURLs off;
|
||||||
|
}
|
||||||
|
location /mod_pagespeed_test/optimize_for_bandwidth/core_filters {
|
||||||
|
pagespeed RewriteLevel CoreFilters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
# For testing with a custom origin header. In this VirtualHost,
|
||||||
|
# /mod_pagespeed_test is included in our DocumentRoot and thus does
|
||||||
|
# not need to be in any resource URL paths. This helps us verify that
|
||||||
|
# we are looping back to the corect VirtualHost -- if we hit the wrong
|
||||||
|
# one it will not work. Also we don't have a VirtualHost for
|
||||||
|
# sharedcdn.example.com, so the default Host header used for
|
||||||
|
# origin-mapping won't work either. Instead, we want origin-fetches
|
||||||
|
# to go back to this VirtualHost so we rely on the new third optional
|
||||||
|
# argument to MapOriginDomain.
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name customhostheader.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@_test";
|
||||||
|
root "@@SERVER_ROOT@@/mod_pagespeed_test";
|
||||||
|
|
||||||
|
pagespeed on;
|
||||||
|
pagespeed RewriteLevel PassThrough;
|
||||||
|
pagespeed EnableFilters rewrite_images;
|
||||||
|
# Don't use localhost, as ngx_pagespeed's native fetcher cannot resolve it
|
||||||
|
pagespeed MapOriginDomain 127.0.0.1:@@SECONDARY_PORT@@/customhostheader
|
||||||
|
sharedcdn.example.com/test customhostheader.example.com;
|
||||||
|
pagespeed JpegRecompressionQuality 50;
|
||||||
|
pagespeed CriticalImagesBeaconEnabled false;
|
||||||
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
# Sets up a virtual host where we can specify forbidden filters without
|
# Sets up a virtual host where we can specify forbidden filters without
|
||||||
# affecting any other hosts.
|
# affecting any other hosts.
|
||||||
@@ -206,7 +399,6 @@ http {
|
|||||||
server_name forbidden.example.com;
|
server_name forbidden.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
pagespeed BlockingRewriteKey psatest;
|
|
||||||
|
|
||||||
# Start with all core filters enabled ...
|
# Start with all core filters enabled ...
|
||||||
pagespeed RewriteLevel CoreFilters;
|
pagespeed RewriteLevel CoreFilters;
|
||||||
@@ -217,6 +409,31 @@ http {
|
|||||||
pagespeed DisableFilters inline_css;
|
pagespeed DisableFilters inline_css;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name unauthorizedresources.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
|
pagespeed RewriteLevel PassThrough;
|
||||||
|
pagespeed InlineResourcesWithoutExplicitAuthorization Script,Stylesheet;
|
||||||
|
pagespeed CssInlineMaxBytes 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name client-domain-rewrite.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
|
# Don't actually try to rewrite any resources; the ones in
|
||||||
|
# rewrite_domains.html don't actually exist.
|
||||||
|
pagespeed RewriteLevel PassThrough;
|
||||||
|
|
||||||
|
pagespeed MapRewriteDomain http://client-domain-rewrite.example.com
|
||||||
|
http://src.example.com;
|
||||||
|
pagespeed ClientDomainRewrite true;
|
||||||
|
pagespeed EnableFilters rewrite_domains;
|
||||||
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
server_name url-attribute.example.com;
|
server_name url-attribute.example.com;
|
||||||
@@ -236,6 +453,9 @@ http {
|
|||||||
pagespeed UrlValuedAttribute custom a Image;
|
pagespeed UrlValuedAttribute custom a Image;
|
||||||
pagespeed UrlValuedAttribute custom b otherResource;
|
pagespeed UrlValuedAttribute custom b otherResource;
|
||||||
pagespeed UrlValuedAttribute custom c hyperlink;
|
pagespeed UrlValuedAttribute custom c hyperlink;
|
||||||
|
pagespeed UrlValuedAttribute img alt-src Image;
|
||||||
|
pagespeed UrlValuedAttribute video alt-a Image;
|
||||||
|
pagespeed UrlValuedAttribute video alt-b Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
@@ -313,7 +533,7 @@ http {
|
|||||||
# Note that we test with two distinct caches.
|
# Note that we test with two distinct caches.
|
||||||
server {
|
server {
|
||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
server_name embed-config-html.example.com;
|
server_name embed-config-html.example.org;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
|
||||||
root "@@SERVER_ROOT@@/mod_pagespeed_test";
|
root "@@SERVER_ROOT@@/mod_pagespeed_test";
|
||||||
@@ -323,6 +543,9 @@ http {
|
|||||||
pagespeed DisableFilters inline_css,extend_cache,inline_javascript;
|
pagespeed DisableFilters inline_css,extend_cache,inline_javascript;
|
||||||
pagespeed Domain embed-config-resources.example.com;
|
pagespeed Domain embed-config-resources.example.com;
|
||||||
|
|
||||||
|
# Share a cache keyspace with embed-config-resources.example.com.
|
||||||
|
pagespeed CacheFragment "embed-config";
|
||||||
|
|
||||||
pagespeed LoadFromFile "http://embed-config-resources.example.com/"
|
pagespeed LoadFromFile "http://embed-config-resources.example.com/"
|
||||||
"@@SERVER_ROOT@@/mod_pagespeed_example/";
|
"@@SERVER_ROOT@@/mod_pagespeed_example/";
|
||||||
}
|
}
|
||||||
@@ -338,12 +561,26 @@ http {
|
|||||||
|
|
||||||
# Note that we do not set the jpeg quality here, but take
|
# Note that we do not set the jpeg quality here, but take
|
||||||
# it from image URL query parameters that we synthesize in
|
# it from image URL query parameters that we synthesize in
|
||||||
# from embed-config-html.example.com.
|
# from embed-config-html.example.org.
|
||||||
|
|
||||||
|
# Share a cache keyspace with embed-config-html.example.org.
|
||||||
|
pagespeed CacheFragment "embed-config";
|
||||||
|
|
||||||
pagespeed LoadFromFile "http://embed-config-resources.example.com/"
|
pagespeed LoadFromFile "http://embed-config-resources.example.com/"
|
||||||
"@@SERVER_ROOT@@/mod_pagespeed_example/";
|
"@@SERVER_ROOT@@/mod_pagespeed_example/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name ipro-for-browser.example.com;
|
||||||
|
root "@@SERVER_ROOT@@/mod_pagespeed_example";
|
||||||
|
pagespeed EnableFilters rewrite_images,rewrite_css;
|
||||||
|
pagespeed EnableFilters convert_to_webp_lossless;
|
||||||
|
pagespeed EnableFilters in_place_optimize_for_browser;
|
||||||
|
pagespeed InPlaceResourceOptimization on;
|
||||||
|
pagespeed FileCachePath "@@IPRO_CACHE@@";
|
||||||
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
server_name respectvary.example.com;
|
server_name respectvary.example.com;
|
||||||
@@ -395,6 +632,7 @@ http {
|
|||||||
pagespeed MapRewriteDomain cdn.example.com origin.example.com;
|
pagespeed MapRewriteDomain cdn.example.com origin.example.com;
|
||||||
pagespeed RewriteLevel PassThrough;
|
pagespeed RewriteLevel PassThrough;
|
||||||
pagespeed EnableFilters rewrite_css,rewrite_images;
|
pagespeed EnableFilters rewrite_css,rewrite_images;
|
||||||
|
pagespeed CacheFragment "example";
|
||||||
}
|
}
|
||||||
server {
|
server {
|
||||||
# Sets up a logical origin for CDNs to fetch content from, on
|
# Sets up a logical origin for CDNs to fetch content from, on
|
||||||
@@ -407,6 +645,7 @@ http {
|
|||||||
pagespeed MapRewriteDomain cdn.example.com origin.example.com;
|
pagespeed MapRewriteDomain cdn.example.com origin.example.com;
|
||||||
pagespeed RewriteLevel PassThrough;
|
pagespeed RewriteLevel PassThrough;
|
||||||
pagespeed EnableFilters rewrite_css,rewrite_images;
|
pagespeed EnableFilters rewrite_css,rewrite_images;
|
||||||
|
pagespeed CacheFragment "example";
|
||||||
}
|
}
|
||||||
server {
|
server {
|
||||||
# Sets up a logical cdn, which is where we tell browsers to fetch resources
|
# Sets up a logical cdn, which is where we tell browsers to fetch resources
|
||||||
@@ -462,7 +701,6 @@ http {
|
|||||||
server_name blocking.example.com;
|
server_name blocking.example.com;
|
||||||
pagespeed FileCachePath "@@SECONDARY_CACHE@@";
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@";
|
||||||
|
|
||||||
pagespeed BlockingRewriteKey psatest;
|
|
||||||
pagespeed RewriteLevel PassThrough;
|
pagespeed RewriteLevel PassThrough;
|
||||||
pagespeed EnableFilters rewrite_images;
|
pagespeed EnableFilters rewrite_images;
|
||||||
}
|
}
|
||||||
@@ -472,35 +710,153 @@ http {
|
|||||||
server_name keepalive-html.example.com;
|
server_name keepalive-html.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
pagespeed RewriteLevel CoreFilters;
|
pagespeed RewriteLevel CoreFilters;
|
||||||
error_log "@@TEST_TMP@@/keepalive-html.example.com.error.log" info;
|
error_log "@@TEST_TMP@@/keepalive-html.example.com.error.log" warn;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
server_name keepalive-resource.example.com;
|
server_name keepalive-resource.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
error_log "@@TEST_TMP@@/keepalive-resource.example.com.error.log" info;
|
error_log "@@TEST_TMP@@/keepalive-resource.example.com.error.log" warn;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
server_name keepalive-beacon-get.example.com;
|
server_name keepalive-beacon-get.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
error_log "@@TEST_TMP@@/keepalive-beacon-get.example.com.error.log" info;
|
error_log "@@TEST_TMP@@/keepalive-beacon-get.example.com.error.log" warn;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
server_name keepalive-beacon-post.example.com;
|
server_name keepalive-beacon-post.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
error_log "@@TEST_TMP@@/keepalive-beacon-post.example.com.error.log" info;
|
error_log "@@TEST_TMP@@/keepalive-beacon-post.example.com.error.log" warn;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen @@SECONDARY_PORT@@;
|
listen @@SECONDARY_PORT@@;
|
||||||
server_name keepalive-static.example.com;
|
server_name keepalive-static.example.com;
|
||||||
pagespeed FileCachePath "@@FILE_CACHE@@";
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
error_log "@@TEST_TMP@@/keepalive-static.example.com.error.log" info;
|
error_log "@@TEST_TMP@@/keepalive-static.example.com.error.log" warn;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name response-header-filters.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@";
|
||||||
|
pagespeed RewriteLevel PassThrough;
|
||||||
|
pagespeed on;
|
||||||
|
add_header PageSpeedFilters add_instrumentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name response-header-disable.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@";
|
||||||
|
pagespeed EnableFilters add_instrumentation;
|
||||||
|
pagespeed on;
|
||||||
|
add_header PageSpeed off;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name ipro.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@";
|
||||||
|
|
||||||
|
pagespeed on;
|
||||||
|
pagespeed InPlaceResourceOptimization on;
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/ipro/nocache/test_image_dont_reuse.png {
|
||||||
|
add_header Cache-Control no-cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/ipro/no-cache-control-header {
|
||||||
|
add_header Cache-Control "";
|
||||||
|
pagespeed ImplicitCacheTtlMs 333000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test hosts to cover all possible cache configurations. L1 will be filecache
|
||||||
|
# or memcache depending on the setting of MEMCACHED_TEST. These four hosts
|
||||||
|
# are for the four settings for the L2 cache.
|
||||||
|
|
||||||
|
# 1. L2_d=LRU, L2_m=LRU
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name lrud-lrum.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@_lrud_lrum";
|
||||||
|
|
||||||
|
pagespeed LRUCacheKbPerProcess 1024;
|
||||||
|
pagespeed LRUCacheByteLimit 2000;
|
||||||
|
pagespeed EnableFilters rewrite_images;
|
||||||
|
pagespeed CriticalImagesBeaconEnabled false;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 2. L2_d=LRU, L2_m=SHM
|
||||||
|
pagespeed CreateSharedMemoryMetadataCache
|
||||||
|
"@@SECONDARY_CACHE@@_lrud_shmm" 8192;
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name lrud-shmm.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@_lrud_shmm";
|
||||||
|
|
||||||
|
pagespeed LRUCacheKbPerProcess 1024;
|
||||||
|
pagespeed LRUCacheByteLimit 2000;
|
||||||
|
pagespeed EnableFilters rewrite_images;
|
||||||
|
pagespeed CriticalImagesBeaconEnabled false;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 3. L2_d=none, L2_m=SHM
|
||||||
|
pagespeed CreateSharedMemoryMetadataCache
|
||||||
|
"@@SECONDARY_CACHE@@_noned_shmm" 8192;
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name noned-shmm.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@_noned_shmm";
|
||||||
|
|
||||||
|
pagespeed EnableFilters rewrite_images;
|
||||||
|
pagespeed CriticalImagesBeaconEnabled false;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 4. L2_d=none, L2_m=none
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name noned-nonem.example.com;
|
||||||
|
pagespeed FileCachePath "@@SECONDARY_CACHE@@_noned_nonem";
|
||||||
|
|
||||||
|
pagespeed EnableFilters rewrite_images;
|
||||||
|
pagespeed CriticalImagesBeaconEnabled false;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name date.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
add_header "Date" "Date: Fri, 16 Oct 2009 23:05:07 GMT";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Proxy + IPRO a gzip'd file for testing Issue 896.
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name ipro-proxy.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@_ipro_proxy";
|
||||||
|
|
||||||
|
pagespeed on;
|
||||||
|
pagespeed InPlaceResourceOptimization on;
|
||||||
|
pagespeed EnableFilters rewrite_domains;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass
|
||||||
|
"http://localhost:@@PRIMARY_PORT@@/mod_pagespeed_test/ipro/mod_deflate/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen @@SECONDARY_PORT@@;
|
||||||
|
server_name compressed-css.example.com;
|
||||||
|
pagespeed FileCachePath "@@FILE_CACHE@@";
|
||||||
|
pagespeed InPlaceResourceOptimization on;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
@@ -512,22 +868,40 @@ http {
|
|||||||
add_header "" "";
|
add_header "" "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Backend for ipro-proxy.example.com
|
||||||
|
location /mod_pagespeed_test/ipro/mod_deflate/ {
|
||||||
|
pagespeed off;
|
||||||
|
}
|
||||||
|
|
||||||
location /mod_pagespeed_test/cachable_rewritten_html/ {
|
location /mod_pagespeed_test/cachable_rewritten_html/ {
|
||||||
# This location has the html files that will be configured to be stored
|
# This location has the html files that will be configured to be stored
|
||||||
# in the proxy_cache layer.
|
# in the proxy_cache layer.
|
||||||
pagespeed DownstreamCachePurgeMethod "GET";
|
pagespeed DownstreamCachePurgeMethod "GET";
|
||||||
pagespeed DownstreamCachePurgeLocationPrefix "http://localhost:8051/purge";
|
pagespeed DownstreamCachePurgeLocationPrefix "http://localhost:@@SECONDARY_PORT@@/purge";
|
||||||
|
pagespeed DownstreamCacheRebeaconingKey "random_rebeaconing_key";
|
||||||
# We use a very small deadline here to force the rewriting to not complete
|
# We use a very small deadline here to force the rewriting to not complete
|
||||||
# in the very first attempt.
|
# in the very first attempt.
|
||||||
pagespeed RewriteDeadlinePerFlushMs 1;
|
pagespeed RewriteDeadlinePerFlushMs 1;
|
||||||
pagespeed RewriteLevel PassThrough;
|
pagespeed RewriteLevel PassThrough;
|
||||||
pagespeed EnableFilters collapse_whitespace,extend_cache,recompress_images,convert_jpeg_to_webp,defer_javascript;
|
pagespeed EnableFilters collapse_whitespace,extend_cache,recompress_images;
|
||||||
|
pagespeed CriticalImagesBeaconEnabled true;
|
||||||
|
add_header Cache-Control "public, max-age=100";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/disable_no_transform/index.html {
|
||||||
|
pagespeed DisableRewriteOnNoTransform off;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/disable_no_transform/disable_no_transform.css {
|
||||||
|
add_header 'Cache-Control' 'no-transform';
|
||||||
|
}
|
||||||
|
|
||||||
# uncomment the following two lines if you're testing memcached
|
# uncomment the following two lines if you're testing memcached
|
||||||
#pagespeed MemcachedServers "localhost:11211";
|
#pagespeed MemcachedServers "localhost:11211";
|
||||||
#pagespeed MemcachedThreads 1;
|
#pagespeed MemcachedThreads 1;
|
||||||
|
|
||||||
pagespeed on;
|
pagespeed on;
|
||||||
|
pagespeed MessageBufferSize 200000;
|
||||||
|
|
||||||
#pagespeed CacheFlushPollIntervalSec 1;
|
#pagespeed CacheFlushPollIntervalSec 1;
|
||||||
|
|
||||||
@@ -539,14 +913,6 @@ http {
|
|||||||
pagespeed Library 43 1o978_K0_LNE5_ystNklf
|
pagespeed Library 43 1o978_K0_LNE5_ystNklf
|
||||||
http://www.modpagespeed.com/rewrite_javascript.js;
|
http://www.modpagespeed.com/rewrite_javascript.js;
|
||||||
|
|
||||||
# If X-PSA-Blocking-Rewrite request header is present and its value matches
|
|
||||||
# the value of BlockingRewriteKey below, the response will be fully
|
|
||||||
# rewritten before being flushed to the client.
|
|
||||||
pagespeed BlockingRewriteKey psatest;
|
|
||||||
|
|
||||||
# Disable parsing if the size of the HTML exceeds 50kB.
|
|
||||||
pagespeed MaxHtmlParseBytes 50000;
|
|
||||||
|
|
||||||
add_header X-Extra-Header 1;
|
add_header X-Extra-Header 1;
|
||||||
|
|
||||||
# Establish a proxy mapping where the current server proxies an image
|
# Establish a proxy mapping where the current server proxies an image
|
||||||
@@ -585,6 +951,10 @@ http {
|
|||||||
pagespeed DisableFilters collapse_whitespace;
|
pagespeed DisableFilters collapse_whitespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/max_html_parse_size {
|
||||||
|
pagespeed MaxHtmlParseBytes 5000;
|
||||||
|
}
|
||||||
|
|
||||||
location ~ \.php$ {
|
location ~ \.php$ {
|
||||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||||
fastcgi_param QUERY_STRING $query_string;
|
fastcgi_param QUERY_STRING $query_string;
|
||||||
@@ -642,6 +1012,12 @@ http {
|
|||||||
add_header Cache-Control "private, max-age=3000";
|
add_header Cache-Control "private, max-age=3000";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/retain_cache_control_with_downstream_caching/ {
|
||||||
|
pagespeed ModifyCachingHeaders on;
|
||||||
|
pagespeed DownstreamCachePurgeLocationPrefix "http://localhost:8020/";
|
||||||
|
add_header Cache-Control "private, max-age=3000";
|
||||||
|
}
|
||||||
|
|
||||||
location /mod_pagespeed_test/avoid_renaming_introspective_javascript__on/ {
|
location /mod_pagespeed_test/avoid_renaming_introspective_javascript__on/ {
|
||||||
pagespeed AvoidRenamingIntrospectiveJavascript on;
|
pagespeed AvoidRenamingIntrospectiveJavascript on;
|
||||||
}
|
}
|
||||||
@@ -650,6 +1026,75 @@ http {
|
|||||||
pagespeed DisableFilters convert_jpeg_to_progressive;
|
pagespeed DisableFilters convert_jpeg_to_progressive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/ipro/test_image_dont_reuse.png {
|
||||||
|
expires 5m;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/ipro/instant/wait/ {
|
||||||
|
pagespeed InPlaceWaitForOptimized on;
|
||||||
|
|
||||||
|
# TODO(jefftk): When running with valgrind we need to raise the rewrite
|
||||||
|
# deadline or else we get "Deadline exceeded for rewrite of resource".
|
||||||
|
# I had thought InPlaceWaitForOptimized was supposed to disable the
|
||||||
|
# rewrite deadline, but it seems not to.
|
||||||
|
#
|
||||||
|
# InPlaceWaitForOptimized is definitely doing something, though: when I
|
||||||
|
# remove the InPlaceRewriteDeadlineMs line below and run without valgrind,
|
||||||
|
# purple.css is optimized via ipro on the first request but if I set
|
||||||
|
# InPlaceWaitForOptimized to off then it is not.
|
||||||
|
pagespeed InPlaceRewriteDeadlineMs 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/ipro/instant/deadline/ {
|
||||||
|
pagespeed InPlaceRewriteDeadlineMs -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test to make sure that user-authenticated resources do not get cached and
|
||||||
|
# optimized.
|
||||||
|
location /mod_pagespeed_test/auth/ {
|
||||||
|
auth_basic "Restricted";
|
||||||
|
auth_basic_user_file "@@SERVER_ROOT@@mod_pagespeed_test/auth/passwd.conf";
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/ipro/cookie/ {
|
||||||
|
# Add Vary:Cookie. This should prevent us from optimizing the
|
||||||
|
# vary_cookie.css even though PagespeedRespectVary is off.
|
||||||
|
# test/nginx_system_test.sh does the fetches test with and w/o cookies.
|
||||||
|
add_header Vary Cookie;
|
||||||
|
pagespeed RespectVary off;
|
||||||
|
pagespeed InPlaceWaitForOptimized on;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/ipro/cookie2/ {
|
||||||
|
# Add Vary:Cookie2. This should prevent us from optimizing the
|
||||||
|
# vary_cookie2.css even though PagespeedRespectVary is off.
|
||||||
|
# test/nginx_system_test.sh does the fetches test with and w/o cookie2.
|
||||||
|
add_header Vary Cookie2;
|
||||||
|
pagespeed RespectVary off;
|
||||||
|
pagespeed InPlaceWaitForOptimized on;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/vary/ {
|
||||||
|
pagespeed RespectVary on;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ /mod_pagespeed_test/vary/\.(js|css)$ {
|
||||||
|
add_header Vary User-Agent;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/vary/no_respect/ {
|
||||||
|
pagespeed DisableFilters add_instrumentation,inline_css;
|
||||||
|
pagespeed RespectVary off;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /mod_pagespeed_test/experimental_js_minifier/ {
|
||||||
|
pagespeed UseExperimentalJsMinifier on;
|
||||||
|
}
|
||||||
|
|
||||||
|
pagespeed LoadFromFile
|
||||||
|
"http://localhost:@@PRIMARY_PORT@@/mod_pagespeed_test/ipro/instant/"
|
||||||
|
"@@SERVER_ROOT@@/mod_pagespeed_test/ipro/instant/";
|
||||||
|
|
||||||
pagespeed EnableFilters remove_comments;
|
pagespeed EnableFilters remove_comments;
|
||||||
|
|
||||||
# Test LoadFromFile mapping by mapping one dir to another.
|
# Test LoadFromFile mapping by mapping one dir to another.
|
||||||
@@ -688,6 +1133,7 @@ http {
|
|||||||
# set up gzip
|
# set up gzip
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_vary on;
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
# Turn on gzip for all content types that should benefit from it.
|
# Turn on gzip for all content types that should benefit from it.
|
||||||
gzip_types application/ecmascript;
|
gzip_types application/ecmascript;
|
||||||
gzip_types application/javascript;
|
gzip_types application/javascript;
|
||||||
|
|||||||
@@ -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
|
||||||
|
...
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user