├── .gitignore ├── docker ├── alpine-3.8 │ ├── nginx-mainline │ │ ├── pagespeed.png │ │ ├── patches │ │ │ └── modpagespeed │ │ │ │ ├── rename_c_symbols.patch │ │ │ │ ├── pthread_nonrecursive_np.patch │ │ │ │ ├── automatic_makefile.patch │ │ │ │ ├── stack_trace_posix.patch │ │ │ │ └── libpng16.patch │ │ ├── conf │ │ │ ├── nginx.conf │ │ │ └── nginx.vh.default.conf │ │ └── Dockerfile │ └── nginx-stable │ │ ├── pagespeed.png │ │ ├── patches │ │ └── modpagespeed │ │ │ ├── rename_c_symbols.patch │ │ │ ├── pthread_nonrecursive_np.patch │ │ │ ├── automatic_makefile.patch │ │ │ ├── stack_trace_posix.patch │ │ │ └── libpng16.patch │ │ ├── conf │ │ ├── nginx.conf │ │ └── nginx.vh.default.conf │ │ └── Dockerfile ├── alpine-edge │ ├── nginx-stable │ │ ├── pagespeed.png │ │ ├── patches │ │ │ ├── modpagespeed │ │ │ │ ├── rename_c_symbols.patch │ │ │ │ ├── pthread_nonrecursive_np.patch │ │ │ │ ├── automatic_makefile.patch │ │ │ │ ├── stack_trace_posix.patch │ │ │ │ └── libpng16.patch │ │ │ └── ngx │ │ │ │ └── gcc8.patch │ │ ├── conf │ │ │ ├── nginx.conf │ │ │ └── nginx.vh.default.conf │ │ └── Dockerfile │ └── nginx-mainline │ │ ├── pagespeed.png │ │ ├── patches │ │ └── modpagespeed │ │ │ ├── rename_c_symbols.patch │ │ │ ├── pthread_nonrecursive_np.patch │ │ │ ├── automatic_makefile.patch │ │ │ ├── stack_trace_posix.patch │ │ │ └── libpng16.patch │ │ ├── conf │ │ ├── nginx.conf │ │ └── nginx.vh.default.conf │ │ └── Dockerfile └── README.md ├── PSOL_BINARY_URL ├── NOTICE ├── .gitmodules ├── .travis.yml ├── config.make ├── scripts ├── format_binary_url.sh ├── rebuild.sh └── pagespeed_libraries_generator.sh ├── src ├── ngx_list_iterator.cc ├── ngx_list_iterator.h ├── log_message_handler.h ├── ngx_caching_headers.cc ├── ngx_caching_headers.h ├── ngx_message_handler.h ├── ngx_server_context.h ├── ngx_event_connection.h ├── ngx_server_context.cc ├── log_message_handler.cc ├── ngx_gzip_setter.h ├── ngx_message_handler.cc ├── ngx_pagespeed.h ├── ngx_url_async_fetcher.h ├── ngx_rewrite_driver_factory.h ├── ngx_event_connection.cc ├── ngx_fetch.h ├── ngx_base_fetch.h ├── ngx_rewrite_options.h └── ngx_url_async_fetcher.cc ├── README.md ├── cpp_feature └── test ├── run_tests.sh └── valgrind.sup /.gitignore: -------------------------------------------------------------------------------- 1 | test/tmp 2 | psol/ 3 | psol-*.tar.gz 4 | *.*.*.*.tar.gz 5 | nginx 6 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/pagespeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/We-Amp/ngx_pagespeed/HEAD/docker/alpine-3.8/nginx-mainline/pagespeed.png -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/pagespeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/We-Amp/ngx_pagespeed/HEAD/docker/alpine-3.8/nginx-stable/pagespeed.png -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/pagespeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/We-Amp/ngx_pagespeed/HEAD/docker/alpine-edge/nginx-stable/pagespeed.png -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/pagespeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/We-Amp/ngx_pagespeed/HEAD/docker/alpine-edge/nginx-mainline/pagespeed.png -------------------------------------------------------------------------------- /PSOL_BINARY_URL: -------------------------------------------------------------------------------- 1 | In a release this file would contain the URL to download the pre-compiled PSOL 2 | binary, but on development branches (like this one) you have to build PSOL from 3 | source yourself. See: 4 | https://github.com/apache/incubator-pagespeed-ngx/wiki/Building-PSOL-From-Source 5 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/patches/modpagespeed/rename_c_symbols.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/automatic/rename_c_symbols.sh 2 | +++ b/pagespeed/automatic/rename_c_symbols.sh 3 | @@ -24,8 +24,8 @@ 4 | set -e # exit script if any command returns an error 5 | set -u # exit the script if any variable is uninitialized 6 | 7 | -IN=$(readlink -f $1) 8 | -OUT=$(readlink -f $2) 9 | +IN=$1 10 | +OUT=$2 11 | 12 | # Get a list of defined non-C++ symbols that are global and not weak. 13 | # _Z is used at start of C++-mangled symbol names. 14 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/patches/modpagespeed/rename_c_symbols.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/automatic/rename_c_symbols.sh 2 | +++ b/pagespeed/automatic/rename_c_symbols.sh 3 | @@ -24,8 +24,8 @@ 4 | set -e # exit script if any command returns an error 5 | set -u # exit the script if any variable is uninitialized 6 | 7 | -IN=$(readlink -f $1) 8 | -OUT=$(readlink -f $2) 9 | +IN=$1 10 | +OUT=$2 11 | 12 | # Get a list of defined non-C++ symbols that are global and not weak. 13 | # _Z is used at start of C++-mangled symbol names. 14 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/patches/modpagespeed/rename_c_symbols.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/automatic/rename_c_symbols.sh 2 | +++ b/pagespeed/automatic/rename_c_symbols.sh 3 | @@ -24,8 +24,8 @@ 4 | set -e # exit script if any command returns an error 5 | set -u # exit the script if any variable is uninitialized 6 | 7 | -IN=$(readlink -f $1) 8 | -OUT=$(readlink -f $2) 9 | +IN=$1 10 | +OUT=$2 11 | 12 | # Get a list of defined non-C++ symbols that are global and not weak. 13 | # _Z is used at start of C++-mangled symbol names. 14 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/patches/modpagespeed/rename_c_symbols.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/automatic/rename_c_symbols.sh 2 | +++ b/pagespeed/automatic/rename_c_symbols.sh 3 | @@ -24,8 +24,8 @@ 4 | set -e # exit script if any command returns an error 5 | set -u # exit the script if any variable is uninitialized 6 | 7 | -IN=$(readlink -f $1) 8 | -OUT=$(readlink -f $2) 9 | +IN=$1 10 | +OUT=$2 11 | 12 | # Get a list of defined non-C++ symbols that are global and not weak. 13 | # _Z is used at start of C++-mangled symbol names. 14 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/patches/modpagespeed/pthread_nonrecursive_np.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/kernel/thread/pthread_rw_lock.cc 2 | +++ b/pagespeed/kernel/thread/pthread_rw_lock.cc 3 | @@ -31,7 +31,7 @@ 4 | // 5 | // Other OS's (FreeBSD, Darwin, OpenSolaris) documentation suggests 6 | // that they prefer writers by default. 7 | -#ifdef linux 8 | +#if defined(linux) && defined(__GLIBC__) 9 | pthread_rwlockattr_setkind_np(&attr_, 10 | PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 11 | #endif 12 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/patches/modpagespeed/pthread_nonrecursive_np.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/kernel/thread/pthread_rw_lock.cc 2 | +++ b/pagespeed/kernel/thread/pthread_rw_lock.cc 3 | @@ -31,7 +31,7 @@ 4 | // 5 | // Other OS's (FreeBSD, Darwin, OpenSolaris) documentation suggests 6 | // that they prefer writers by default. 7 | -#ifdef linux 8 | +#if defined(linux) && defined(__GLIBC__) 9 | pthread_rwlockattr_setkind_np(&attr_, 10 | PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 11 | #endif 12 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/patches/modpagespeed/pthread_nonrecursive_np.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/kernel/thread/pthread_rw_lock.cc 2 | +++ b/pagespeed/kernel/thread/pthread_rw_lock.cc 3 | @@ -31,7 +31,7 @@ 4 | // 5 | // Other OS's (FreeBSD, Darwin, OpenSolaris) documentation suggests 6 | // that they prefer writers by default. 7 | -#ifdef linux 8 | +#if defined(linux) && defined(__GLIBC__) 9 | pthread_rwlockattr_setkind_np(&attr_, 10 | PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 11 | #endif 12 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/patches/modpagespeed/pthread_nonrecursive_np.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/kernel/thread/pthread_rw_lock.cc 2 | +++ b/pagespeed/kernel/thread/pthread_rw_lock.cc 3 | @@ -31,7 +31,7 @@ 4 | // 5 | // Other OS's (FreeBSD, Darwin, OpenSolaris) documentation suggests 6 | // that they prefer writers by default. 7 | -#ifdef linux 8 | +#if defined(linux) && defined(__GLIBC__) 9 | pthread_rwlockattr_setkind_np(&attr_, 10 | PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); 11 | #endif 12 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Apache ngx_pagespeed 2 | 3 | Copyright 2018 The Apache Software Foundation 4 | 5 | This product includes software developed at 6 | - The Apache Software Foundation (http://www.apache.org/). 7 | - Google Inc. 8 | 9 | Codebase originally donated by Google Inc: 10 | 11 | Copyright (C) 2010-2017 Google Inc. 12 | 13 | Licensed under the Apache License, Version 2.0 (the "License"); 14 | you may not use this file except in compliance with the License. 15 | You may obtain a copy of the License at 16 | 17 | http://www.apache.org/licenses/LICENSE-2.0 18 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | user nginx; 3 | worker_processes 1; 4 | 5 | error_log /var/log/nginx/error.log warn; 6 | pid /var/run/nginx.pid; 7 | 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | 14 | http { 15 | include /etc/nginx/mime.types; 16 | default_type application/octet-stream; 17 | 18 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 | '$status $body_bytes_sent "$http_referer" ' 20 | '"$http_user_agent" "$http_x_forwarded_for"'; 21 | 22 | access_log /var/log/nginx/access.log main; 23 | 24 | sendfile on; 25 | #tcp_nopush on; 26 | 27 | keepalive_timeout 65; 28 | 29 | #gzip on; 30 | 31 | include /etc/nginx/conf.d/*.conf; 32 | } 33 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | user nginx; 3 | worker_processes 1; 4 | 5 | error_log /var/log/nginx/error.log warn; 6 | pid /var/run/nginx.pid; 7 | 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | 14 | http { 15 | include /etc/nginx/mime.types; 16 | default_type application/octet-stream; 17 | 18 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 | '$status $body_bytes_sent "$http_referer" ' 20 | '"$http_user_agent" "$http_x_forwarded_for"'; 21 | 22 | access_log /var/log/nginx/access.log main; 23 | 24 | sendfile on; 25 | #tcp_nopush on; 26 | 27 | keepalive_timeout 65; 28 | 29 | #gzip on; 30 | 31 | include /etc/nginx/conf.d/*.conf; 32 | } 33 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | user nginx; 3 | worker_processes 1; 4 | 5 | error_log /var/log/nginx/error.log warn; 6 | pid /var/run/nginx.pid; 7 | 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | 14 | http { 15 | include /etc/nginx/mime.types; 16 | default_type application/octet-stream; 17 | 18 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 | '$status $body_bytes_sent "$http_referer" ' 20 | '"$http_user_agent" "$http_x_forwarded_for"'; 21 | 22 | access_log /var/log/nginx/access.log main; 23 | 24 | sendfile on; 25 | #tcp_nopush on; 26 | 27 | keepalive_timeout 65; 28 | 29 | #gzip on; 30 | 31 | include /etc/nginx/conf.d/*.conf; 32 | } 33 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | user nginx; 3 | worker_processes 1; 4 | 5 | error_log /var/log/nginx/error.log warn; 6 | pid /var/run/nginx.pid; 7 | 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | 14 | http { 15 | include /etc/nginx/mime.types; 16 | default_type application/octet-stream; 17 | 18 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 | '$status $body_bytes_sent "$http_referer" ' 20 | '"$http_user_agent" "$http_x_forwarded_for"'; 21 | 22 | access_log /var/log/nginx/access.log main; 23 | 24 | sendfile on; 25 | #tcp_nopush on; 26 | 27 | keepalive_timeout 65; 28 | 29 | #gzip on; 30 | 31 | include /etc/nginx/conf.d/*.conf; 32 | } 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "testing-dependencies/mod_pagespeed"] 2 | path = testing-dependencies/mod_pagespeed 3 | url = https://github.com/apache/incubator-pagespeed-mod.git 4 | [submodule "testing-dependencies/ngx_cache_purge"] 5 | path = testing-dependencies/ngx_cache_purge 6 | url = https://github.com/FRiCKLE/ngx_cache_purge.git 7 | [submodule "testing-dependencies/nginx"] 8 | path = testing-dependencies/nginx 9 | url = https://github.com/nginx/nginx.git 10 | [submodule "testing-dependencies/set-misc-nginx-module"] 11 | path = testing-dependencies/set-misc-nginx-module 12 | url = https://github.com/openresty/set-misc-nginx-module 13 | [submodule "testing-dependencies/ngx_devel_kit"] 14 | path = testing-dependencies/ngx_devel_kit 15 | url = https://github.com/simpl/ngx_devel_kit 16 | [submodule "testing-dependencies/headers-more-nginx-module"] 17 | path = testing-dependencies/headers-more-nginx-module 18 | url = https://github.com/openresty/headers-more-nginx-module 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c++ 2 | env: 3 | global: 4 | - MAKEFLAGS=-j3 5 | # By default travis loads submodules serially, but we can load them in parallel 6 | # if we install an updated git and use --jobs. Some timing numbers: 7 | # serial: 257s 8 | # jobs=4: 182s (29s to install new git, 153s to run the downloads) 9 | # jobs=8: 179s (29s to install new git, 150s to run the downloads) 10 | # We can't use --depth=1, though, because github doesn't have 11 | # allowReachableSHA1InWant set. 12 | # 13 | # TODO(jefftk): once we're running on a server with git 2.8 or later we can have 14 | # --jobs without installing a new git. 15 | git: 16 | submodules: false 17 | before_install: 18 | - sudo add-apt-repository --yes ppa:git-core/ppa 19 | - sudo apt-get update 20 | - sudo apt-get install git 21 | - git submodule update --init --recursive --jobs=8 22 | install: 23 | scripts/build_ngx_pagespeed.sh --devel --assume-yes 24 | script: 25 | test/run_tests.sh $PWD/testing-dependencies/mod_pagespeed/ \ 26 | $PWD/nginx/sbin/nginx 27 | dist: trusty 28 | sudo: required 29 | compiler: 30 | - gcc 31 | notifications: 32 | email: 33 | - pagespeed-ci@googlegroups.com 34 | -------------------------------------------------------------------------------- /config.make: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | # Since nginx build system doesn't normally do C++, there is no CXXFLAGS for us 19 | # to touch, and compilers are understandably unhappy with --std=c++11 on C 20 | # files. Hence, we hack the makefile to add it for just our sources. 21 | 22 | for ps_src_file in $PS_NGX_SRCS; do 23 | ps_obj_file="$NGX_OBJS/addon/src/`basename $ps_src_file .cc`.o" 24 | echo "$ps_obj_file : CFLAGS += --std=c++11" >> $NGX_MAKEFILE 25 | done 26 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/patches/modpagespeed/automatic_makefile.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/automatic/Makefile 2 | +++ b/pagespeed/automatic/Makefile 3 | @@ -146,8 +146,6 @@ 4 | pagespeed/libpagespeed_thread.a \ 5 | pagespeed/libpthread_system.a \ 6 | pagespeed/libutil.a \ 7 | - third_party/apr/libapr.a \ 8 | - third_party/aprutil/libaprutil.a \ 9 | third_party/base64/libbase64.a \ 10 | third_party/chromium/src/base/third_party/dynamic_annotations/libdynamic_annotations.a \ 11 | third_party/css_parser/libcss_parser.a \ 12 | @@ -163,18 +161,11 @@ 13 | third_party/grpc/libgrpc_core.a \ 14 | third_party/grpc/libgrpc_cpp.a \ 15 | third_party/hiredis/libhiredis.a \ 16 | - third_party/icu/libicudata.a \ 17 | - third_party/icu/libicuuc.a \ 18 | third_party/jsoncpp/libjsoncpp.a \ 19 | - third_party/libjpeg_turbo/libjpeg.a \ 20 | - third_party/libjpeg_turbo/src/libjpeg_turbo.a \ 21 | - third_party/libpng/libpng.a \ 22 | third_party/optipng/libopngreduc.a \ 23 | third_party/protobuf/libprotobuf_full_do_not_use.a \ 24 | third_party/re2/libre2.a \ 25 | - third_party/serf/libopenssl.a \ 26 | third_party/serf/libserf.a \ 27 | - third_party/zlib/libzlib.a \ 28 | url/liburl_lib.a 29 | 30 | # The 'gclient' build flow uses 'xcodebuild' on Mac and 'make' on Linux. 31 | 32 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/patches/modpagespeed/automatic_makefile.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/automatic/Makefile 2 | +++ b/pagespeed/automatic/Makefile 3 | @@ -146,8 +146,6 @@ 4 | pagespeed/libpagespeed_thread.a \ 5 | pagespeed/libpthread_system.a \ 6 | pagespeed/libutil.a \ 7 | - third_party/apr/libapr.a \ 8 | - third_party/aprutil/libaprutil.a \ 9 | third_party/base64/libbase64.a \ 10 | third_party/chromium/src/base/third_party/dynamic_annotations/libdynamic_annotations.a \ 11 | third_party/css_parser/libcss_parser.a \ 12 | @@ -163,18 +161,11 @@ 13 | third_party/grpc/libgrpc_core.a \ 14 | third_party/grpc/libgrpc_cpp.a \ 15 | third_party/hiredis/libhiredis.a \ 16 | - third_party/icu/libicudata.a \ 17 | - third_party/icu/libicuuc.a \ 18 | third_party/jsoncpp/libjsoncpp.a \ 19 | - third_party/libjpeg_turbo/libjpeg.a \ 20 | - third_party/libjpeg_turbo/src/libjpeg_turbo.a \ 21 | - third_party/libpng/libpng.a \ 22 | third_party/optipng/libopngreduc.a \ 23 | third_party/protobuf/libprotobuf_full_do_not_use.a \ 24 | third_party/re2/libre2.a \ 25 | - third_party/serf/libopenssl.a \ 26 | third_party/serf/libserf.a \ 27 | - third_party/zlib/libzlib.a \ 28 | url/liburl_lib.a 29 | 30 | # The 'gclient' build flow uses 'xcodebuild' on Mac and 'make' on Linux. 31 | 32 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/patches/modpagespeed/automatic_makefile.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/automatic/Makefile 2 | +++ b/pagespeed/automatic/Makefile 3 | @@ -146,8 +146,6 @@ 4 | pagespeed/libpagespeed_thread.a \ 5 | pagespeed/libpthread_system.a \ 6 | pagespeed/libutil.a \ 7 | - third_party/apr/libapr.a \ 8 | - third_party/aprutil/libaprutil.a \ 9 | third_party/base64/libbase64.a \ 10 | third_party/chromium/src/base/third_party/dynamic_annotations/libdynamic_annotations.a \ 11 | third_party/css_parser/libcss_parser.a \ 12 | @@ -163,18 +161,11 @@ 13 | third_party/grpc/libgrpc_core.a \ 14 | third_party/grpc/libgrpc_cpp.a \ 15 | third_party/hiredis/libhiredis.a \ 16 | - third_party/icu/libicudata.a \ 17 | - third_party/icu/libicuuc.a \ 18 | third_party/jsoncpp/libjsoncpp.a \ 19 | - third_party/libjpeg_turbo/libjpeg.a \ 20 | - third_party/libjpeg_turbo/src/libjpeg_turbo.a \ 21 | - third_party/libpng/libpng.a \ 22 | third_party/optipng/libopngreduc.a \ 23 | third_party/protobuf/libprotobuf_full_do_not_use.a \ 24 | third_party/re2/libre2.a \ 25 | - third_party/serf/libopenssl.a \ 26 | third_party/serf/libserf.a \ 27 | - third_party/zlib/libzlib.a \ 28 | url/liburl_lib.a 29 | 30 | # The 'gclient' build flow uses 'xcodebuild' on Mac and 'make' on Linux. 31 | 32 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/patches/modpagespeed/automatic_makefile.patch: -------------------------------------------------------------------------------- 1 | --- a/pagespeed/automatic/Makefile 2 | +++ b/pagespeed/automatic/Makefile 3 | @@ -146,8 +146,6 @@ 4 | pagespeed/libpagespeed_thread.a \ 5 | pagespeed/libpthread_system.a \ 6 | pagespeed/libutil.a \ 7 | - third_party/apr/libapr.a \ 8 | - third_party/aprutil/libaprutil.a \ 9 | third_party/base64/libbase64.a \ 10 | third_party/chromium/src/base/third_party/dynamic_annotations/libdynamic_annotations.a \ 11 | third_party/css_parser/libcss_parser.a \ 12 | @@ -163,18 +161,11 @@ 13 | third_party/grpc/libgrpc_core.a \ 14 | third_party/grpc/libgrpc_cpp.a \ 15 | third_party/hiredis/libhiredis.a \ 16 | - third_party/icu/libicudata.a \ 17 | - third_party/icu/libicuuc.a \ 18 | third_party/jsoncpp/libjsoncpp.a \ 19 | - third_party/libjpeg_turbo/libjpeg.a \ 20 | - third_party/libjpeg_turbo/src/libjpeg_turbo.a \ 21 | - third_party/libpng/libpng.a \ 22 | third_party/optipng/libopngreduc.a \ 23 | third_party/protobuf/libprotobuf_full_do_not_use.a \ 24 | third_party/re2/libre2.a \ 25 | - third_party/serf/libopenssl.a \ 26 | third_party/serf/libserf.a \ 27 | - third_party/zlib/libzlib.a \ 28 | url/liburl_lib.a 29 | 30 | # The 'gclient' build flow uses 'xcodebuild' on Mac and 'make' on Linux. 31 | 32 | -------------------------------------------------------------------------------- /scripts/format_binary_url.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | 19 | set -e 20 | set -u 21 | 22 | if [ $# -ne 1 ]; then 23 | echo "Usage: $(basename $0) " >&2 24 | exit 1 25 | fi 26 | 27 | url_file=$1 28 | 29 | if [ ! -e "$url_file" ]; then 30 | echo "Url file '$url_file' missing!" >&2 31 | fi 32 | 33 | # The size names must match install/build_psol.sh in mod_pagespeed 34 | if [ "$(uname -m)" = x86_64 ]; then 35 | bit_size_name=x64 36 | else 37 | bit_size_name=ia32 38 | fi 39 | 40 | sed -e 's/$BIT_SIZE_NAME/'$bit_size_name'/g' $url_file 41 | -------------------------------------------------------------------------------- /scripts/rebuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | 19 | # Usage: scripts/rebuild.sh 20 | # 21 | # After building with "scripts/build_ngx_pagespeed.sh --devel", if you make 22 | # changes to ngx_pagespeed you'll need to rebuild it. The underlying commands 23 | # aren't complicated, but it's faster to work if it's automated. 24 | 25 | set -e # exit script if any command returns an error 26 | set -u # exit the script if any variable is uninitialized 27 | 28 | this_dir="$(dirname $0)" 29 | cd "$this_dir/.." 30 | nps_dir="$PWD" 31 | 32 | cd "$nps_dir/testing-dependencies/mod_pagespeed/devel" 33 | make apache_debug_psol 34 | 35 | cd "$nps_dir/testing-dependencies/nginx/" 36 | make 37 | make install 38 | -------------------------------------------------------------------------------- /src/ngx_list_iterator.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | #include "ngx_list_iterator.h" 23 | 24 | namespace net_instaweb { 25 | 26 | NgxListIterator::NgxListIterator(ngx_list_part_t* part) : 27 | part_(part), 28 | index_within_part_(0) {} 29 | 30 | ngx_table_elt_t* NgxListIterator::Next() { 31 | if (index_within_part_ >= part_->nelts) { 32 | if (part_->next == NULL) { 33 | return NULL; 34 | } 35 | part_ = part_->next; 36 | index_within_part_ = 0; 37 | } 38 | ngx_table_elt_t* elts = static_cast(part_->elts); 39 | return &elts[index_within_part_++]; // Intentional post-increment. 40 | } 41 | 42 | } // namespace net_instaweb 43 | -------------------------------------------------------------------------------- /src/ngx_list_iterator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | // 22 | // Simplifies iteration over nginx lists. 23 | // 24 | // 25 | 26 | #ifndef NGX_LIST_ITERATOR_H_ 27 | #define NGX_LIST_ITERATOR_H_ 28 | 29 | extern "C" { 30 | #include 31 | } 32 | 33 | #include "base/basictypes.h" 34 | 35 | namespace net_instaweb { 36 | 37 | class NgxListIterator { 38 | public: 39 | explicit NgxListIterator(ngx_list_part_t* part); 40 | 41 | // Return the next element of the list if there is one, NULL otherwise. 42 | ngx_table_elt_t* Next(); 43 | 44 | private: 45 | ngx_list_part_t* part_; 46 | ngx_uint_t index_within_part_; 47 | 48 | DISALLOW_COPY_AND_ASSIGN(NgxListIterator); 49 | }; 50 | 51 | } // namespace net_instaweb 52 | 53 | #endif // NGX_LIST_ITERATOR_H_ 54 | -------------------------------------------------------------------------------- /scripts/pagespeed_libraries_generator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | 19 | # Converts pagespeed_libraries.conf from Apache-format to Nginx-format, 20 | # supporting the canonicalize_javascript_libraries filter. 21 | # Inspired by https://github.com/apache/incubator-pagespeed-ngx/issues/532 22 | # 23 | # Usage: 24 | # scripts/pagespeed_libraries_generator.sh > pagespeed_libraries.conf 25 | # 26 | # Then have nginx include that configuration file and enable the filter 27 | # canonicalize_javascript_libraries. 28 | 29 | URL="https://github.com/apache/incubator-pagespeed-mod/raw/master/" 30 | URL+="net/instaweb/genfiles/conf/pagespeed_libraries.conf" 31 | curl -L -s -S "$URL" \ 32 | | grep ModPagespeedLibrary \ 33 | | while read library size hash url ; do 34 | echo " pagespeed Library $size $hash $url;" 35 | done 36 | -------------------------------------------------------------------------------- /src/log_message_handler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | #ifndef LOG_MESSAGE_HANDLER_H_ 23 | #define LOG_MESSAGE_HANDLER_H_ 24 | 25 | extern "C" { 26 | #include 27 | #include 28 | #include 29 | #include 30 | } 31 | 32 | namespace net_instaweb { 33 | 34 | namespace log_message_handler { 35 | 36 | // Install a log message handler that routes LOG() messages to the 37 | // server error log. Should be called once at startup. If server blocks define 38 | // their own logging files you would expect that LOG() messages would be routed 39 | // appropriately, but because logging is all done with global variables this 40 | // isn't possible. 41 | void Install(ngx_log_t* log_in); 42 | 43 | } // namespace log_message_handler 44 | 45 | } // namespace net_instaweb 46 | 47 | #endif // LOG_MESSAGE_HANDLER_H_ 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![ngx_pagespeed](https://user-images.githubusercontent.com/6751650/73116078-338a9180-3f0f-11ea-8fdf-8c99cb4bec7f.png) 2 | 3 | [![Build Status](https://travis-ci.org/apache/incubator-pagespeed-ngx.svg?branch=master)](https://travis-ci.org/apache/incubator-pagespeed-ngx) 4 | 5 | ngx_pagespeed speeds up your site and reduces page load time by automatically 6 | applying web performance best practices to pages and associated assets (CSS, 7 | JavaScript, images) without requiring you to modify your existing content or 8 | workflow. Features include: 9 | 10 | - Image optimization: stripping meta-data, dynamic resizing, recompression 11 | - CSS & JavaScript minification, concatenation, inlining, and outlining 12 | - Small resource inlining 13 | - Deferring image and JavaScript loading 14 | - HTML rewriting 15 | - Cache lifetime extension 16 | - and 17 | [more](https://developers.google.com/speed/docs/mod_pagespeed/config_filters) 18 | 19 | To see ngx_pagespeed in action, with example pages for each of the 20 | optimizations, see our demonstration site. 21 | 22 | ## How to build 23 | 24 | Follow the steps on build 26 | ngx_pagespeed from source. 27 | 28 | ## How to use 29 | 30 | Follow the steps on PageSpeed 32 | configuration. 33 | 34 | For feedback, questions, and to follow 35 | the progress of the project: 36 | 37 | - [ngx-pagespeed-discuss mailing 38 | list](https://groups.google.com/forum/#!forum/ngx-pagespeed-discuss) 39 | - [ngx-pagespeed-announce mailing 40 | list](https://groups.google.com/forum/#!forum/ngx-pagespeed-announce) 41 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/conf/nginx.vh.default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #charset koi8-r; 6 | #access_log /var/log/nginx/host.access.log main; 7 | 8 | location / { 9 | root /usr/share/nginx/html; 10 | index index.html index.htm; 11 | } 12 | 13 | #error_page 404 /404.html; 14 | 15 | # redirect server error pages to the static page /50x.html 16 | # 17 | error_page 500 502 503 504 /50x.html; 18 | location = /50x.html { 19 | root /usr/share/nginx/html; 20 | } 21 | 22 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 23 | # 24 | #location ~ \.php$ { 25 | # proxy_pass http://127.0.0.1; 26 | #} 27 | 28 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 29 | # 30 | #location ~ \.php$ { 31 | # root html; 32 | # fastcgi_pass 127.0.0.1:9000; 33 | # fastcgi_index index.php; 34 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 35 | # include fastcgi_params; 36 | #} 37 | pagespeed on; 38 | 39 | # Needs to exist and be writable by nginx. Use tmpfs for best performance. 40 | pagespeed FileCachePath /var/cache/ngx_pagespeed; 41 | 42 | # Ensure requests for pagespeed optimized resources go to the pagespeed handler 43 | # and no extraneous headers get set. 44 | location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { 45 | add_header "" ""; 46 | } 47 | location ~ "^/pagespeed_static/" { } 48 | location ~ "^/ngx_pagespeed_beacon$" { } 49 | 50 | # deny access to .htaccess files, if Apache's document root 51 | # concurs with nginx's one 52 | # 53 | #location ~ /\.ht { 54 | # deny all; 55 | #} 56 | } 57 | 58 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/conf/nginx.vh.default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #charset koi8-r; 6 | #access_log /var/log/nginx/host.access.log main; 7 | 8 | location / { 9 | root /usr/share/nginx/html; 10 | index index.html index.htm; 11 | } 12 | 13 | #error_page 404 /404.html; 14 | 15 | # redirect server error pages to the static page /50x.html 16 | # 17 | error_page 500 502 503 504 /50x.html; 18 | location = /50x.html { 19 | root /usr/share/nginx/html; 20 | } 21 | 22 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 23 | # 24 | #location ~ \.php$ { 25 | # proxy_pass http://127.0.0.1; 26 | #} 27 | 28 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 29 | # 30 | #location ~ \.php$ { 31 | # root html; 32 | # fastcgi_pass 127.0.0.1:9000; 33 | # fastcgi_index index.php; 34 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 35 | # include fastcgi_params; 36 | #} 37 | pagespeed on; 38 | 39 | # Needs to exist and be writable by nginx. Use tmpfs for best performance. 40 | pagespeed FileCachePath /var/cache/ngx_pagespeed; 41 | 42 | # Ensure requests for pagespeed optimized resources go to the pagespeed handler 43 | # and no extraneous headers get set. 44 | location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { 45 | add_header "" ""; 46 | } 47 | location ~ "^/pagespeed_static/" { } 48 | location ~ "^/ngx_pagespeed_beacon$" { } 49 | 50 | # deny access to .htaccess files, if Apache's document root 51 | # concurs with nginx's one 52 | # 53 | #location ~ /\.ht { 54 | # deny all; 55 | #} 56 | } 57 | 58 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/conf/nginx.vh.default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #charset koi8-r; 6 | #access_log /var/log/nginx/host.access.log main; 7 | 8 | location / { 9 | root /usr/share/nginx/html; 10 | index index.html index.htm; 11 | } 12 | 13 | #error_page 404 /404.html; 14 | 15 | # redirect server error pages to the static page /50x.html 16 | # 17 | error_page 500 502 503 504 /50x.html; 18 | location = /50x.html { 19 | root /usr/share/nginx/html; 20 | } 21 | 22 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 23 | # 24 | #location ~ \.php$ { 25 | # proxy_pass http://127.0.0.1; 26 | #} 27 | 28 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 29 | # 30 | #location ~ \.php$ { 31 | # root html; 32 | # fastcgi_pass 127.0.0.1:9000; 33 | # fastcgi_index index.php; 34 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 35 | # include fastcgi_params; 36 | #} 37 | pagespeed on; 38 | 39 | # Needs to exist and be writable by nginx. Use tmpfs for best performance. 40 | pagespeed FileCachePath /var/cache/ngx_pagespeed; 41 | 42 | # Ensure requests for pagespeed optimized resources go to the pagespeed handler 43 | # and no extraneous headers get set. 44 | location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { 45 | add_header "" ""; 46 | } 47 | location ~ "^/pagespeed_static/" { } 48 | location ~ "^/ngx_pagespeed_beacon$" { } 49 | 50 | # deny access to .htaccess files, if Apache's document root 51 | # concurs with nginx's one 52 | # 53 | #location ~ /\.ht { 54 | # deny all; 55 | #} 56 | } 57 | 58 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/conf/nginx.vh.default.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #charset koi8-r; 6 | #access_log /var/log/nginx/host.access.log main; 7 | 8 | location / { 9 | root /usr/share/nginx/html; 10 | index index.html index.htm; 11 | } 12 | 13 | #error_page 404 /404.html; 14 | 15 | # redirect server error pages to the static page /50x.html 16 | # 17 | error_page 500 502 503 504 /50x.html; 18 | location = /50x.html { 19 | root /usr/share/nginx/html; 20 | } 21 | 22 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 23 | # 24 | #location ~ \.php$ { 25 | # proxy_pass http://127.0.0.1; 26 | #} 27 | 28 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 29 | # 30 | #location ~ \.php$ { 31 | # root html; 32 | # fastcgi_pass 127.0.0.1:9000; 33 | # fastcgi_index index.php; 34 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 35 | # include fastcgi_params; 36 | #} 37 | pagespeed on; 38 | 39 | # Needs to exist and be writable by nginx. Use tmpfs for best performance. 40 | pagespeed FileCachePath /var/cache/ngx_pagespeed; 41 | 42 | # Ensure requests for pagespeed optimized resources go to the pagespeed handler 43 | # and no extraneous headers get set. 44 | location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { 45 | add_header "" ""; 46 | } 47 | location ~ "^/pagespeed_static/" { } 48 | location ~ "^/ngx_pagespeed_beacon$" { } 49 | 50 | # deny access to .htaccess files, if Apache's document root 51 | # concurs with nginx's one 52 | # 53 | #location ~ /\.ht { 54 | # deny all; 55 | #} 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/ngx_caching_headers.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | #include "ngx_caching_headers.h" 23 | #include "ngx_list_iterator.h" 24 | 25 | #include "ngx_pagespeed.h" 26 | 27 | namespace net_instaweb { 28 | 29 | bool NgxCachingHeaders::Lookup(const StringPiece& key, 30 | StringPieceVector* values) { 31 | ngx_table_elt_t* header; 32 | NgxListIterator it(&(request_->headers_out.headers.part)); 33 | while ((header = it.Next()) != NULL) { 34 | if (header->hash != 0 && key == str_to_string_piece(header->key)) { 35 | // This will be called multiple times if there are multiple headers with 36 | // this name. Each time it will append to values. 37 | SplitStringPieceToVector(str_to_string_piece(header->value), ",", values, 38 | true /* omit empty strings */); 39 | } 40 | } 41 | 42 | if (values->size() == 0) { 43 | // No header found with this name. 44 | return false; 45 | } 46 | 47 | for (int i = 0, n = values->size(); i < n; ++i) { 48 | TrimWhitespace(&((*values)[i])); 49 | } 50 | 51 | return true; 52 | } 53 | 54 | } // namespace net_instaweb 55 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/patches/modpagespeed/stack_trace_posix.patch: -------------------------------------------------------------------------------- 1 | --- a/third_party/chromium/src/base/debug/stack_trace_posix.cc 2 | +++ b/third_party/chromium/src/base/debug/stack_trace_posix.cc 3 | @@ -5,7 +5,9 @@ 4 | #include "base/debug/stack_trace.h" 5 | 6 | #include 7 | +#if defined(HAVE_BACKTRACE) 8 | #include 9 | +#endif 10 | #include 11 | #include 12 | #include 13 | @@ -64,7 +66,7 @@ 14 | // Note: code in this function is NOT async-signal safe (std::string uses 15 | // malloc internally). 16 | 17 | -#if defined(__GLIBCXX__) 18 | +#if defined(__GLIBCXX__) && defined(HAVE_BACKTRACE) 19 | 20 | std::string::size_type search_from = 0; 21 | while (search_from < text->size()) { 22 | @@ -145,7 +147,7 @@ 23 | 24 | handler->HandleOutput("\n"); 25 | } 26 | -#else 27 | +#elif defined(HAVE_BACKTRACE) 28 | bool printed = false; 29 | 30 | // Below part is async-signal unsafe (uses malloc), so execute it only 31 | @@ -469,23 +471,31 @@ 32 | StackTrace::StackTrace() { 33 | // NOTE: This code MUST be async-signal safe (it's used by in-process 34 | // stack dumping signal handler). NO malloc or stdio is allowed here. 35 | - 36 | +#if defined(HAVE_BACKTRACE) 37 | // Though the backtrace API man page does not list any possible negative 38 | // return values, we take no chance. 39 | count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); 40 | +#else 41 | + count_ = 0; 42 | +#endif 43 | } 44 | 45 | void StackTrace::Print() const { 46 | // NOTE: This code MUST be async-signal safe (it's used by in-process 47 | // stack dumping signal handler). NO malloc or stdio is allowed here. 48 | - 49 | +#if defined(HAVE_BACKTRACE) 50 | PrintBacktraceOutputHandler handler; 51 | ProcessBacktrace(trace_, count_, &handler); 52 | +#endif 53 | } 54 | 55 | void StackTrace::OutputToStream(std::ostream* os) const { 56 | +#if !defined(HAVE_BACKTRACE) 57 | +(*os) << "(stack trace not supported)\n"; 58 | +#else 59 | StreamBacktraceOutputHandler handler(os); 60 | ProcessBacktrace(trace_, count_, &handler); 61 | +#endif 62 | } 63 | 64 | namespace internal { 65 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/patches/modpagespeed/stack_trace_posix.patch: -------------------------------------------------------------------------------- 1 | --- a/third_party/chromium/src/base/debug/stack_trace_posix.cc 2 | +++ b/third_party/chromium/src/base/debug/stack_trace_posix.cc 3 | @@ -5,7 +5,9 @@ 4 | #include "base/debug/stack_trace.h" 5 | 6 | #include 7 | +#if defined(HAVE_BACKTRACE) 8 | #include 9 | +#endif 10 | #include 11 | #include 12 | #include 13 | @@ -64,7 +66,7 @@ 14 | // Note: code in this function is NOT async-signal safe (std::string uses 15 | // malloc internally). 16 | 17 | -#if defined(__GLIBCXX__) 18 | +#if defined(__GLIBCXX__) && defined(HAVE_BACKTRACE) 19 | 20 | std::string::size_type search_from = 0; 21 | while (search_from < text->size()) { 22 | @@ -145,7 +147,7 @@ 23 | 24 | handler->HandleOutput("\n"); 25 | } 26 | -#else 27 | +#elif defined(HAVE_BACKTRACE) 28 | bool printed = false; 29 | 30 | // Below part is async-signal unsafe (uses malloc), so execute it only 31 | @@ -469,23 +471,31 @@ 32 | StackTrace::StackTrace() { 33 | // NOTE: This code MUST be async-signal safe (it's used by in-process 34 | // stack dumping signal handler). NO malloc or stdio is allowed here. 35 | - 36 | +#if defined(HAVE_BACKTRACE) 37 | // Though the backtrace API man page does not list any possible negative 38 | // return values, we take no chance. 39 | count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); 40 | +#else 41 | + count_ = 0; 42 | +#endif 43 | } 44 | 45 | void StackTrace::Print() const { 46 | // NOTE: This code MUST be async-signal safe (it's used by in-process 47 | // stack dumping signal handler). NO malloc or stdio is allowed here. 48 | - 49 | +#if defined(HAVE_BACKTRACE) 50 | PrintBacktraceOutputHandler handler; 51 | ProcessBacktrace(trace_, count_, &handler); 52 | +#endif 53 | } 54 | 55 | void StackTrace::OutputToStream(std::ostream* os) const { 56 | +#if !defined(HAVE_BACKTRACE) 57 | +(*os) << "(stack trace not supported)\n"; 58 | +#else 59 | StreamBacktraceOutputHandler handler(os); 60 | ProcessBacktrace(trace_, count_, &handler); 61 | +#endif 62 | } 63 | 64 | namespace internal { 65 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/patches/modpagespeed/stack_trace_posix.patch: -------------------------------------------------------------------------------- 1 | --- a/third_party/chromium/src/base/debug/stack_trace_posix.cc 2 | +++ b/third_party/chromium/src/base/debug/stack_trace_posix.cc 3 | @@ -5,7 +5,9 @@ 4 | #include "base/debug/stack_trace.h" 5 | 6 | #include 7 | +#if defined(HAVE_BACKTRACE) 8 | #include 9 | +#endif 10 | #include 11 | #include 12 | #include 13 | @@ -64,7 +66,7 @@ 14 | // Note: code in this function is NOT async-signal safe (std::string uses 15 | // malloc internally). 16 | 17 | -#if defined(__GLIBCXX__) 18 | +#if defined(__GLIBCXX__) && defined(HAVE_BACKTRACE) 19 | 20 | std::string::size_type search_from = 0; 21 | while (search_from < text->size()) { 22 | @@ -145,7 +147,7 @@ 23 | 24 | handler->HandleOutput("\n"); 25 | } 26 | -#else 27 | +#elif defined(HAVE_BACKTRACE) 28 | bool printed = false; 29 | 30 | // Below part is async-signal unsafe (uses malloc), so execute it only 31 | @@ -469,23 +471,31 @@ 32 | StackTrace::StackTrace() { 33 | // NOTE: This code MUST be async-signal safe (it's used by in-process 34 | // stack dumping signal handler). NO malloc or stdio is allowed here. 35 | - 36 | +#if defined(HAVE_BACKTRACE) 37 | // Though the backtrace API man page does not list any possible negative 38 | // return values, we take no chance. 39 | count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); 40 | +#else 41 | + count_ = 0; 42 | +#endif 43 | } 44 | 45 | void StackTrace::Print() const { 46 | // NOTE: This code MUST be async-signal safe (it's used by in-process 47 | // stack dumping signal handler). NO malloc or stdio is allowed here. 48 | - 49 | +#if defined(HAVE_BACKTRACE) 50 | PrintBacktraceOutputHandler handler; 51 | ProcessBacktrace(trace_, count_, &handler); 52 | +#endif 53 | } 54 | 55 | void StackTrace::OutputToStream(std::ostream* os) const { 56 | +#if !defined(HAVE_BACKTRACE) 57 | +(*os) << "(stack trace not supported)\n"; 58 | +#else 59 | StreamBacktraceOutputHandler handler(os); 60 | ProcessBacktrace(trace_, count_, &handler); 61 | +#endif 62 | } 63 | 64 | namespace internal { 65 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/patches/modpagespeed/stack_trace_posix.patch: -------------------------------------------------------------------------------- 1 | --- a/third_party/chromium/src/base/debug/stack_trace_posix.cc 2 | +++ b/third_party/chromium/src/base/debug/stack_trace_posix.cc 3 | @@ -5,7 +5,9 @@ 4 | #include "base/debug/stack_trace.h" 5 | 6 | #include 7 | +#if defined(HAVE_BACKTRACE) 8 | #include 9 | +#endif 10 | #include 11 | #include 12 | #include 13 | @@ -64,7 +66,7 @@ 14 | // Note: code in this function is NOT async-signal safe (std::string uses 15 | // malloc internally). 16 | 17 | -#if defined(__GLIBCXX__) 18 | +#if defined(__GLIBCXX__) && defined(HAVE_BACKTRACE) 19 | 20 | std::string::size_type search_from = 0; 21 | while (search_from < text->size()) { 22 | @@ -145,7 +147,7 @@ 23 | 24 | handler->HandleOutput("\n"); 25 | } 26 | -#else 27 | +#elif defined(HAVE_BACKTRACE) 28 | bool printed = false; 29 | 30 | // Below part is async-signal unsafe (uses malloc), so execute it only 31 | @@ -469,23 +471,31 @@ 32 | StackTrace::StackTrace() { 33 | // NOTE: This code MUST be async-signal safe (it's used by in-process 34 | // stack dumping signal handler). NO malloc or stdio is allowed here. 35 | - 36 | +#if defined(HAVE_BACKTRACE) 37 | // Though the backtrace API man page does not list any possible negative 38 | // return values, we take no chance. 39 | count_ = std::max(backtrace(trace_, arraysize(trace_)), 0); 40 | +#else 41 | + count_ = 0; 42 | +#endif 43 | } 44 | 45 | void StackTrace::Print() const { 46 | // NOTE: This code MUST be async-signal safe (it's used by in-process 47 | // stack dumping signal handler). NO malloc or stdio is allowed here. 48 | - 49 | +#if defined(HAVE_BACKTRACE) 50 | PrintBacktraceOutputHandler handler; 51 | ProcessBacktrace(trace_, count_, &handler); 52 | +#endif 53 | } 54 | 55 | void StackTrace::OutputToStream(std::ostream* os) const { 56 | +#if !defined(HAVE_BACKTRACE) 57 | +(*os) << "(stack trace not supported)\n"; 58 | +#else 59 | StreamBacktraceOutputHandler handler(os); 60 | ProcessBacktrace(trace_, count_, &handler); 61 | +#endif 62 | } 63 | 64 | namespace internal { 65 | -------------------------------------------------------------------------------- /src/ngx_caching_headers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | #ifndef NGX_CACHING_HEADERS_H_ 23 | #define NGX_CACHING_HEADERS_H_ 24 | 25 | extern "C" { 26 | #include 27 | } 28 | 29 | #include "pagespeed/kernel/base/basictypes.h" 30 | #include "pagespeed/kernel/http/caching_headers.h" 31 | 32 | namespace net_instaweb { 33 | 34 | // Based off of ApacheCachingHeaders in net/instaweb/apache/header_util.cc 35 | // Needed so ps_header_filter can call GenerateDisabledCacheControl(). 36 | class NgxCachingHeaders : public CachingHeaders { 37 | public: 38 | explicit NgxCachingHeaders(ngx_http_request_t* request) 39 | : CachingHeaders(request->headers_out.status), 40 | request_(request) { 41 | } 42 | 43 | virtual bool Lookup(const StringPiece& key, StringPieceVector* values); 44 | 45 | virtual bool IsLikelyStaticResourceType() const { 46 | DCHECK(false); // not called in our use-case. 47 | return false; 48 | } 49 | 50 | virtual bool IsCacheableResourceStatusCode() const { 51 | DCHECK(false); // not called in our use-case. 52 | return false; 53 | } 54 | 55 | private: 56 | ngx_http_request_t* request_; 57 | 58 | DISALLOW_COPY_AND_ASSIGN(NgxCachingHeaders); 59 | }; 60 | 61 | } // namespace net_instaweb 62 | 63 | #endif // NGX_CACHING_HEADERS_H_ 64 | -------------------------------------------------------------------------------- /src/ngx_message_handler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | 23 | #ifndef NGX_MESSAGE_HANDLER_H_ 24 | #define NGX_MESSAGE_HANDLER_H_ 25 | 26 | extern "C" { 27 | #include 28 | #if (NGX_THREADS) 29 | #include 30 | #endif 31 | #include 32 | #include 33 | } 34 | 35 | #include 36 | 37 | #include "pagespeed/kernel/base/basictypes.h" 38 | #include "pagespeed/kernel/base/message_handler.h" 39 | #include "pagespeed/kernel/base/string.h" 40 | #include "pagespeed/kernel/base/string_util.h" 41 | #include "pagespeed/system/system_message_handler.h" 42 | 43 | namespace net_instaweb { 44 | 45 | class AbstractMutex; 46 | class Timer; 47 | 48 | // Implementation of a message handler that uses ngx_log_error() 49 | // logging to emit messages, with a fallback to GoogleMessageHandler 50 | class NgxMessageHandler : public SystemMessageHandler { 51 | public: 52 | explicit NgxMessageHandler(Timer* timer, AbstractMutex* mutex); 53 | 54 | // Installs a signal handler for common crash signals that tries to print 55 | // out a backtrace. 56 | static void InstallCrashHandler(ngx_log_t* log); 57 | 58 | void set_log(ngx_log_t* log) { log_ = log; } 59 | ngx_log_t* log() { return log_; } 60 | 61 | protected: 62 | virtual void MessageSImpl(MessageType type, const GoogleString& message); 63 | 64 | virtual void FileMessageSImpl(MessageType type, const char* file, 65 | int line, const GoogleString& message); 66 | 67 | private: 68 | ngx_uint_t GetNgxLogLevel(MessageType type); 69 | ngx_log_t* log_; 70 | 71 | DISALLOW_COPY_AND_ASSIGN(NgxMessageHandler); 72 | }; 73 | 74 | } // namespace net_instaweb 75 | 76 | #endif // NGX_MESSAGE_HANDLER_H_ 77 | -------------------------------------------------------------------------------- /src/ngx_server_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | // Manage pagespeed state across requests. Compare to ApacheResourceManager. 23 | 24 | #ifndef NGX_SERVER_CONTEXT_H_ 25 | #define NGX_SERVER_CONTEXT_H_ 26 | 27 | #include "ngx_message_handler.h" 28 | #include "pagespeed/system/system_server_context.h" 29 | 30 | extern "C" { 31 | #include 32 | } 33 | 34 | namespace net_instaweb { 35 | 36 | class NgxRewriteDriverFactory; 37 | class NgxRewriteOptions; 38 | class SystemRequestContext; 39 | 40 | class NgxServerContext : public SystemServerContext { 41 | public: 42 | NgxServerContext( 43 | NgxRewriteDriverFactory* factory, StringPiece hostname, int port); 44 | virtual ~NgxServerContext(); 45 | 46 | // We don't allow ProxyFetch to fetch HTML via MapProxyDomain. We will call 47 | // set_trusted_input() on any ProxyFetches we use to transform internal HTML. 48 | virtual bool ProxiesHtml() const { return false; } 49 | 50 | // Call only when you need an NgxRewriteOptions. If you don't need 51 | // nginx-specific behavior, call global_options() instead which doesn't 52 | // downcast. 53 | NgxRewriteOptions* config(); 54 | 55 | NgxRewriteDriverFactory* ngx_rewrite_driver_factory() { return ngx_factory_; } 56 | SystemRequestContext* NewRequestContext(ngx_http_request_t* r); 57 | 58 | NgxMessageHandler* ngx_message_handler() { 59 | return dynamic_cast(message_handler()); 60 | } 61 | 62 | virtual GoogleString FormatOption(StringPiece option_name, StringPiece args); 63 | 64 | void set_ngx_http2_variable_index(ngx_int_t idx) { 65 | ngx_http2_variable_index_ = idx; 66 | } 67 | 68 | ngx_int_t ngx_http2_variable_index() const { 69 | return ngx_http2_variable_index_; 70 | } 71 | 72 | private: 73 | NgxRewriteDriverFactory* ngx_factory_; 74 | // what index the "http2" var is, or NGX_ERROR. 75 | ngx_int_t ngx_http2_variable_index_; 76 | 77 | DISALLOW_COPY_AND_ASSIGN(NgxServerContext); 78 | }; 79 | 80 | } // namespace net_instaweb 81 | 82 | #endif // NGX_SERVER_CONTEXT_H_ 83 | -------------------------------------------------------------------------------- /src/ngx_event_connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | // 22 | // NgxEventConnection implements a means to send events from other threads to 23 | // nginx's event loop, and is implemented by a named pipe under the hood. 24 | // A single instance is used by NgxBaseFetch, and one instance is created per 25 | // NgxUrlAsyncFetcher when native fetching is on. 26 | 27 | #ifndef NGX_EVENT_CONNECTION_H_ 28 | #define NGX_EVENT_CONNECTION_H_ 29 | 30 | extern "C" { 31 | #include 32 | } 33 | 34 | #include 35 | 36 | #include "pagespeed/kernel/base/string.h" 37 | #include "pagespeed/kernel/http/headers.h" 38 | 39 | namespace net_instaweb { 40 | 41 | class NgxEventConnection; 42 | 43 | // Represents a single event that can be written to or read from the pipe. 44 | // Technically, sender is the only data we need to send. type and connection are 45 | // included to provide a means to trace the events along with some more 46 | // info. 47 | typedef struct { 48 | char type; 49 | void* sender; 50 | NgxEventConnection* connection; 51 | } ps_event_data; 52 | 53 | // Handler signature for receiving events 54 | typedef void (*callbackPtr)(const ps_event_data&); 55 | 56 | // Abstracts a connection to nginx through which events can be written. 57 | class NgxEventConnection { 58 | public: 59 | explicit NgxEventConnection(callbackPtr handler); 60 | 61 | // Creates the file descriptors and ngx_connection_t required for event 62 | // messaging between pagespeed and nginx. 63 | bool Init(ngx_cycle_t* cycle); 64 | // Shuts down the underlying file descriptors and connection created in Init() 65 | void Shutdown(); 66 | // Constructs a ps_event_data and writes it to the underlying named pipe. 67 | bool WriteEvent(char type, void* sender); 68 | // Convenience overload for clients that have a single event type. 69 | bool WriteEvent(void* sender); 70 | // Reads and processes what is available in the named pipe's buffer. 71 | void Drain(); 72 | private: 73 | static bool CreateNgxConnection(ngx_cycle_t* cycle, ngx_fd_t pipe_fd); 74 | static void ReadEventHandler(ngx_event_t* e); 75 | static bool ReadAndNotify(ngx_fd_t fd); 76 | 77 | callbackPtr event_handler_; 78 | // We own these file descriptors 79 | ngx_fd_t pipe_write_fd_; 80 | ngx_fd_t pipe_read_fd_; 81 | 82 | DISALLOW_COPY_AND_ASSIGN(NgxEventConnection); 83 | }; 84 | 85 | } // namespace net_instaweb 86 | 87 | #endif // NGX_EVENT_CONNECTION_H_ 88 | -------------------------------------------------------------------------------- /cpp_feature: -------------------------------------------------------------------------------- 1 | # Copyright (C) Igor Sysoev 2 | # Copyright (C) Nginx, Inc. 3 | # 2012-10-01 Modified from auto/feature by jefftk to support c++ test files. 4 | 5 | echo $ngx_n "checking for $ngx_feature ...$ngx_c" 6 | 7 | cat << END >> $NGX_AUTOCONF_ERR 8 | 9 | ---------------------------------------- 10 | checking for $ngx_feature 11 | 12 | END 13 | 14 | ngx_found=no 15 | 16 | if test -n "$ngx_feature_name"; then 17 | ngx_have_feature=`echo $ngx_feature_name \ 18 | | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` 19 | fi 20 | 21 | if test -n "$ngx_feature_path"; then 22 | for ngx_temp in $ngx_feature_path; do 23 | ngx_feature_inc_path="$ngx_feature_inc_path -I $ngx_temp" 24 | done 25 | fi 26 | 27 | cat << END > $NGX_AUTOTEST.cc 28 | 29 | #include 30 | $NGX_INCLUDE_UNISTD_H 31 | $ngx_feature_incs 32 | 33 | int main() { 34 | $ngx_feature_test; 35 | return 0; 36 | } 37 | 38 | END 39 | 40 | 41 | ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \ 42 | -o $NGX_AUTOTEST $NGX_AUTOTEST.cc $NGX_TEST_LD_OPT $ngx_feature_libs" 43 | 44 | ngx_feature_inc_path= 45 | 46 | eval "/bin/sh -c \"$ngx_test\" >> $NGX_AUTOCONF_ERR 2>&1" 47 | 48 | 49 | if [ -x $NGX_AUTOTEST ]; then 50 | 51 | case "$ngx_feature_run" in 52 | 53 | yes) 54 | # /bin/sh is used to intercept "Killed" or "Abort trap" messages 55 | if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then 56 | echo " found" 57 | ngx_found=yes 58 | 59 | if test -n "$ngx_feature_name"; then 60 | have=$ngx_have_feature . auto/have 61 | fi 62 | 63 | else 64 | echo " found but is not working" 65 | fi 66 | ;; 67 | 68 | value) 69 | # /bin/sh is used to intercept "Killed" or "Abort trap" messages 70 | if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then 71 | echo " found" 72 | ngx_found=yes 73 | 74 | cat << END >> $NGX_AUTO_CONFIG_H 75 | 76 | #ifndef $ngx_feature_name 77 | #define $ngx_feature_name `$NGX_AUTOTEST` 78 | #endif 79 | 80 | END 81 | else 82 | echo " found but is not working" 83 | fi 84 | ;; 85 | 86 | bug) 87 | # /bin/sh is used to intercept "Killed" or "Abort trap" messages 88 | if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then 89 | echo " not found" 90 | 91 | else 92 | echo " found" 93 | ngx_found=yes 94 | 95 | if test -n "$ngx_feature_name"; then 96 | have=$ngx_have_feature . auto/have 97 | fi 98 | fi 99 | ;; 100 | 101 | *) 102 | echo " found" 103 | ngx_found=yes 104 | 105 | if test -n "$ngx_feature_name"; then 106 | have=$ngx_have_feature . auto/have 107 | fi 108 | ;; 109 | 110 | esac 111 | 112 | else 113 | echo " not found" 114 | 115 | echo "----------" >> $NGX_AUTOCONF_ERR 116 | cat $NGX_AUTOTEST.cc >> $NGX_AUTOCONF_ERR 117 | echo "----------" >> $NGX_AUTOCONF_ERR 118 | echo $ngx_test >> $NGX_AUTOCONF_ERR 119 | echo "----------" >> $NGX_AUTOCONF_ERR 120 | fi 121 | 122 | rm $NGX_AUTOTEST* 123 | -------------------------------------------------------------------------------- /src/ngx_server_context.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | #include "ngx_server_context.h" 23 | 24 | extern "C" { 25 | #include 26 | } 27 | 28 | #include "ngx_pagespeed.h" 29 | #include "ngx_message_handler.h" 30 | #include "ngx_rewrite_driver_factory.h" 31 | #include "ngx_rewrite_options.h" 32 | #include "net/instaweb/rewriter/public/rewrite_driver.h" 33 | #include "pagespeed/system/add_headers_fetcher.h" 34 | #include "pagespeed/system/loopback_route_fetcher.h" 35 | #include "pagespeed/system/system_request_context.h" 36 | 37 | namespace net_instaweb { 38 | 39 | NgxServerContext::NgxServerContext( 40 | NgxRewriteDriverFactory* factory, StringPiece hostname, int port) 41 | : SystemServerContext(factory, hostname, port), 42 | ngx_http2_variable_index_(NGX_ERROR) { 43 | } 44 | 45 | NgxServerContext::~NgxServerContext() { } 46 | 47 | NgxRewriteOptions* NgxServerContext::config() { 48 | return NgxRewriteOptions::DynamicCast(global_options()); 49 | } 50 | 51 | SystemRequestContext* NgxServerContext::NewRequestContext( 52 | ngx_http_request_t* r) { 53 | // Based on ngx_http_variable_server_port. 54 | bool port_set = false; 55 | int local_port = 0; 56 | #if (NGX_HAVE_INET6) 57 | if (r->connection->local_sockaddr->sa_family == AF_INET6) { 58 | local_port = ntohs(reinterpret_cast( 59 | r->connection->local_sockaddr)->sin6_port); 60 | port_set = true; 61 | } 62 | #endif 63 | if (!port_set) { 64 | local_port = ntohs(reinterpret_cast( 65 | r->connection->local_sockaddr)->sin_port); 66 | } 67 | 68 | ngx_str_t local_ip; 69 | u_char addr[NGX_SOCKADDR_STRLEN]; 70 | local_ip.len = NGX_SOCKADDR_STRLEN; 71 | local_ip.data = addr; 72 | ngx_int_t rc = ngx_connection_local_sockaddr(r->connection, &local_ip, 0); 73 | if (rc != NGX_OK) { 74 | local_ip.len = 0; 75 | } 76 | 77 | SystemRequestContext* ctx = new SystemRequestContext( 78 | thread_system()->NewMutex(), timer(), 79 | ps_determine_host(r), local_port, str_to_string_piece(local_ip)); 80 | 81 | // See if http2 is in use. 82 | if (ngx_http2_variable_index_ >= 0) { 83 | ngx_http_variable_value_t* val = 84 | ngx_http_get_indexed_variable(r, ngx_http2_variable_index_); 85 | if (val != NULL && val->valid) { 86 | StringPiece str_val(reinterpret_cast(val->data), val->len); 87 | if (str_val == "h2" || str_val == "h2c") { 88 | ctx->set_using_http2(true); 89 | } 90 | } 91 | } 92 | 93 | return ctx; 94 | } 95 | 96 | GoogleString NgxServerContext::FormatOption(StringPiece option_name, 97 | StringPiece args) { 98 | return StrCat("pagespeed ", option_name, " ", args, ";"); 99 | } 100 | 101 | } // namespace net_instaweb 102 | -------------------------------------------------------------------------------- /src/log_message_handler.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | // TODO(jefftk): share more of this code with apache's log_message_handler 23 | 24 | #include "log_message_handler.h" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | #include "base/debug/debugger.h" 32 | #include "base/debug/stack_trace.h" 33 | #include "base/logging.h" 34 | #include "net/instaweb/public/version.h" 35 | #include "pagespeed/kernel/base/string_util.h" 36 | 37 | // Make sure we don't attempt to use LOG macros here, since doing so 38 | // would cause us to go into an infinite log loop. 39 | #undef LOG 40 | #define LOG USING_LOG_HERE_WOULD_CAUSE_INFINITE_RECURSION 41 | 42 | namespace { 43 | 44 | ngx_log_t* ngx_log = NULL; 45 | 46 | ngx_uint_t GetNgxLogLevel(int severity) { 47 | switch (severity) { 48 | case logging::LOG_INFO: 49 | return NGX_LOG_INFO; 50 | case logging::LOG_WARNING: 51 | return NGX_LOG_WARN; 52 | case logging::LOG_ERROR: 53 | return NGX_LOG_ERR; 54 | case logging::LOG_ERROR_REPORT: 55 | case logging::LOG_FATAL: 56 | return NGX_LOG_ALERT; 57 | default: // For VLOG(s) 58 | return NGX_LOG_DEBUG; 59 | } 60 | } 61 | 62 | bool LogMessageHandler(int severity, const char* file, int line, 63 | size_t message_start, const GoogleString& str) { 64 | ngx_uint_t this_log_level = GetNgxLogLevel(severity); 65 | 66 | GoogleString message = str; 67 | if (severity == logging::LOG_FATAL) { 68 | if (base::debug::BeingDebugged()) { 69 | base::debug::BreakDebugger(); 70 | } else { 71 | base::debug::StackTrace trace; 72 | std::ostringstream stream; 73 | trace.OutputToStream(&stream); 74 | message.append(stream.str()); 75 | } 76 | } 77 | 78 | // Trim the newline off the end of the message string. 79 | size_t last_msg_character_index = message.length() - 1; 80 | if (message[last_msg_character_index] == '\n') { 81 | message.resize(last_msg_character_index); 82 | } 83 | 84 | ngx_log_error(this_log_level, ngx_log, 0, "[ngx_pagespeed %s] %s", 85 | net_instaweb::kModPagespeedVersion, 86 | message.c_str()); 87 | 88 | if (severity == logging::LOG_FATAL) { 89 | // Crash the process to generate a dump. 90 | base::debug::BreakDebugger(); 91 | } 92 | 93 | return true; 94 | } 95 | 96 | } // namespace 97 | 98 | 99 | namespace net_instaweb { 100 | 101 | namespace log_message_handler { 102 | 103 | 104 | void Install(ngx_log_t* log_in) { 105 | ngx_log = log_in; 106 | logging::SetLogMessageHandler(&LogMessageHandler); 107 | 108 | // All VLOG(2) and higher will be displayed as DEBUG logs if the nginx log 109 | // level is DEBUG. 110 | if (ngx_log->log_level >= NGX_LOG_DEBUG) { 111 | logging::SetMinLogLevel(-2); 112 | } 113 | } 114 | 115 | } // namespace log_message_handler 116 | 117 | } // namespace net_instaweb 118 | -------------------------------------------------------------------------------- /test/run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | 19 | # Runs ngx_pagespeed system tests. 20 | # 21 | # Exits with status 0 if all tests pass. 22 | # Exits with status 1 immediately if any test fails. 23 | # Exits with status 2 if command line args are wrong. 24 | # 25 | # Usage: 26 | # ./run_tests.sh 27 | # Or: 28 | # ./run_tests.sh /path/to/mod_pagespeed /path/to/nginx/binary 29 | # 30 | # If you built ngx_pagespeed with "scripts/build_ngx_pagespeed.sh --devel" then 31 | # you don't need to pass any arguments to run_tests.sh. Otherwise, you'll need 32 | # to tell it where to find a mod_pagespeed checkout (for example html files etc) 33 | # and the nginx binary to test. 34 | # 35 | # By default the test script uses several ports. If you have a port conflict 36 | # and need to override one you can do that by setting the relevant environment 37 | # variable. For example: 38 | # PRIMARY_PORT=1234 ./run_tests.sh /.../mod_pagespeed /.../nginx/binary 39 | 40 | # Normally we test only with the native fetcher off. Set 41 | # TEST_NATIVE_FETCHER=true to also test the native fetcher, set 42 | # TEST_SERF_FETCHER=false to skip the serf fetcher. 43 | TEST_NATIVE_FETCHER=${TEST_NATIVE_FETCHER:-false} 44 | TEST_SERF_FETCHER=${TEST_SERF_FETCHER:-true} 45 | 46 | # Normally we actually run the tests, but you might only want us to set up nginx 47 | # for you so you can do manual testing. If so, set RUN_TESTS=false and this 48 | # will exit after configuring and starting nginx. 49 | RUN_TESTS=${RUN_TESTS:-true} 50 | 51 | # To run tests with valgrind, set the environment variable USE_VALGRIND to 52 | # true. 53 | USE_VALGRIND=${USE_VALGRIND:-false} 54 | 55 | if [ "$#" -eq 0 ]; then 56 | MOD_PAGESPEED_DIR="testing-dependencies/mod_pagespeed/" 57 | NGINX_EXECUTABLE="nginx/sbin/nginx" 58 | elif [ "$#" -eq 2 ]; then 59 | MOD_PAGESPEED_DIR="$1" 60 | NGINX_EXECUTABLE="$2" 61 | else 62 | echo "Usage: $0 [mod_pagespeed_dir nginx_executable]" 63 | exit 2 64 | fi 65 | 66 | : ${PRIMARY_PORT:=8050} 67 | : ${SECONDARY_PORT:=8051} 68 | : ${CONTROLLER_PORT:=8053} 69 | : ${RCPORT:=9991} 70 | : ${PAGESPEED_TEST_HOST:=selfsigned.modpagespeed.com} 71 | : ${PHP_PORT:=9000} 72 | 73 | this_dir="$( cd $(dirname "$0") && pwd)" 74 | 75 | function run_test_checking_failure() { 76 | "$MOD_PAGESPEED_DIR/install/start_php.sh" "$PHP_PORT" 77 | USE_VALGRIND="$USE_VALGRIND" \ 78 | PRIMARY_PORT="$PRIMARY_PORT" \ 79 | SECONDARY_PORT="$SECONDARY_PORT" \ 80 | MOD_PAGESPEED_DIR="$MOD_PAGESPEED_DIR" \ 81 | NGINX_EXECUTABLE="$NGINX_EXECUTABLE" \ 82 | PAGESPEED_TEST_HOST="$PAGESPEED_TEST_HOST" \ 83 | RUN_TESTS="$RUN_TESTS" \ 84 | CONTROLLER_PORT="$CONTROLLER_PORT" \ 85 | RCPORT="$RCPORT" \ 86 | bash "$this_dir/nginx_system_test.sh" 87 | STATUS=$? 88 | echo "With $@ setup." 89 | case $STATUS in 90 | 0) 91 | return # No failure. 92 | ;; 93 | 3) 94 | return # Only expected failures. 95 | ;; 96 | 4) 97 | return # Return passing error code when running manually. 98 | ;; 99 | *) 100 | exit 1 # Real failure. 101 | esac 102 | } 103 | 104 | if $TEST_SERF_FETCHER; then 105 | NATIVE_FETCHER=off run_test_checking_failure "serf fetcher" 106 | fi 107 | 108 | if $TEST_NATIVE_FETCHER; then 109 | NATIVE_FETCHER=on run_test_checking_failure "native fetcher" 110 | fi 111 | -------------------------------------------------------------------------------- /src/ngx_gzip_setter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | /* 23 | * NgxGZipSetter sets up gzip for pagespeed 24 | * with the following configuration: 25 | * gzip on; 26 | * gzip_vary on; 27 | * gzip_types application/ecmascript; 28 | * gzip_types application/javascript; 29 | * gzip_types application/json; 30 | * gzip_types application/pdf; 31 | * gzip_types application/postscript; 32 | * gzip_types application/x-javascript; 33 | * gzip_types image/svg+xml; 34 | * gzip_types text/css; 35 | * gzip_types text/csv; 36 | * gzip_types text/javascript; 37 | * gzip_types text/plain; 38 | * gzip_types text/xml; 39 | * gzip_http_version 1.0; 40 | * 41 | * If there is an explicit gzip configuration in the nginx.conf 42 | * pagespeed will rollback the set configuration and let the 43 | * user decide what the configuration will be. 44 | * 45 | * It manipulates the configuration by manipulating ngx_flag_t 46 | * and ngx_uint_t settings directly and using the nginx setter for 47 | * gzip_http_types. 48 | * This is probably a safe way to do it. If this mechanism 49 | * changes all non nginx module setup & configuration will 50 | * fail. 51 | */ 52 | 53 | #ifndef NGX_GZIP_SETTER_H_ 54 | #define NGX_GZIP_SETTER_H_ 55 | 56 | extern "C" { 57 | #include 58 | #include 59 | #include 60 | } 61 | 62 | #include 63 | 64 | #include "ngx_pagespeed.h" 65 | 66 | #include "pagespeed/kernel/base/basictypes.h" 67 | 68 | namespace net_instaweb { 69 | 70 | // We need this class because configuration for gzip is in different modules, so 71 | // just saving the command will not work. 72 | class ngx_command_ctx { 73 | public: 74 | ngx_command_ctx() : command_(NULL), module_(NULL) { } 75 | void* GetConfPtr(ngx_conf_t* cf); 76 | char* GetModuleConfPtr(ngx_conf_t* cf); 77 | ngx_command_t* command_; 78 | ngx_module_t* module_; 79 | }; 80 | 81 | enum gzs_enable_result { 82 | kEnableGZipOk, 83 | kEnableGZipPartial, 84 | kEnableGZipNotEnabled 85 | }; 86 | 87 | class NgxGZipSetter { 88 | std::vector ngx_flags_set_; 89 | std::vector ngx_uint_set_; 90 | std::vector ngx_httptypes_set_; 91 | ngx_command_ctx gzip_command_; 92 | ngx_command_ctx gzip_http_types_command_; 93 | ngx_command_ctx gzip_proxied_command_; 94 | ngx_command_ctx gzip_vary_command_; 95 | ngx_command_ctx gzip_http_version_command_; 96 | bool enabled_; 97 | 98 | public: 99 | NgxGZipSetter(); 100 | ~NgxGZipSetter(); 101 | void Init(ngx_conf_t* cf); 102 | 103 | void SetNgxConfFlag(ngx_conf_t* cf, 104 | ngx_command_ctx* command_ctx, 105 | ngx_flag_t value); 106 | void SetNgxConfEnum(ngx_conf_t* cf, 107 | ngx_command_ctx* command_ctx, 108 | ngx_uint_t value); 109 | void SetNgxConfBitmask(ngx_conf_t* cf, 110 | ngx_command_ctx* command_ctx, 111 | ngx_uint_t value); 112 | void EnableGZipForLocation(ngx_conf_t* cf); 113 | gzs_enable_result SetGZipForLocation(ngx_conf_t* cf, bool value); 114 | void AddGZipHTTPTypes(ngx_conf_t* cf); 115 | void RollBackAndDisable(ngx_conf_t* cf); 116 | 117 | bool enabled() { return enabled_; } 118 | 119 | private: 120 | DISALLOW_COPY_AND_ASSIGN(NgxGZipSetter); 121 | }; 122 | 123 | extern NgxGZipSetter g_gzip_setter; 124 | 125 | } // namespace net_instaweb 126 | 127 | #endif // NGX_GZIP_SETTER_H_ 128 | -------------------------------------------------------------------------------- /src/ngx_message_handler.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | 23 | #include "ngx_message_handler.h" 24 | 25 | #include 26 | 27 | #include "net/instaweb/public/version.h" 28 | #include "pagespeed/kernel/base/abstract_mutex.h" 29 | #include "pagespeed/kernel/base/debug.h" 30 | #include "pagespeed/kernel/base/posix_timer.h" 31 | #include "pagespeed/kernel/base/string_util.h" 32 | #include "pagespeed/kernel/base/time_util.h" 33 | #include "pagespeed/kernel/sharedmem/shared_circular_buffer.h" 34 | 35 | namespace { 36 | 37 | // This will be prefixed to every logged message. 38 | const char kModuleName[] = "ngx_pagespeed"; 39 | 40 | // If set, the crash handler will use this to output a backtrace using 41 | // ngx_log_error. 42 | ngx_log_t* global_log = NULL; 43 | 44 | } // namespace 45 | 46 | extern "C" { 47 | static void signal_handler(int sig) { 48 | // Try to output the backtrace to the log file. Since this may end up 49 | // crashing/deadlocking/etc. we set an alarm() to abort us if it comes to 50 | // that. 51 | alarm(2); 52 | if (global_log != NULL) { 53 | ngx_log_error(NGX_LOG_ALERT, global_log, 0, "Trapped signal [%d]\n%s", 54 | sig, net_instaweb::StackTraceString().c_str()); 55 | } else { 56 | fprintf(stderr, "Trapped signal [%d]\n%s\n", 57 | sig, net_instaweb::StackTraceString().c_str()); 58 | } 59 | kill(getpid(), SIGKILL); 60 | } 61 | } // extern "C" 62 | 63 | namespace net_instaweb { 64 | 65 | NgxMessageHandler::NgxMessageHandler(Timer* timer, AbstractMutex* mutex) 66 | : SystemMessageHandler(timer, mutex), 67 | log_(NULL) { 68 | } 69 | 70 | // Installs a signal handler for common crash signals, that tries to print 71 | // out a backtrace. 72 | void NgxMessageHandler::InstallCrashHandler(ngx_log_t* log) { 73 | global_log = log; 74 | signal(SIGTRAP, signal_handler); // On check failures 75 | signal(SIGABRT, signal_handler); 76 | signal(SIGFPE, signal_handler); 77 | signal(SIGSEGV, signal_handler); 78 | } 79 | 80 | ngx_uint_t NgxMessageHandler::GetNgxLogLevel(MessageType type) { 81 | switch (type) { 82 | case kInfo: 83 | return NGX_LOG_INFO; 84 | case kWarning: 85 | return NGX_LOG_WARN; 86 | case kError: 87 | return NGX_LOG_ERR; 88 | case kFatal: 89 | return NGX_LOG_ALERT; 90 | } 91 | 92 | // This should never fall through, but some compilers seem to complain if 93 | // we don't include this. 94 | return NGX_LOG_ALERT; 95 | } 96 | 97 | void NgxMessageHandler::MessageSImpl(MessageType type, 98 | const GoogleString& message) { 99 | if (log_ != NULL) { 100 | ngx_uint_t log_level = GetNgxLogLevel(type); 101 | ngx_log_error(log_level, log_, 0/*ngx_err_t*/, "[%s %s] %s", 102 | kModuleName, kModPagespeedVersion, message.c_str()); 103 | } else { 104 | GoogleMessageHandler::MessageSImpl(type, message); 105 | } 106 | AddMessageToBuffer(type, message); 107 | } 108 | 109 | void NgxMessageHandler::FileMessageSImpl( 110 | MessageType type, const char* file, int line, const GoogleString& message) { 111 | if (log_ != NULL) { 112 | ngx_uint_t log_level = GetNgxLogLevel(type); 113 | ngx_log_error(log_level, log_, 0/*ngx_err_t*/, "[%s %s] %s:%d:%s", 114 | kModuleName, kModPagespeedVersion, file, line, 115 | message.c_str()); 116 | } else { 117 | GoogleMessageHandler::FileMessageSImpl(type, file, line, message); 118 | } 119 | AddMessageToBuffer(type, file, line, message); 120 | } 121 | 122 | } // namespace net_instaweb 123 | -------------------------------------------------------------------------------- /src/ngx_pagespeed.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | #ifndef NGX_PAGESPEED_H_ 23 | #define NGX_PAGESPEED_H_ 24 | 25 | // We might be compiled with syslog.h, which #defines LOG_INFO and LOG_WARNING 26 | // as ints. But logging.h assumes they're usable as names, within their 27 | // namespace, so we need to #undef them before including logging.h 28 | #ifdef LOG_INFO 29 | #undef LOG_INFO 30 | #endif 31 | #ifdef LOG_WARNING 32 | #undef LOG_WARNING 33 | #endif 34 | 35 | extern "C" { 36 | #include 37 | } 38 | 39 | #include "base/logging.h" 40 | #include "pagespeed/kernel/base/string_util.h" 41 | #include "pagespeed/kernel/http/response_headers.h" 42 | 43 | namespace net_instaweb { 44 | 45 | class GzipInflater; 46 | class NgxBaseFetch; 47 | class ProxyFetch; 48 | class RewriteDriver; 49 | class RequestHeaders; 50 | class ResponseHeaders; 51 | class InPlaceResourceRecorder; 52 | 53 | // Allocate chain links and buffers from the supplied pool, and copy over the 54 | // data from the string piece. If the string piece is empty, return 55 | // NGX_DECLINED immediately unless send_last_buf. 56 | ngx_int_t string_piece_to_buffer_chain( 57 | ngx_pool_t* pool, StringPiece sp, 58 | ngx_chain_t** link_ptr, bool send_last_buf, bool send_flush); 59 | 60 | StringPiece str_to_string_piece(ngx_str_t s); 61 | 62 | // s1: ngx_str_t, s2: string literal 63 | // true if they're equal, false otherwise 64 | #define STR_EQ_LITERAL(s1, s2) \ 65 | ((s1).len == (sizeof(s2)-1) && \ 66 | ngx_strncmp((s1).data, (s2), (sizeof(s2)-1)) == 0) 67 | 68 | // s1: ngx_str_t, s2: string literal 69 | // true if they're equal ignoring case, false otherwise 70 | #define STR_CASE_EQ_LITERAL(s1, s2) \ 71 | ((s1).len == (sizeof(s2)-1) && \ 72 | ngx_strncasecmp((s1).data, ( \ 73 | reinterpret_cast( \ 74 | const_cast(s2))), \ 75 | (sizeof(s2)-1)) == 0) 76 | 77 | // Allocate memory out of the pool for the string piece, and copy the contents 78 | // over. Returns NULL if we can't get memory. 79 | char* string_piece_to_pool_string(ngx_pool_t* pool, StringPiece sp); 80 | 81 | enum PreserveCachingHeaders { 82 | kPreserveAllCachingHeaders, // Cache-Control, ETag, Last-Modified, etc 83 | kPreserveOnlyCacheControl, // Only Cache-Control. 84 | kDontPreserveHeaders, 85 | }; 86 | 87 | typedef struct { 88 | NgxBaseFetch* base_fetch; 89 | 90 | ngx_http_request_t* r; 91 | 92 | bool html_rewrite; 93 | bool in_place; 94 | 95 | PreserveCachingHeaders preserve_caching_headers; 96 | 97 | // for html rewrite 98 | ProxyFetch* proxy_fetch; 99 | GzipInflater* inflater_; 100 | 101 | // for in place resource 102 | RewriteDriver* driver; 103 | InPlaceResourceRecorder* recorder; 104 | ResponseHeaders* ipro_response_headers; 105 | 106 | // We need to remember the URL here as well since we may modify what NGX 107 | // gets by stripping our special query params and honoring X-Forwarded-Proto. 108 | GoogleString url_string; 109 | 110 | // We need to remember if the upstream had headers_out->location set, because 111 | // we should mirror that when we write it back. nginx may absolutify 112 | // Location: headers that start with '/' without regarding X-Forwarded-Proto. 113 | bool location_field_set; 114 | bool psol_vary_accept_only; 115 | bool follow_flushes; 116 | } ps_request_ctx_t; 117 | 118 | ps_request_ctx_t* ps_get_request_context(ngx_http_request_t* r); 119 | 120 | void copy_request_headers_from_ngx(const ngx_http_request_t* r, 121 | RequestHeaders* headers); 122 | 123 | void copy_response_headers_from_ngx(const ngx_http_request_t* r, 124 | ResponseHeaders* headers); 125 | 126 | ngx_int_t copy_response_headers_to_ngx( 127 | ngx_http_request_t* r, 128 | const ResponseHeaders& pagespeed_headers, 129 | PreserveCachingHeaders preserve_caching_headers); 130 | 131 | StringPiece ps_determine_host(ngx_http_request_t* r); 132 | 133 | namespace ps_base_fetch { 134 | 135 | ngx_int_t ps_base_fetch_handler(ngx_http_request_t* r); 136 | 137 | } // namespace ps_base_fetch 138 | 139 | } // namespace net_instaweb 140 | 141 | #endif // NGX_PAGESPEED_H_ 142 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/patches/modpagespeed/libpng16.patch: -------------------------------------------------------------------------------- 1 | From 7ea8d5fc141c7067c54ffa2b9fbc552c15089ca6 Mon Sep 17 00:00:00 2001 2 | From: ashishk-1 3 | Date: Thu, 18 Jan 2018 22:14:05 +0530 4 | Subject: [PATCH] Upgrading libpng library to version 1.6 (#1724) 5 | 6 | --- 7 | net/instaweb/rewriter/image.cc | 8 ++++++++ 8 | pagespeed/kernel/image/gif_reader.cc | 4 ++-- 9 | pagespeed/kernel/image/image_converter.cc | 6 ++++++ 10 | pagespeed/kernel/image/png_optimizer_test.cc | 6 ++++++ 11 | third_party/libpng/libpng.gyp | 26 +++++++++++++++++++++++--- 12 | third_party/libpng/src | 2 +- 13 | 6 files changed, 46 insertions(+), 6 deletions(-) 14 | 15 | diff --git a/net/instaweb/rewriter/image.cc b/net/instaweb/rewriter/image.cc 16 | index 4f631182a..bb67bba35 100644 17 | --- a/net/instaweb/rewriter/image.cc 18 | +++ b/net/instaweb/rewriter/image.cc 19 | @@ -21,6 +21,14 @@ 20 | #include 21 | #include 22 | 23 | +extern "C" { 24 | +#ifdef USE_SYSTEM_ZLIB 25 | +#include "zlib.h" 26 | +#else 27 | +#include "third_party/zlib/zlib.h" 28 | +#endif 29 | +} // extern "C" 30 | + 31 | #include "base/logging.h" 32 | #include "net/instaweb/rewriter/cached_result.pb.h" 33 | #include "net/instaweb/rewriter/public/image_data_lookup.h" 34 | diff --git a/pagespeed/kernel/image/gif_reader.cc b/pagespeed/kernel/image/gif_reader.cc 35 | index 7de69b3d7..bb0bc9cfc 100644 36 | --- a/pagespeed/kernel/image/gif_reader.cc 37 | +++ b/pagespeed/kernel/image/gif_reader.cc 38 | @@ -411,8 +411,8 @@ bool ReadGifToPng(GifFileType* gif_file, 39 | png_uint_32 height = png_get_image_height(paletted_png_ptr, 40 | paletted_info_ptr); 41 | for (png_uint_32 row = 1; row < height; ++row) { 42 | - memcpy(paletted_info_ptr->row_pointers[row], 43 | - paletted_info_ptr->row_pointers[0], 44 | + memcpy(row_pointers[row], 45 | + row_pointers[0], 46 | row_size); 47 | } 48 | 49 | diff --git a/pagespeed/kernel/image/image_converter.cc b/pagespeed/kernel/image/image_converter.cc 50 | index d796b5065..84b7aff74 100644 51 | --- a/pagespeed/kernel/image/image_converter.cc 52 | +++ b/pagespeed/kernel/image/image_converter.cc 53 | @@ -30,6 +30,12 @@ extern "C" { 54 | #else 55 | #include "third_party/libpng/src/png.h" 56 | #endif 57 | + 58 | +#ifdef USE_SYSTEM_ZLIB 59 | +#include "zlib.h" 60 | +#else 61 | +#include "third_party/zlib/zlib.h" 62 | +#endif 63 | } // extern "C" 64 | 65 | #include "base/logging.h" 66 | diff --git a/pagespeed/kernel/image/png_optimizer_test.cc b/pagespeed/kernel/image/png_optimizer_test.cc 67 | index 9ad915aff..3faa526a8 100644 68 | --- a/pagespeed/kernel/image/png_optimizer_test.cc 69 | +++ b/pagespeed/kernel/image/png_optimizer_test.cc 70 | @@ -36,6 +36,12 @@ extern "C" { 71 | #else 72 | #include "third_party/libpng/src/png.h" 73 | #endif 74 | + 75 | +#ifdef USE_SYSTEM_ZLIB 76 | +#include "zlib.h" 77 | +#else 78 | +#include "third_party/zlib/zlib.h" 79 | +#endif 80 | } 81 | 82 | namespace { 83 | diff --git a/third_party/libpng/libpng.gyp b/third_party/libpng/libpng.gyp 84 | index cfaafee00..d96a8f74c 100644 85 | --- a/third_party/libpng/libpng.gyp 86 | +++ b/third_party/libpng/libpng.gyp 87 | @@ -22,14 +22,29 @@ 88 | 'dependencies': [ 89 | '../zlib/zlib.gyp:zlib', 90 | ], 91 | + 'actions': [ 92 | + { 93 | + 'action_name': 'copy_libpngconf_prebuilt', 94 | + 'inputs' : [], 95 | + 'outputs': [''], 96 | + 'action': [ 97 | + 'cp', 98 | + '-f', 99 | + '<(DEPTH)/third_party/libpng/src/scripts/pnglibconf.h.prebuilt', 100 | + '<(DEPTH)/third_party/libpng/src/pnglibconf.h', 101 | + ], 102 | + }, 103 | + ], 104 | 'msvs_guid': 'C564F145-9172-42C3-BFCB-6014CA97DBCD', 105 | 'sources': [ 106 | + 'src/pngpriv.h', 107 | 'src/png.c', 108 | 'src/png.h', 109 | 'src/pngconf.h', 110 | + 'src/pngdebug.h', 111 | 'src/pngerror.c', 112 | - 'src/pnggccrd.c', 113 | 'src/pngget.c', 114 | + 'src/pnginfo.h', 115 | 'src/pngmem.c', 116 | 'src/pngpread.c', 117 | 'src/pngread.c', 118 | @@ -37,9 +52,8 @@ 119 | 'src/pngrtran.c', 120 | 'src/pngrutil.c', 121 | 'src/pngset.c', 122 | + 'src/pngstruct.h', 123 | 'src/pngtrans.c', 124 | - 'src/pngusr.h', 125 | - 'src/pngvcrd.c', 126 | 'src/pngwio.c', 127 | 'src/pngwrite.c', 128 | 'src/pngwtran.c', 129 | @@ -54,6 +68,12 @@ 130 | # doesn't like that. This define tells libpng to not 131 | # complain about our inclusion of setjmp.h. 132 | 'PNG_SKIP_SETJMP_CHECK', 133 | + 134 | + # The PNG_FREE_ME_SUPPORTED define was dropped in libpng 135 | + # 1.4.0beta78, with its behavior becoming the default 136 | + # behavior. 137 | + # Hence, we define it ourselves for version >= 1.4.0 138 | + 'PNG_FREE_ME_SUPPORTED', 139 | ], 140 | }, 141 | 'export_dependent_settings': [ 142 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/patches/modpagespeed/libpng16.patch: -------------------------------------------------------------------------------- 1 | From 7ea8d5fc141c7067c54ffa2b9fbc552c15089ca6 Mon Sep 17 00:00:00 2001 2 | From: ashishk-1 3 | Date: Thu, 18 Jan 2018 22:14:05 +0530 4 | Subject: [PATCH] Upgrading libpng library to version 1.6 (#1724) 5 | 6 | --- 7 | net/instaweb/rewriter/image.cc | 8 ++++++++ 8 | pagespeed/kernel/image/gif_reader.cc | 4 ++-- 9 | pagespeed/kernel/image/image_converter.cc | 6 ++++++ 10 | pagespeed/kernel/image/png_optimizer_test.cc | 6 ++++++ 11 | third_party/libpng/libpng.gyp | 26 +++++++++++++++++++++++--- 12 | third_party/libpng/src | 2 +- 13 | 6 files changed, 46 insertions(+), 6 deletions(-) 14 | 15 | diff --git a/net/instaweb/rewriter/image.cc b/net/instaweb/rewriter/image.cc 16 | index 4f631182a..bb67bba35 100644 17 | --- a/net/instaweb/rewriter/image.cc 18 | +++ b/net/instaweb/rewriter/image.cc 19 | @@ -21,6 +21,14 @@ 20 | #include 21 | #include 22 | 23 | +extern "C" { 24 | +#ifdef USE_SYSTEM_ZLIB 25 | +#include "zlib.h" 26 | +#else 27 | +#include "third_party/zlib/zlib.h" 28 | +#endif 29 | +} // extern "C" 30 | + 31 | #include "base/logging.h" 32 | #include "net/instaweb/rewriter/cached_result.pb.h" 33 | #include "net/instaweb/rewriter/public/image_data_lookup.h" 34 | diff --git a/pagespeed/kernel/image/gif_reader.cc b/pagespeed/kernel/image/gif_reader.cc 35 | index 7de69b3d7..bb0bc9cfc 100644 36 | --- a/pagespeed/kernel/image/gif_reader.cc 37 | +++ b/pagespeed/kernel/image/gif_reader.cc 38 | @@ -411,8 +411,8 @@ bool ReadGifToPng(GifFileType* gif_file, 39 | png_uint_32 height = png_get_image_height(paletted_png_ptr, 40 | paletted_info_ptr); 41 | for (png_uint_32 row = 1; row < height; ++row) { 42 | - memcpy(paletted_info_ptr->row_pointers[row], 43 | - paletted_info_ptr->row_pointers[0], 44 | + memcpy(row_pointers[row], 45 | + row_pointers[0], 46 | row_size); 47 | } 48 | 49 | diff --git a/pagespeed/kernel/image/image_converter.cc b/pagespeed/kernel/image/image_converter.cc 50 | index d796b5065..84b7aff74 100644 51 | --- a/pagespeed/kernel/image/image_converter.cc 52 | +++ b/pagespeed/kernel/image/image_converter.cc 53 | @@ -30,6 +30,12 @@ extern "C" { 54 | #else 55 | #include "third_party/libpng/src/png.h" 56 | #endif 57 | + 58 | +#ifdef USE_SYSTEM_ZLIB 59 | +#include "zlib.h" 60 | +#else 61 | +#include "third_party/zlib/zlib.h" 62 | +#endif 63 | } // extern "C" 64 | 65 | #include "base/logging.h" 66 | diff --git a/pagespeed/kernel/image/png_optimizer_test.cc b/pagespeed/kernel/image/png_optimizer_test.cc 67 | index 9ad915aff..3faa526a8 100644 68 | --- a/pagespeed/kernel/image/png_optimizer_test.cc 69 | +++ b/pagespeed/kernel/image/png_optimizer_test.cc 70 | @@ -36,6 +36,12 @@ extern "C" { 71 | #else 72 | #include "third_party/libpng/src/png.h" 73 | #endif 74 | + 75 | +#ifdef USE_SYSTEM_ZLIB 76 | +#include "zlib.h" 77 | +#else 78 | +#include "third_party/zlib/zlib.h" 79 | +#endif 80 | } 81 | 82 | namespace { 83 | diff --git a/third_party/libpng/libpng.gyp b/third_party/libpng/libpng.gyp 84 | index cfaafee00..d96a8f74c 100644 85 | --- a/third_party/libpng/libpng.gyp 86 | +++ b/third_party/libpng/libpng.gyp 87 | @@ -22,14 +22,29 @@ 88 | 'dependencies': [ 89 | '../zlib/zlib.gyp:zlib', 90 | ], 91 | + 'actions': [ 92 | + { 93 | + 'action_name': 'copy_libpngconf_prebuilt', 94 | + 'inputs' : [], 95 | + 'outputs': [''], 96 | + 'action': [ 97 | + 'cp', 98 | + '-f', 99 | + '<(DEPTH)/third_party/libpng/src/scripts/pnglibconf.h.prebuilt', 100 | + '<(DEPTH)/third_party/libpng/src/pnglibconf.h', 101 | + ], 102 | + }, 103 | + ], 104 | 'msvs_guid': 'C564F145-9172-42C3-BFCB-6014CA97DBCD', 105 | 'sources': [ 106 | + 'src/pngpriv.h', 107 | 'src/png.c', 108 | 'src/png.h', 109 | 'src/pngconf.h', 110 | + 'src/pngdebug.h', 111 | 'src/pngerror.c', 112 | - 'src/pnggccrd.c', 113 | 'src/pngget.c', 114 | + 'src/pnginfo.h', 115 | 'src/pngmem.c', 116 | 'src/pngpread.c', 117 | 'src/pngread.c', 118 | @@ -37,9 +52,8 @@ 119 | 'src/pngrtran.c', 120 | 'src/pngrutil.c', 121 | 'src/pngset.c', 122 | + 'src/pngstruct.h', 123 | 'src/pngtrans.c', 124 | - 'src/pngusr.h', 125 | - 'src/pngvcrd.c', 126 | 'src/pngwio.c', 127 | 'src/pngwrite.c', 128 | 'src/pngwtran.c', 129 | @@ -54,6 +68,12 @@ 130 | # doesn't like that. This define tells libpng to not 131 | # complain about our inclusion of setjmp.h. 132 | 'PNG_SKIP_SETJMP_CHECK', 133 | + 134 | + # The PNG_FREE_ME_SUPPORTED define was dropped in libpng 135 | + # 1.4.0beta78, with its behavior becoming the default 136 | + # behavior. 137 | + # Hence, we define it ourselves for version >= 1.4.0 138 | + 'PNG_FREE_ME_SUPPORTED', 139 | ], 140 | }, 141 | 'export_dependent_settings': [ 142 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/patches/modpagespeed/libpng16.patch: -------------------------------------------------------------------------------- 1 | From 7ea8d5fc141c7067c54ffa2b9fbc552c15089ca6 Mon Sep 17 00:00:00 2001 2 | From: ashishk-1 3 | Date: Thu, 18 Jan 2018 22:14:05 +0530 4 | Subject: [PATCH] Upgrading libpng library to version 1.6 (#1724) 5 | 6 | --- 7 | net/instaweb/rewriter/image.cc | 8 ++++++++ 8 | pagespeed/kernel/image/gif_reader.cc | 4 ++-- 9 | pagespeed/kernel/image/image_converter.cc | 6 ++++++ 10 | pagespeed/kernel/image/png_optimizer_test.cc | 6 ++++++ 11 | third_party/libpng/libpng.gyp | 26 +++++++++++++++++++++++--- 12 | third_party/libpng/src | 2 +- 13 | 6 files changed, 46 insertions(+), 6 deletions(-) 14 | 15 | diff --git a/net/instaweb/rewriter/image.cc b/net/instaweb/rewriter/image.cc 16 | index 4f631182a..bb67bba35 100644 17 | --- a/net/instaweb/rewriter/image.cc 18 | +++ b/net/instaweb/rewriter/image.cc 19 | @@ -21,6 +21,14 @@ 20 | #include 21 | #include 22 | 23 | +extern "C" { 24 | +#ifdef USE_SYSTEM_ZLIB 25 | +#include "zlib.h" 26 | +#else 27 | +#include "third_party/zlib/zlib.h" 28 | +#endif 29 | +} // extern "C" 30 | + 31 | #include "base/logging.h" 32 | #include "net/instaweb/rewriter/cached_result.pb.h" 33 | #include "net/instaweb/rewriter/public/image_data_lookup.h" 34 | diff --git a/pagespeed/kernel/image/gif_reader.cc b/pagespeed/kernel/image/gif_reader.cc 35 | index 7de69b3d7..bb0bc9cfc 100644 36 | --- a/pagespeed/kernel/image/gif_reader.cc 37 | +++ b/pagespeed/kernel/image/gif_reader.cc 38 | @@ -411,8 +411,8 @@ bool ReadGifToPng(GifFileType* gif_file, 39 | png_uint_32 height = png_get_image_height(paletted_png_ptr, 40 | paletted_info_ptr); 41 | for (png_uint_32 row = 1; row < height; ++row) { 42 | - memcpy(paletted_info_ptr->row_pointers[row], 43 | - paletted_info_ptr->row_pointers[0], 44 | + memcpy(row_pointers[row], 45 | + row_pointers[0], 46 | row_size); 47 | } 48 | 49 | diff --git a/pagespeed/kernel/image/image_converter.cc b/pagespeed/kernel/image/image_converter.cc 50 | index d796b5065..84b7aff74 100644 51 | --- a/pagespeed/kernel/image/image_converter.cc 52 | +++ b/pagespeed/kernel/image/image_converter.cc 53 | @@ -30,6 +30,12 @@ extern "C" { 54 | #else 55 | #include "third_party/libpng/src/png.h" 56 | #endif 57 | + 58 | +#ifdef USE_SYSTEM_ZLIB 59 | +#include "zlib.h" 60 | +#else 61 | +#include "third_party/zlib/zlib.h" 62 | +#endif 63 | } // extern "C" 64 | 65 | #include "base/logging.h" 66 | diff --git a/pagespeed/kernel/image/png_optimizer_test.cc b/pagespeed/kernel/image/png_optimizer_test.cc 67 | index 9ad915aff..3faa526a8 100644 68 | --- a/pagespeed/kernel/image/png_optimizer_test.cc 69 | +++ b/pagespeed/kernel/image/png_optimizer_test.cc 70 | @@ -36,6 +36,12 @@ extern "C" { 71 | #else 72 | #include "third_party/libpng/src/png.h" 73 | #endif 74 | + 75 | +#ifdef USE_SYSTEM_ZLIB 76 | +#include "zlib.h" 77 | +#else 78 | +#include "third_party/zlib/zlib.h" 79 | +#endif 80 | } 81 | 82 | namespace { 83 | diff --git a/third_party/libpng/libpng.gyp b/third_party/libpng/libpng.gyp 84 | index cfaafee00..d96a8f74c 100644 85 | --- a/third_party/libpng/libpng.gyp 86 | +++ b/third_party/libpng/libpng.gyp 87 | @@ -22,14 +22,29 @@ 88 | 'dependencies': [ 89 | '../zlib/zlib.gyp:zlib', 90 | ], 91 | + 'actions': [ 92 | + { 93 | + 'action_name': 'copy_libpngconf_prebuilt', 94 | + 'inputs' : [], 95 | + 'outputs': [''], 96 | + 'action': [ 97 | + 'cp', 98 | + '-f', 99 | + '<(DEPTH)/third_party/libpng/src/scripts/pnglibconf.h.prebuilt', 100 | + '<(DEPTH)/third_party/libpng/src/pnglibconf.h', 101 | + ], 102 | + }, 103 | + ], 104 | 'msvs_guid': 'C564F145-9172-42C3-BFCB-6014CA97DBCD', 105 | 'sources': [ 106 | + 'src/pngpriv.h', 107 | 'src/png.c', 108 | 'src/png.h', 109 | 'src/pngconf.h', 110 | + 'src/pngdebug.h', 111 | 'src/pngerror.c', 112 | - 'src/pnggccrd.c', 113 | 'src/pngget.c', 114 | + 'src/pnginfo.h', 115 | 'src/pngmem.c', 116 | 'src/pngpread.c', 117 | 'src/pngread.c', 118 | @@ -37,9 +52,8 @@ 119 | 'src/pngrtran.c', 120 | 'src/pngrutil.c', 121 | 'src/pngset.c', 122 | + 'src/pngstruct.h', 123 | 'src/pngtrans.c', 124 | - 'src/pngusr.h', 125 | - 'src/pngvcrd.c', 126 | 'src/pngwio.c', 127 | 'src/pngwrite.c', 128 | 'src/pngwtran.c', 129 | @@ -54,6 +68,12 @@ 130 | # doesn't like that. This define tells libpng to not 131 | # complain about our inclusion of setjmp.h. 132 | 'PNG_SKIP_SETJMP_CHECK', 133 | + 134 | + # The PNG_FREE_ME_SUPPORTED define was dropped in libpng 135 | + # 1.4.0beta78, with its behavior becoming the default 136 | + # behavior. 137 | + # Hence, we define it ourselves for version >= 1.4.0 138 | + 'PNG_FREE_ME_SUPPORTED', 139 | ], 140 | }, 141 | 'export_dependent_settings': [ 142 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/patches/modpagespeed/libpng16.patch: -------------------------------------------------------------------------------- 1 | From 7ea8d5fc141c7067c54ffa2b9fbc552c15089ca6 Mon Sep 17 00:00:00 2001 2 | From: ashishk-1 3 | Date: Thu, 18 Jan 2018 22:14:05 +0530 4 | Subject: [PATCH] Upgrading libpng library to version 1.6 (#1724) 5 | 6 | --- 7 | net/instaweb/rewriter/image.cc | 8 ++++++++ 8 | pagespeed/kernel/image/gif_reader.cc | 4 ++-- 9 | pagespeed/kernel/image/image_converter.cc | 6 ++++++ 10 | pagespeed/kernel/image/png_optimizer_test.cc | 6 ++++++ 11 | third_party/libpng/libpng.gyp | 26 +++++++++++++++++++++++--- 12 | third_party/libpng/src | 2 +- 13 | 6 files changed, 46 insertions(+), 6 deletions(-) 14 | 15 | diff --git a/net/instaweb/rewriter/image.cc b/net/instaweb/rewriter/image.cc 16 | index 4f631182a..bb67bba35 100644 17 | --- a/net/instaweb/rewriter/image.cc 18 | +++ b/net/instaweb/rewriter/image.cc 19 | @@ -21,6 +21,14 @@ 20 | #include 21 | #include 22 | 23 | +extern "C" { 24 | +#ifdef USE_SYSTEM_ZLIB 25 | +#include "zlib.h" 26 | +#else 27 | +#include "third_party/zlib/zlib.h" 28 | +#endif 29 | +} // extern "C" 30 | + 31 | #include "base/logging.h" 32 | #include "net/instaweb/rewriter/cached_result.pb.h" 33 | #include "net/instaweb/rewriter/public/image_data_lookup.h" 34 | diff --git a/pagespeed/kernel/image/gif_reader.cc b/pagespeed/kernel/image/gif_reader.cc 35 | index 7de69b3d7..bb0bc9cfc 100644 36 | --- a/pagespeed/kernel/image/gif_reader.cc 37 | +++ b/pagespeed/kernel/image/gif_reader.cc 38 | @@ -411,8 +411,8 @@ bool ReadGifToPng(GifFileType* gif_file, 39 | png_uint_32 height = png_get_image_height(paletted_png_ptr, 40 | paletted_info_ptr); 41 | for (png_uint_32 row = 1; row < height; ++row) { 42 | - memcpy(paletted_info_ptr->row_pointers[row], 43 | - paletted_info_ptr->row_pointers[0], 44 | + memcpy(row_pointers[row], 45 | + row_pointers[0], 46 | row_size); 47 | } 48 | 49 | diff --git a/pagespeed/kernel/image/image_converter.cc b/pagespeed/kernel/image/image_converter.cc 50 | index d796b5065..84b7aff74 100644 51 | --- a/pagespeed/kernel/image/image_converter.cc 52 | +++ b/pagespeed/kernel/image/image_converter.cc 53 | @@ -30,6 +30,12 @@ extern "C" { 54 | #else 55 | #include "third_party/libpng/src/png.h" 56 | #endif 57 | + 58 | +#ifdef USE_SYSTEM_ZLIB 59 | +#include "zlib.h" 60 | +#else 61 | +#include "third_party/zlib/zlib.h" 62 | +#endif 63 | } // extern "C" 64 | 65 | #include "base/logging.h" 66 | diff --git a/pagespeed/kernel/image/png_optimizer_test.cc b/pagespeed/kernel/image/png_optimizer_test.cc 67 | index 9ad915aff..3faa526a8 100644 68 | --- a/pagespeed/kernel/image/png_optimizer_test.cc 69 | +++ b/pagespeed/kernel/image/png_optimizer_test.cc 70 | @@ -36,6 +36,12 @@ extern "C" { 71 | #else 72 | #include "third_party/libpng/src/png.h" 73 | #endif 74 | + 75 | +#ifdef USE_SYSTEM_ZLIB 76 | +#include "zlib.h" 77 | +#else 78 | +#include "third_party/zlib/zlib.h" 79 | +#endif 80 | } 81 | 82 | namespace { 83 | diff --git a/third_party/libpng/libpng.gyp b/third_party/libpng/libpng.gyp 84 | index cfaafee00..d96a8f74c 100644 85 | --- a/third_party/libpng/libpng.gyp 86 | +++ b/third_party/libpng/libpng.gyp 87 | @@ -22,14 +22,29 @@ 88 | 'dependencies': [ 89 | '../zlib/zlib.gyp:zlib', 90 | ], 91 | + 'actions': [ 92 | + { 93 | + 'action_name': 'copy_libpngconf_prebuilt', 94 | + 'inputs' : [], 95 | + 'outputs': [''], 96 | + 'action': [ 97 | + 'cp', 98 | + '-f', 99 | + '<(DEPTH)/third_party/libpng/src/scripts/pnglibconf.h.prebuilt', 100 | + '<(DEPTH)/third_party/libpng/src/pnglibconf.h', 101 | + ], 102 | + }, 103 | + ], 104 | 'msvs_guid': 'C564F145-9172-42C3-BFCB-6014CA97DBCD', 105 | 'sources': [ 106 | + 'src/pngpriv.h', 107 | 'src/png.c', 108 | 'src/png.h', 109 | 'src/pngconf.h', 110 | + 'src/pngdebug.h', 111 | 'src/pngerror.c', 112 | - 'src/pnggccrd.c', 113 | 'src/pngget.c', 114 | + 'src/pnginfo.h', 115 | 'src/pngmem.c', 116 | 'src/pngpread.c', 117 | 'src/pngread.c', 118 | @@ -37,9 +52,8 @@ 119 | 'src/pngrtran.c', 120 | 'src/pngrutil.c', 121 | 'src/pngset.c', 122 | + 'src/pngstruct.h', 123 | 'src/pngtrans.c', 124 | - 'src/pngusr.h', 125 | - 'src/pngvcrd.c', 126 | 'src/pngwio.c', 127 | 'src/pngwrite.c', 128 | 'src/pngwtran.c', 129 | @@ -54,6 +68,12 @@ 130 | # doesn't like that. This define tells libpng to not 131 | # complain about our inclusion of setjmp.h. 132 | 'PNG_SKIP_SETJMP_CHECK', 133 | + 134 | + # The PNG_FREE_ME_SUPPORTED define was dropped in libpng 135 | + # 1.4.0beta78, with its behavior becoming the default 136 | + # behavior. 137 | + # Hence, we define it ourselves for version >= 1.4.0 138 | + 'PNG_FREE_ME_SUPPORTED', 139 | ], 140 | }, 141 | 'export_dependent_settings': [ 142 | -------------------------------------------------------------------------------- /src/ngx_url_async_fetcher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | // 22 | // Fetch the resources asynchronously in Nginx. The fetcher is called in 23 | // the rewrite thread. 24 | // 25 | // It can communicate with Nginx by pipe. One pipe for one fetcher. 26 | // When new url fetch comes, Fetcher will add it to the pending queue and 27 | // notify the Nginx thread to start the Fetch event. All the events are hooked 28 | // in the main thread's epoll structure. 29 | 30 | #ifndef NET_INSTAWEB_NGX_URL_ASYNC_FETCHER_H_ 31 | #define NET_INSTAWEB_NGX_URL_ASYNC_FETCHER_H_ 32 | 33 | extern "C" { 34 | #include 35 | #include 36 | } 37 | 38 | #include 39 | 40 | #include "ngx_event_connection.h" 41 | 42 | #include "net/instaweb/http/public/url_async_fetcher.h" 43 | #include "pagespeed/kernel/base/basictypes.h" 44 | #include "pagespeed/kernel/base/pool.h" 45 | #include "pagespeed/kernel/base/string.h" 46 | #include "pagespeed/kernel/base/thread_system.h" 47 | 48 | 49 | namespace net_instaweb { 50 | 51 | class AsyncFetch; 52 | class MessageHandler; 53 | class Statistics; 54 | class NgxFetch; 55 | class Variable; 56 | 57 | class NgxUrlAsyncFetcher : public UrlAsyncFetcher { 58 | public: 59 | NgxUrlAsyncFetcher( 60 | const char* proxy, ngx_log_t* log, ngx_msec_t resolver_timeout, 61 | ngx_msec_t fetch_timeout, ngx_resolver_t* resolver, 62 | int max_keepalive_requests, ThreadSystem* thread_system, 63 | MessageHandler* handler); 64 | 65 | ~NgxUrlAsyncFetcher(); 66 | 67 | // It should be called in the module init_process callback function. Do some 68 | // intializations which can't be done in the master process 69 | bool Init(ngx_cycle_t* cycle); 70 | 71 | // shutdown all the fetches. 72 | virtual void ShutDown(); 73 | 74 | // the read handler in the main thread 75 | static void ReadCallback(const ps_event_data& data); 76 | 77 | virtual bool SupportsHttps() const { return false; } 78 | 79 | virtual void Fetch(const GoogleString& url, 80 | MessageHandler* message_handler, 81 | AsyncFetch* callback); 82 | 83 | bool StartFetch(NgxFetch* fetch); 84 | 85 | // Remove the completed fetch from the active fetch set, and put it into a 86 | // completed fetch list to be cleaned up. 87 | void FetchComplete(NgxFetch* fetch); 88 | void PrintActiveFetches(MessageHandler* handler) const; 89 | 90 | // Indicates that it should track the original content length for 91 | // fetched resources. 92 | bool track_original_content_length() { 93 | return track_original_content_length_; 94 | } 95 | void set_track_original_content_length(bool x) { 96 | track_original_content_length_ = x; 97 | } 98 | 99 | typedef Pool NgxFetchPool; 100 | 101 | // AnyPendingFetches is accurate only at the time of call; this is 102 | // used conservatively during shutdown. It counts fetches that have been 103 | // requested by some thread, and can include fetches for which no action 104 | // has yet been taken (ie fetches that are not active). 105 | virtual bool AnyPendingFetches() { 106 | return !active_fetches_.empty(); 107 | } 108 | 109 | // ApproximateNumActiveFetches can under- or over-count and is used only for 110 | // error reporting. 111 | int ApproximateNumActiveFetches() { 112 | return active_fetches_.size(); 113 | } 114 | 115 | void CancelActiveFetches(); 116 | 117 | // These must be accessed with mutex_ held. 118 | bool shutdown() const { return shutdown_; } 119 | void set_shutdown(bool s) { shutdown_ = s; } 120 | 121 | 122 | private: 123 | static void TimeoutHandler(ngx_event_t* tev); 124 | static bool ParseUrl(ngx_url_t* url, ngx_pool_t* pool); 125 | friend class NgxFetch; 126 | 127 | NgxFetchPool active_fetches_; 128 | // Add the pending task to this list 129 | NgxFetchPool pending_fetches_; 130 | NgxFetchPool completed_fetches_; 131 | ngx_url_t proxy_; 132 | 133 | int fetchers_count_; 134 | bool shutdown_; 135 | bool track_original_content_length_; 136 | int64 byte_count_; 137 | ThreadSystem* thread_system_; 138 | MessageHandler* message_handler_; 139 | // Protect the member variable in this class 140 | // active_fetches, pending_fetches 141 | ThreadSystem::CondvarCapableMutex* mutex_; 142 | 143 | ngx_pool_t* pool_; 144 | ngx_log_t* log_; 145 | ngx_resolver_t* resolver_; 146 | int max_keepalive_requests_; 147 | ngx_msec_t resolver_timeout_; 148 | ngx_msec_t fetch_timeout_; 149 | 150 | NgxEventConnection* event_connection_; 151 | 152 | DISALLOW_COPY_AND_ASSIGN(NgxUrlAsyncFetcher); 153 | }; 154 | 155 | } // namespace net_instaweb 156 | 157 | #endif // NET_INSTAWEB_NGX_URL_ASYNC_FETCHER_H_$ 158 | -------------------------------------------------------------------------------- /test/valgrind.sup: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License 17 | 18 | # The first few suppressions can be found in other modules 19 | # and easily found when searched for, and seem false positives. 20 | { 21 | 22 | Memcheck:Param 23 | socketcall.sendmsg(msg.msg_iov[i]) 24 | fun:__sendmsg_nocancel 25 | fun:ngx_write_channel 26 | fun:ngx_signal_worker_processes 27 | fun:ngx_master_process_cycle 28 | fun:main 29 | } 30 | { 31 | 32 | Memcheck:Param 33 | socketcall.sendmsg(msg.msg_iov[i]) 34 | fun:__sendmsg_nocancel 35 | fun:ngx_write_channel 36 | fun:ngx_master_process_cycle 37 | fun:main 38 | } 39 | { 40 | 41 | Memcheck:Param 42 | socketcall.sendmsg(msg.msg_iov[i]) 43 | fun:__sendmsg_nocancel 44 | fun:ngx_write_channel 45 | fun:ngx_pass_open_channel 46 | fun:ngx_start_cache_manager_processes 47 | fun:ngx_master_process_cycle 48 | fun:main 49 | } 50 | { 51 | 52 | Memcheck:Param 53 | socketcall.sendmsg(msg.msg_iov[i]) 54 | fun:__sendmsg_nocancel 55 | fun:ngx_write_channel 56 | fun:ngx_pass_open_channel 57 | fun:ngx_start_cache_manager_processes 58 | fun:ngx_master_process_cycle 59 | fun:main 60 | } 61 | { 62 | 63 | Memcheck:Leak 64 | fun:malloc 65 | fun:ngx_alloc 66 | fun:ngx_event_process_init 67 | fun:ngx_worker_process_init 68 | fun:ngx_worker_process_cycle 69 | fun:ngx_spawn_process 70 | fun:ngx_start_worker_processes 71 | fun:ngx_master_process_cycle 72 | fun:main 73 | } 74 | { 75 | 76 | Memcheck:Param 77 | socketcall.sendmsg(msg.msg_iov[i]) 78 | fun:__sendmsg_nocancel 79 | fun:ngx_write_channel 80 | fun:ngx_pass_open_channel 81 | fun:ngx_start_worker_processes 82 | fun:ngx_master_process_cycle 83 | fun:main 84 | } 85 | 86 | # similar to http://trac.nginx.org/nginx/ticket/369 87 | { 88 | 89 | Memcheck:Param 90 | pwrite64(buf) 91 | obj:/lib/x86_64-linux-gnu/libpthread-2.15.so 92 | fun:ngx_write_file 93 | fun:ngx_write_chain_to_file 94 | fun:ngx_write_chain_to_temp_file 95 | fun:ngx_event_pipe_write_chain_to_temp_file 96 | fun:ngx_event_pipe 97 | fun:ngx_http_upstream_process_upstream 98 | fun:ngx_http_upstream_process_header 99 | fun:ngx_http_upstream_handler 100 | fun:ngx_epoll_process_events 101 | fun:ngx_process_events_and_timers 102 | fun:ngx_worker_process_cycle 103 | } 104 | # Mentioned in https://github.com/apache/incubator-pagespeed-ngx/issues/103 105 | # Assuming a false postives as the issue is closed. 106 | { 107 | 108 | Memcheck:Param 109 | write(buf) 110 | obj:/lib/x86_64-linux-gnu/libpthread-2.15.so 111 | fun:ngx_log_error_core 112 | fun:ngx_http_parse_complex_uri 113 | fun:ngx_http_process_request_uri 114 | fun:ngx_http_process_request_line 115 | fun:ngx_http_wait_request_handler 116 | fun:ngx_epoll_process_events 117 | fun:ngx_process_events_and_timers 118 | fun:ngx_worker_process_cycle 119 | fun:ngx_spawn_process 120 | fun:ngx_start_worker_processes 121 | fun:ngx_master_process_cycle 122 | } 123 | 124 | # Extra suppresions for testing in release mode: 125 | 126 | { 127 | 128 | Memcheck:Cond 129 | fun:_ZN3re24Prog8OptimizeEv 130 | ... 131 | } 132 | { 133 | 134 | Memcheck:Value8 135 | fun:_ZN3re24Prog8OptimizeEv 136 | ... 137 | } 138 | 139 | { 140 | 141 | Memcheck:Cond 142 | fun:_ZN3re2L4AddQEPNS_9SparseSetEi 143 | ... 144 | } 145 | 146 | { 147 | 148 | Memcheck:Value8 149 | fun:_ZN3re2L4AddQEPNS_9SparseSetEi 150 | ... 151 | } 152 | 153 | { 154 | 155 | Memcheck:Value8 156 | fun:_ZN3re23DFA10AddToQueueEPNS0_5WorkqEij 157 | ... 158 | } 159 | 160 | { 161 | 162 | Memcheck:Cond 163 | fun:_ZN3re23DFA10AddToQueueEPNS0_5WorkqEij 164 | ... 165 | } 166 | 167 | { 168 | 169 | Memcheck:Value8 170 | fun:_ZNK3re210SparseSetTIvE8containsEi 171 | ... 172 | } 173 | 174 | { 175 | 176 | Memcheck:Cond 177 | fun:_ZNK3re210SparseSetTIvE8containsEi 178 | ... 179 | } 180 | 181 | { 182 | 183 | Memcheck:Value8 184 | fun:_ZNK3re211SparseArrayIiE9has_indexEi 185 | ... 186 | } 187 | 188 | { 189 | 190 | Memcheck:Cond 191 | fun:_ZNK3re211SparseArrayIiE9has_indexEi 192 | ... 193 | } 194 | -------------------------------------------------------------------------------- /src/ngx_rewrite_driver_factory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | #ifndef NGX_REWRITE_DRIVER_FACTORY_H_ 23 | #define NGX_REWRITE_DRIVER_FACTORY_H_ 24 | 25 | extern "C" { 26 | #include 27 | #if (NGX_THREADS) 28 | #include 29 | #endif 30 | #include 31 | #include 32 | #include 33 | #include 34 | } 35 | 36 | #include 37 | 38 | #include "pagespeed/kernel/base/md5_hasher.h" 39 | #include "pagespeed/kernel/base/scoped_ptr.h" 40 | #include "pagespeed/system/system_rewrite_driver_factory.h" 41 | 42 | namespace net_instaweb { 43 | 44 | class NgxMessageHandler; 45 | class NgxRewriteOptions; 46 | class NgxServerContext; 47 | class NgxUrlAsyncFetcher; 48 | class SharedCircularBuffer; 49 | class SharedMemRefererStatistics; 50 | class SlowWorker; 51 | class Statistics; 52 | class SystemThreadSystem; 53 | 54 | enum ProcessScriptVariablesMode { 55 | kOff, 56 | kLegacyRestricted, 57 | kAll 58 | }; 59 | 60 | class NgxRewriteDriverFactory : public SystemRewriteDriverFactory { 61 | public: 62 | // We take ownership of the thread system. 63 | explicit NgxRewriteDriverFactory( 64 | const ProcessContext& process_context, 65 | SystemThreadSystem* system_thread_system, StringPiece hostname, int port); 66 | virtual ~NgxRewriteDriverFactory(); 67 | virtual Hasher* NewHasher(); 68 | virtual UrlAsyncFetcher* AllocateFetcher(SystemRewriteOptions* config); 69 | virtual MessageHandler* DefaultHtmlParseMessageHandler(); 70 | virtual MessageHandler* DefaultMessageHandler(); 71 | virtual FileSystem* DefaultFileSystem(); 72 | virtual Timer* DefaultTimer(); 73 | virtual NamedLockManager* DefaultLockManager(); 74 | // Create a new RewriteOptions. In this implementation it will be an 75 | // NgxRewriteOptions, and it will have CoreFilters explicitly set. 76 | virtual RewriteOptions* NewRewriteOptions(); 77 | virtual RewriteOptions* NewRewriteOptionsForQuery(); 78 | virtual ServerContext* NewDecodingServerContext(); 79 | // Check resolver configured or not. 80 | bool CheckResolver(); 81 | 82 | // Initializes all the statistics objects created transitively by 83 | // NgxRewriteDriverFactory, including nginx-specific and 84 | // platform-independent statistics. 85 | static void InitStats(Statistics* statistics); 86 | NgxServerContext* MakeNgxServerContext(StringPiece hostname, int port); 87 | virtual ServerContext* NewServerContext(); 88 | virtual void ShutDown(); 89 | 90 | // Starts pagespeed threads if they've not been started already. Must be 91 | // called after the caller has finished any forking it intends to do. 92 | void StartThreads(); 93 | 94 | void SetServerContextMessageHandler(ServerContext* server_context, 95 | ngx_log_t* log); 96 | 97 | NgxMessageHandler* ngx_message_handler() { return ngx_message_handler_; } 98 | 99 | virtual void NonStaticInitStats(Statistics* statistics) { 100 | InitStats(statistics); 101 | } 102 | 103 | void SetMainConf(NgxRewriteOptions* main_conf); 104 | 105 | void set_resolver(ngx_resolver_t* resolver) { 106 | resolver_ = resolver; 107 | } 108 | void set_resolver_timeout(ngx_msec_t resolver_timeout) { 109 | resolver_timeout_ = resolver_timeout == NGX_CONF_UNSET_MSEC ? 110 | 1000 : resolver_timeout; 111 | } 112 | bool use_native_fetcher() { 113 | return use_native_fetcher_; 114 | } 115 | void set_use_native_fetcher(bool x) { 116 | use_native_fetcher_ = x; 117 | } 118 | int native_fetcher_max_keepalive_requests() { 119 | return native_fetcher_max_keepalive_requests_; 120 | } 121 | void set_native_fetcher_max_keepalive_requests(int x) { 122 | native_fetcher_max_keepalive_requests_ = x; 123 | } 124 | ProcessScriptVariablesMode process_script_variables() { 125 | return process_script_variables_mode_; 126 | } 127 | 128 | void LoggingInit(ngx_log_t* log, bool may_install_crash_handler); 129 | 130 | virtual void ShutDownMessageHandlers(); 131 | 132 | virtual void SetCircularBuffer(SharedCircularBuffer* buffer); 133 | 134 | bool SetProcessScriptVariables(ProcessScriptVariablesMode mode) { 135 | if (!process_script_variables_set_) { 136 | process_script_variables_mode_ = mode; 137 | process_script_variables_set_ = true; 138 | return true; 139 | } 140 | return false; 141 | } 142 | 143 | virtual void PrepareForkedProcess(const char* name); 144 | 145 | virtual void NameProcess(const char* name); 146 | 147 | private: 148 | Timer* timer_; 149 | 150 | bool threads_started_; 151 | NgxMessageHandler* ngx_message_handler_; 152 | NgxMessageHandler* ngx_html_parse_message_handler_; 153 | 154 | std::vector ngx_url_async_fetchers_; 155 | ngx_log_t* log_; 156 | ngx_msec_t resolver_timeout_; 157 | ngx_resolver_t* resolver_; 158 | bool use_native_fetcher_; 159 | int native_fetcher_max_keepalive_requests_; 160 | 161 | typedef std::set NgxMessageHandlerSet; 162 | NgxMessageHandlerSet server_context_message_handlers_; 163 | 164 | // Owned by the superclass. 165 | // TODO(jefftk): merge the nginx and apache ways of doing this. 166 | SharedCircularBuffer* ngx_shared_circular_buffer_; 167 | 168 | GoogleString hostname_; 169 | int port_; 170 | ProcessScriptVariablesMode process_script_variables_mode_; 171 | bool process_script_variables_set_; 172 | bool shut_down_; 173 | 174 | DISALLOW_COPY_AND_ASSIGN(NgxRewriteDriverFactory); 175 | }; 176 | 177 | } // namespace net_instaweb 178 | 179 | #endif // NGX_REWRITE_DRIVER_FACTORY_H_ 180 | -------------------------------------------------------------------------------- /src/ngx_event_connection.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | extern "C" { 23 | 24 | #include 25 | 26 | } 27 | 28 | #include "ngx_event_connection.h" 29 | 30 | #include "pagespeed/kernel/base/google_message_handler.h" 31 | #include "pagespeed/kernel/base/message_handler.h" 32 | 33 | namespace net_instaweb { 34 | 35 | NgxEventConnection::NgxEventConnection(callbackPtr callback) 36 | : event_handler_(callback) { 37 | } 38 | 39 | bool NgxEventConnection::Init(ngx_cycle_t* cycle) { 40 | int file_descriptors[2]; 41 | 42 | if (pipe(file_descriptors) != 0) { 43 | ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "pagespeed: pipe() failed"); 44 | return false; 45 | } 46 | if (ngx_nonblocking(file_descriptors[0]) == -1) { 47 | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, 48 | ngx_nonblocking_n "pagespeed: pipe[0] failed"); 49 | } else if (ngx_nonblocking(file_descriptors[1]) == -1) { 50 | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, 51 | ngx_nonblocking_n "pagespeed: pipe[1] failed"); 52 | } else if (!CreateNgxConnection(cycle, file_descriptors[0])) { 53 | ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, 54 | "pagespeed: failed to create connection."); 55 | } else { 56 | pipe_read_fd_ = file_descriptors[0]; 57 | pipe_write_fd_ = file_descriptors[1]; 58 | // Attempt to bump the pipe capacity, because running out of buffer space 59 | // can potentially lead up to writes spinning on EAGAIN. 60 | // See https://github.com/apache/incubator-pagespeed-ngx/issues/1380 61 | // TODO(oschaaf): Consider implementing a queueing mechanism for retrying 62 | // failed writes. 63 | #ifdef F_SETPIPE_SZ 64 | fcntl(pipe_write_fd_, F_SETPIPE_SZ, 200*1024 /* minimal amount of bytes */); 65 | #endif 66 | return true; 67 | } 68 | close(file_descriptors[0]); 69 | close(file_descriptors[1]); 70 | return false; 71 | } 72 | 73 | bool NgxEventConnection::CreateNgxConnection(ngx_cycle_t* cycle, 74 | ngx_fd_t pipe_fd) { 75 | // pipe_fd (the read side of the pipe will end up as c->fd on the 76 | // underlying ngx_connection_t that gets created here) 77 | ngx_int_t rc = ngx_add_channel_event(cycle, pipe_fd, NGX_READ_EVENT, 78 | &NgxEventConnection::ReadEventHandler); 79 | return rc == NGX_OK; 80 | } 81 | 82 | void NgxEventConnection::ReadEventHandler(ngx_event_t* ev) { 83 | ngx_connection_t* c = static_cast(ev->data); 84 | ngx_int_t result = ngx_handle_read_event(ev, 0); 85 | if (result != NGX_OK) { 86 | CHECK(false) << "pagespeed: ngx_handle_read_event error: " << result; 87 | } 88 | 89 | if (ev->timedout) { 90 | ev->timedout = 0; 91 | return; 92 | } 93 | 94 | if (!NgxEventConnection::ReadAndNotify(c->fd)) { 95 | // This was copied from ngx_channel_handler(): for epoll, we need to call 96 | // ngx_del_conn(). Sadly, no documentation as to why. 97 | if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { 98 | ngx_del_conn(c, 0); 99 | } 100 | ngx_close_connection(c); 101 | ngx_del_event(ev, NGX_READ_EVENT, 0); 102 | } 103 | } 104 | 105 | // Deserialize ps_event_data's from the pipe as they become available. 106 | // Subsequently do some bookkeeping, cleanup, and error checking to keep 107 | // the mess out of ps_base_fetch_handler. 108 | bool NgxEventConnection::ReadAndNotify(ngx_fd_t fd) { 109 | while (true) { 110 | // We read only one ps_event_data at a time for now: 111 | // We can end up recursing all the way and end up calling ourselves here. 112 | // If that happens in the middle of looping over multiple ps_event_data's we 113 | // have obtained with read(), the results from the next read() will make us 114 | // process events out of order. Which can give headaches. 115 | // Alternatively, we could maintain a queue to make sure we process in 116 | // sequence 117 | ps_event_data data; 118 | ngx_int_t size = read(fd, static_cast(&data), sizeof(data)); 119 | 120 | if (size == -1) { 121 | if (errno == EINTR) { 122 | continue; 123 | // TODO(oschaaf): should we worry about spinning here? 124 | } else if (ngx_errno == EAGAIN || ngx_errno == EWOULDBLOCK) { 125 | return true; 126 | } 127 | } 128 | 129 | if (size <= 0) { 130 | return false; 131 | } 132 | 133 | data.connection->event_handler_(data); 134 | return true; 135 | } 136 | } 137 | 138 | bool NgxEventConnection::WriteEvent(void* sender) { 139 | return WriteEvent('X' /* Anything char is fine */, sender); 140 | } 141 | 142 | bool NgxEventConnection::WriteEvent(char type, void* sender) { 143 | ssize_t size = 0; 144 | ps_event_data data; 145 | 146 | ngx_memzero(&data, sizeof(data)); 147 | data.type = type; 148 | data.sender = sender; 149 | data.connection = this; 150 | 151 | while (true) { 152 | size = write(pipe_write_fd_, 153 | static_cast(&data), sizeof(data)); 154 | if (size == sizeof(data)) { 155 | return true; 156 | } else if (size == -1) { 157 | // TODO(oschaaf): should we worry about spinning here? 158 | if (ngx_errno == EINTR || ngx_errno == EAGAIN 159 | || ngx_errno == EWOULDBLOCK) { 160 | continue; 161 | } else { 162 | return false; 163 | } 164 | } else { 165 | CHECK(false) << "pagespeed: unexpected return value from write(): " 166 | << size; 167 | } 168 | } 169 | CHECK(false) << "Should not get here"; 170 | return false; 171 | } 172 | 173 | // Reads and processes what is available in the pipe. 174 | void NgxEventConnection::Drain() { 175 | NgxEventConnection::ReadAndNotify(pipe_read_fd_); 176 | } 177 | 178 | void NgxEventConnection::Shutdown() { 179 | close(pipe_write_fd_); 180 | close(pipe_read_fd_); 181 | } 182 | 183 | } // namespace net_instaweb 184 | -------------------------------------------------------------------------------- /src/ngx_fetch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | // 22 | // PageSpeed needs some way to talk to the internet and request resources. For 23 | // example, if it's optimizing www.example.com/index.html and it sees html with 24 | // and images.example.com is authorized 25 | // for rewriting in the config, then it needs to fetch cat.jpg from 26 | // images.example.com and optimize it. In apache (always) and nginx (by 27 | // default) we use a fetcher called "serf". This works fine, but it does run 28 | // its own event loop. To be more efficient, this is a "native" fetcher that 29 | // uses nginx's event loop. 30 | // 31 | // The fetch is started by the main thread. It will fetch the remote resource 32 | // from the specific url asynchronously. 33 | 34 | #ifndef NET_INSTAWEB_NGX_FETCH_H_ 35 | #define NET_INSTAWEB_NGX_FETCH_H_ 36 | 37 | extern "C" { 38 | #include 39 | #include 40 | #include 41 | } 42 | 43 | #include "ngx_url_async_fetcher.h" 44 | #include 45 | #include "net/instaweb/http/public/url_async_fetcher.h" 46 | #include "pagespeed/kernel/base/basictypes.h" 47 | #include "pagespeed/kernel/base/pool.h" 48 | #include "pagespeed/kernel/base/string.h" 49 | #include "pagespeed/kernel/http/response_headers.h" 50 | #include "pagespeed/kernel/http/response_headers_parser.h" 51 | #include "pagespeed/kernel/thread/pthread_mutex.h" 52 | 53 | 54 | namespace net_instaweb { 55 | 56 | typedef bool (*response_handler_pt)(ngx_connection_t* c); 57 | 58 | class NgxUrlAsyncFetcher; 59 | class NgxConnection; 60 | 61 | class NgxConnection : public PoolElement { 62 | public: 63 | NgxConnection(MessageHandler* handler, int max_keepalive_requests); 64 | ~NgxConnection(); 65 | void SetSock(u_char *sockaddr, socklen_t socklen) { 66 | socklen_ = socklen; 67 | ngx_memcpy(&sockaddr_, sockaddr, socklen); 68 | } 69 | // Close ensures that NgxConnection deletes itself at the appropriate time, 70 | // which can be after receiving a non-keepalive response, or when the remote 71 | // server closes the connection when the NgxConnection is pooled and idle. 72 | void Close(); 73 | 74 | // Once keepalive is disabled, it can't be toggled back on. 75 | void set_keepalive(bool k) { keepalive_ = keepalive_ && k; } 76 | bool keepalive() { return keepalive_; } 77 | 78 | typedef Pool NgxConnectionPool; 79 | 80 | static NgxConnection* Connect(ngx_peer_connection_t* pc, 81 | MessageHandler* handler, 82 | int max_keepalive_requests); 83 | static void IdleWriteHandler(ngx_event_t* ev); 84 | static void IdleReadHandler(ngx_event_t* ev); 85 | // Terminate will cleanup any idle connections upon shutdown. 86 | static void Terminate(); 87 | 88 | static NgxConnectionPool connection_pool; 89 | static PthreadMutex connection_pool_mutex; 90 | 91 | // c_ is owned by NgxConnection and freed in ::Close() 92 | ngx_connection_t* c_; 93 | static const int64 keepalive_timeout_ms; 94 | static const GoogleString ka_header; 95 | 96 | private: 97 | int max_keepalive_requests_; 98 | bool keepalive_; 99 | socklen_t socklen_; 100 | u_char sockaddr_[NGX_SOCKADDRLEN]; 101 | MessageHandler* handler_; 102 | 103 | DISALLOW_COPY_AND_ASSIGN(NgxConnection); 104 | }; 105 | 106 | class NgxFetch : public PoolElement { 107 | public: 108 | NgxFetch(const GoogleString& url, 109 | AsyncFetch* async_fetch, 110 | MessageHandler* message_handler, 111 | ngx_log_t* log); 112 | ~NgxFetch(); 113 | 114 | // Start the fetch. 115 | bool Start(NgxUrlAsyncFetcher* fetcher); 116 | // Show the completed url, for logging purposes. 117 | const char* str_url(); 118 | // This fetch task is done. Call Done() on the async_fetch. It will copy the 119 | // buffer to cache. 120 | void CallbackDone(bool success); 121 | 122 | // Show the bytes received. 123 | size_t bytes_received(); 124 | void bytes_received_add(int64 x); 125 | int64 fetch_start_ms(); 126 | void set_fetch_start_ms(int64 start_ms); 127 | int64 fetch_end_ms(); 128 | void set_fetch_end_ms(int64 end_ms); 129 | MessageHandler* message_handler(); 130 | 131 | int get_major_version() { 132 | return static_cast(status_->http_version / 1000); 133 | } 134 | int get_minor_version() { 135 | return static_cast(status_->http_version % 1000); 136 | } 137 | int get_status_code() { 138 | return static_cast(status_->code); 139 | } 140 | ngx_event_t* timeout_event() { 141 | return timeout_event_; 142 | } 143 | void set_timeout_event(ngx_event_t* x) { 144 | timeout_event_ = x; 145 | } 146 | void release_resolver() { 147 | if (resolver_ctx_ != NULL && resolver_ctx_ != NGX_NO_RESOLVER) { 148 | ngx_resolve_name_done(resolver_ctx_); 149 | resolver_ctx_ = NULL; 150 | } 151 | } 152 | 153 | private: 154 | response_handler_pt response_handler; 155 | // Do the initialized work and start the resolver work. 156 | bool Init(); 157 | bool ParseUrl(); 158 | // Prepare the request and write it to remote server. 159 | int InitRequest(); 160 | // Create the connection with remote server. 161 | int Connect(); 162 | void set_response_handler(response_handler_pt handler) { 163 | response_handler = handler; 164 | } 165 | // Only the Static functions could be used in callbacks. 166 | static void ResolveDoneHandler(ngx_resolver_ctx_t* ctx); 167 | // Write the request. 168 | static void ConnectionWriteHandler(ngx_event_t* wev); 169 | // Wait for the response. 170 | static void ConnectionReadHandler(ngx_event_t* rev); 171 | // Read and parse the first status line. 172 | static bool HandleStatusLine(ngx_connection_t* c); 173 | // Read and parse the HTTP headers. 174 | static bool HandleHeader(ngx_connection_t* c); 175 | // Read the response body. 176 | static bool HandleBody(ngx_connection_t* c); 177 | // Cancel the fetch when it's timeout. 178 | static void TimeoutHandler(ngx_event_t* tev); 179 | 180 | // Add the pagespeed User-Agent. 181 | void FixUserAgent(); 182 | void FixHost(); 183 | 184 | const GoogleString str_url_; 185 | ngx_url_t url_; 186 | NgxUrlAsyncFetcher* fetcher_; 187 | AsyncFetch* async_fetch_; 188 | ResponseHeadersParser parser_; 189 | MessageHandler* message_handler_; 190 | int64 bytes_received_; 191 | int64 fetch_start_ms_; 192 | int64 fetch_end_ms_; 193 | bool done_; 194 | int64 content_length_; 195 | bool content_length_known_; 196 | 197 | struct sockaddr_in sin_; 198 | ngx_log_t* log_; 199 | ngx_buf_t* out_; 200 | ngx_buf_t* in_; 201 | ngx_pool_t* pool_; 202 | ngx_http_request_t* r_; 203 | ngx_http_status_t* status_; 204 | ngx_event_t* timeout_event_; 205 | NgxConnection* connection_; 206 | ngx_resolver_ctx_t* resolver_ctx_; 207 | 208 | DISALLOW_COPY_AND_ASSIGN(NgxFetch); 209 | }; 210 | 211 | } // namespace net_instaweb 212 | 213 | #endif // NET_INSTAWEB_NGX_FETCH_H_ 214 | -------------------------------------------------------------------------------- /src/ngx_base_fetch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | // 22 | // Collects output from pagespeed and buffers it until nginx asks for it. 23 | // Notifies nginx via NgxEventConnection to call ReadCallback() when 24 | // the headers are computed, when a flush should be performed, and when done. 25 | // 26 | // - nginx creates a base fetch and passes it to a new proxy fetch. 27 | // - The proxy fetch manages rewriting and thread complexity, and through 28 | // several chained steps passes rewritten html to HandleWrite(). 29 | // - Written data is buffered. 30 | // - When HandleHeadersComplete(), HandleFlush(), or HandleDone() is called by 31 | // PSOL, events are written to NgxEventConnection which will end up being 32 | // handled by ReadCallback() on nginx's thread. 33 | // When applicable, request processing will be continued via a call to 34 | // ps_base_fetch_handler(). 35 | // - ps_base_fetch_handler() will pull the header and body bytes from PSOL 36 | // via CollectAccumulatedWrites() and write those to the module's output. 37 | // 38 | // This class is referred to in three places: the proxy fetch, nginx's request, 39 | // and pending events written to the associated NgxEventConnection. It must stay 40 | // alive until the proxy fetch and nginx request are finished, and no more 41 | // events are pending. 42 | // - The proxy fetch will call Done() to indicate this. 43 | // - nginx will call Detach() when the associated request is handled 44 | // completely (e.g. the request context is about to be destroyed). 45 | // - ReadCallback() will call DecrementRefCount() on instances associated to 46 | // events it handles. 47 | // 48 | // When the last reference is dropped, this class will delete itself. 49 | // 50 | // TODO(jmarantz): consider sharing the cache-invalidation infrastructure 51 | // with ApacheFetch, using a common base class. 52 | 53 | #ifndef NGX_BASE_FETCH_H_ 54 | #define NGX_BASE_FETCH_H_ 55 | 56 | extern "C" { 57 | #include 58 | } 59 | 60 | #include 61 | 62 | #include "ngx_pagespeed.h" 63 | 64 | #include "ngx_event_connection.h" 65 | #include "ngx_server_context.h" 66 | 67 | #include "net/instaweb/http/public/async_fetch.h" 68 | #include "net/instaweb/rewriter/public/rewrite_options.h" 69 | #include "pagespeed/kernel/base/string.h" 70 | #include "pagespeed/kernel/http/headers.h" 71 | 72 | namespace net_instaweb { 73 | 74 | enum NgxBaseFetchType { 75 | kIproLookup, 76 | kHtmlTransform, 77 | kPageSpeedResource, 78 | kAdminPage, 79 | kPageSpeedProxy 80 | }; 81 | 82 | class NgxBaseFetch : public AsyncFetch { 83 | public: 84 | NgxBaseFetch(StringPiece url, ngx_http_request_t* r, 85 | NgxServerContext* server_context, 86 | const RequestContextPtr& request_ctx, 87 | PreserveCachingHeaders preserve_caching_headers, 88 | NgxBaseFetchType base_fetch_type, 89 | const RewriteOptions* options); 90 | virtual ~NgxBaseFetch(); 91 | 92 | // Statically initializes event_connection, require for PSOL and nginx to 93 | // communicate. 94 | static bool Initialize(ngx_cycle_t* cycle); 95 | 96 | // Attempts to finish up request processing queued up in the named pipe and 97 | // PSOL for a fixed amount of time. If time is up, a fast and rough shutdown 98 | // is attempted. 99 | // Statically terminates and NULLS event_connection. 100 | static void Terminate(); 101 | 102 | static void ReadCallback(const ps_event_data& data); 103 | 104 | // Puts a chain in link_ptr if we have any output data buffered. Returns 105 | // NGX_OK on success, NGX_ERROR on errors. If there's no data to send, sends 106 | // data only if Done() has been called. Indicates the end of output by 107 | // setting last_buf on the last buffer in the chain. 108 | // 109 | // Sets link_ptr to a chain of as many buffers are needed for the output. 110 | // 111 | // Called by nginx in response to seeing a byte on the pipe. 112 | ngx_int_t CollectAccumulatedWrites(ngx_chain_t** link_ptr); 113 | 114 | // Copies response headers into headers_out. 115 | // 116 | // Called by nginx before calling CollectAccumulatedWrites() for the first 117 | // time for resource fetches. Not called at all for proxy fetches. 118 | ngx_int_t CollectHeaders(ngx_http_headers_out_t* headers_out); 119 | 120 | // Called by nginx to decrement the refcount. 121 | int DecrementRefCount(); 122 | 123 | // Called by pagespeed to increment the refcount. 124 | int IncrementRefCount(); 125 | 126 | // Detach() is called when the nginx side releases this base fetch. It 127 | // sets detached_ to true and decrements the refcount. We need to know 128 | // this to be able to handle events which nginx request context has been 129 | // released while the event was in-flight. 130 | void Detach() { detached_ = true; DecrementRefCount(); } 131 | 132 | bool detached() { return detached_; } 133 | 134 | ngx_http_request_t* request() { return request_; } 135 | NgxBaseFetchType base_fetch_type() { return base_fetch_type_; } 136 | 137 | bool IsCachedResultValid(const ResponseHeaders& headers) override; 138 | 139 | private: 140 | virtual bool HandleWrite(const StringPiece& sp, MessageHandler* handler); 141 | virtual bool HandleFlush(MessageHandler* handler); 142 | virtual void HandleHeadersComplete(); 143 | virtual void HandleDone(bool success); 144 | 145 | // Indicate to nginx that we would like it to call 146 | // CollectAccumulatedWrites(). 147 | void RequestCollection(char type); 148 | 149 | // Lock must be acquired first. 150 | // Returns: 151 | // NGX_ERROR: failure 152 | // NGX_AGAIN: still has buffer to send, need to checkout link_ptr 153 | // NGX_OK: done, HandleDone has been called 154 | // Allocates an nginx buffer, copies our buffer_ contents into it, clears 155 | // buffer_. 156 | ngx_int_t CopyBufferToNginx(ngx_chain_t** link_ptr); 157 | 158 | void Lock(); 159 | void Unlock(); 160 | 161 | // Called by Done() and Release(). Decrements our reference count, and if 162 | // it's zero we delete ourself. 163 | int DecrefAndDeleteIfUnreferenced(); 164 | 165 | static NgxEventConnection* event_connection; 166 | 167 | // Live count of NgxBaseFetch instances that are currently in use. 168 | static int active_base_fetches; 169 | 170 | GoogleString url_; 171 | ngx_http_request_t* request_; 172 | GoogleString buffer_; 173 | NgxServerContext* server_context_; 174 | const RewriteOptions* options_; 175 | bool need_flush_; 176 | bool done_called_; 177 | bool last_buf_sent_; 178 | // How many active references there are to this fetch. Starts at two, 179 | // decremented once when Done() is called and once when Detach() is called. 180 | // Incremented for each event written by pagespeed for this NgxBaseFetch, and 181 | // decremented on the nginx side for each event read for it. 182 | int references_; 183 | pthread_mutex_t mutex_; 184 | NgxBaseFetchType base_fetch_type_; 185 | PreserveCachingHeaders preserve_caching_headers_; 186 | // Set to true just before the nginx side releases its reference 187 | bool detached_; 188 | bool suppress_; 189 | 190 | DISALLOW_COPY_AND_ASSIGN(NgxBaseFetch); 191 | }; 192 | 193 | } // namespace net_instaweb 194 | 195 | #endif // NGX_BASE_FETCH_H_ 196 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-mainline/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG ALPINE_VERSION=3.8 2 | 3 | ######################## 4 | # Build pagespeed psol # 5 | ######################## 6 | FROM alpine:$ALPINE_VERSION as pagespeed 7 | 8 | # Check https://github.com/apache/incubator-pagespeed-mod/tags 9 | ARG MOD_PAGESPEED_TAG=v1.13.35.2 10 | 11 | RUN apk add --no-cache \ 12 | apache2-dev \ 13 | apr-dev \ 14 | apr-util-dev \ 15 | build-base \ 16 | curl \ 17 | gettext-dev \ 18 | git \ 19 | gperf \ 20 | icu-dev \ 21 | libjpeg-turbo-dev \ 22 | libpng-dev \ 23 | libressl-dev \ 24 | pcre-dev \ 25 | py-setuptools \ 26 | zlib-dev \ 27 | ; 28 | 29 | WORKDIR /usr/src 30 | RUN git clone -b ${MOD_PAGESPEED_TAG} \ 31 | --recurse-submodules \ 32 | --depth=1 \ 33 | -c advice.detachedHead=false \ 34 | -j`nproc` \ 35 | https://github.com/apache/incubator-pagespeed-mod.git \ 36 | modpagespeed \ 37 | ; 38 | 39 | WORKDIR /usr/src/modpagespeed 40 | 41 | COPY patches/modpagespeed/*.patch ./ 42 | 43 | RUN for i in *.patch; do printf "\r\nApplying patch ${i%%.*}\r\n"; patch -p1 < $i || exit 1; done 44 | 45 | WORKDIR /usr/src/modpagespeed/tools/gyp 46 | RUN ./setup.py install 47 | 48 | WORKDIR /usr/src/modpagespeed 49 | 50 | RUN build/gyp_chromium --depth=. \ 51 | -D use_system_libs=1 \ 52 | && \ 53 | cd /usr/src/modpagespeed/pagespeed/automatic && \ 54 | make psol BUILDTYPE=Release \ 55 | CFLAGS+="-I/usr/include/apr-1" \ 56 | CXXFLAGS+="-I/usr/include/apr-1 -DUCHAR_TYPE=uint16_t" \ 57 | -j`nproc` \ 58 | ; 59 | 60 | RUN mkdir -p /usr/src/ngxpagespeed/psol/lib/Release/linux/x64 && \ 61 | mkdir -p /usr/src/ngxpagespeed/psol/include/out/Release && \ 62 | cp -R out/Release/obj /usr/src/ngxpagespeed/psol/include/out/Release/ && \ 63 | cp -R pagespeed/automatic/pagespeed_automatic.a /usr/src/ngxpagespeed/psol/lib/Release/linux/x64/ && \ 64 | cp -R net \ 65 | pagespeed \ 66 | testing \ 67 | third_party \ 68 | url \ 69 | /usr/src/ngxpagespeed/psol/include/ \ 70 | ; 71 | 72 | 73 | ########################################## 74 | # Build Nginx with support for PageSpeed # 75 | ########################################## 76 | FROM alpine:$ALPINE_VERSION AS nginx 77 | 78 | # Check https://github.com/apache/incubator-pagespeed-ngx/tags 79 | ARG NGX_PAGESPEED_TAG=v1.13.35.2-stable 80 | 81 | # Check http://nginx.org/en/download.html for the latest version. 82 | ARG NGINX_VERSION=1.15.6 83 | ARG NGINX_PGPKEY=520A9993A1C052F8 84 | ARG NGINX_BUILD_CONFIG="\ 85 | --prefix=/etc/nginx \ 86 | --sbin-path=/usr/sbin/nginx \ 87 | --modules-path=/usr/lib/nginx/modules \ 88 | --conf-path=/etc/nginx/nginx.conf \ 89 | --error-log-path=/var/log/nginx/error.log \ 90 | --http-log-path=/var/log/nginx/access.log \ 91 | --pid-path=/var/run/nginx.pid \ 92 | --lock-path=/var/run/nginx.lock \ 93 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 94 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 95 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 96 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 97 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 98 | --user=nginx \ 99 | --group=nginx \ 100 | --with-http_ssl_module \ 101 | --with-http_realip_module \ 102 | --with-http_addition_module \ 103 | --with-http_sub_module \ 104 | --with-http_dav_module \ 105 | --with-http_flv_module \ 106 | --with-http_mp4_module \ 107 | --with-http_gunzip_module \ 108 | --with-http_gzip_static_module \ 109 | --with-http_random_index_module \ 110 | --with-http_secure_link_module \ 111 | --with-http_stub_status_module \ 112 | --with-http_auth_request_module \ 113 | --with-http_xslt_module=dynamic \ 114 | --with-http_image_filter_module=dynamic \ 115 | --with-http_geoip_module=dynamic \ 116 | --with-threads \ 117 | --with-stream \ 118 | --with-stream_ssl_module \ 119 | --with-stream_ssl_preread_module \ 120 | --with-stream_realip_module \ 121 | --with-stream_geoip_module=dynamic \ 122 | --with-http_slice_module \ 123 | --with-mail \ 124 | --with-mail_ssl_module \ 125 | --with-compat \ 126 | --with-file-aio \ 127 | --with-http_v2_module \ 128 | " 129 | 130 | RUN apk add --no-cache \ 131 | apr-dev \ 132 | apr-util-dev \ 133 | build-base \ 134 | ca-certificates \ 135 | gd-dev \ 136 | geoip-dev \ 137 | git \ 138 | gnupg \ 139 | icu-dev \ 140 | libjpeg-turbo-dev \ 141 | libpng-dev \ 142 | libxslt-dev \ 143 | linux-headers \ 144 | libressl-dev \ 145 | pcre-dev \ 146 | tar \ 147 | zlib-dev \ 148 | ; 149 | 150 | WORKDIR /usr/src 151 | RUN git clone -b ${NGX_PAGESPEED_TAG} \ 152 | --recurse-submodules \ 153 | --shallow-submodules \ 154 | --depth=1 \ 155 | -c advice.detachedHead=false \ 156 | -j`nproc` \ 157 | https://github.com/apache/incubator-pagespeed-ngx.git \ 158 | ngxpagespeed \ 159 | ; 160 | 161 | RUN wget https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ 162 | https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz.asc && \ 163 | (gpg --keyserver ha.pool.sks-keyservers.net --keyserver-options timeout=10 --recv-keys ${NGINX_PGPKEY} || \ 164 | gpg --keyserver hkp://keyserver.ubuntu.com:80 --keyserver-options timeout=10 --recv-keys ${NGINX_PGPKEY} || \ 165 | gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --keyserver-options timeout=10 --recv-keys $NGINX_PGPKEY} ) && \ 166 | gpg --trusted-key ${NGINX_PGPKEY} --verify nginx-${NGINX_VERSION}.tar.gz.asc 167 | 168 | COPY --from=pagespeed /usr/src/ngxpagespeed /usr/src/ngxpagespeed/ 169 | 170 | WORKDIR /usr/src/nginx 171 | 172 | RUN tar zxf ../nginx-${NGINX_VERSION}.tar.gz --strip-components=1 -C . && \ 173 | ./configure \ 174 | ${NGINX_BUILD_CONFIG} \ 175 | --add-module=/usr/src/ngxpagespeed \ 176 | --with-ld-opt="-Wl,-z,relro,--start-group -lapr-1 -laprutil-1 -licudata -licuuc -lpng -lturbojpeg -ljpeg" \ 177 | && \ 178 | make install -j`nproc` 179 | 180 | RUN rm -rf /etc/nginx/html/ && \ 181 | mkdir /etc/nginx/conf.d/ && \ 182 | mkdir -p /usr/share/nginx/html/ && \ 183 | sed -i 's|^|

\n|' html/index.html && \ 184 | install -m644 html/index.html /usr/share/nginx/html/ && \ 185 | install -m644 html/50x.html /usr/share/nginx/html/ && \ 186 | ln -s ../../usr/lib/nginx/modules /etc/nginx/modules && \ 187 | strip /usr/sbin/nginx* \ 188 | /usr/lib/nginx/modules/*.so \ 189 | ; 190 | 191 | COPY conf/nginx.conf /etc/nginx/nginx.conf 192 | COPY conf/nginx.vh.default.conf /etc/nginx/conf.d/default.conf 193 | COPY pagespeed.png /usr/share/nginx/html/ 194 | 195 | 196 | ########################################## 197 | # Combine everything with minimal layers # 198 | ########################################## 199 | FROM alpine:$ALPINE_VERSION 200 | LABEL maintainer="Nico Berlee " \ 201 | version.mod-pagespeed="1.13.35.2" \ 202 | version.nginx="1.15.6" \ 203 | version.ngx-pagespeed="1.13.35.2" 204 | 205 | COPY --from=pagespeed /usr/bin/envsubst /usr/local/bin 206 | COPY --from=nginx /usr/sbin/nginx /usr/sbin/nginx 207 | COPY --from=nginx /usr/lib/nginx/modules/ /usr/lib/nginx/modules/ 208 | COPY --from=nginx /etc/nginx /etc/nginx 209 | COPY --from=nginx /usr/share/nginx/html/ /usr/share/nginx/html/ 210 | 211 | RUN apk --no-cache upgrade && \ 212 | scanelf --needed --nobanner --format '%n#p' /usr/sbin/nginx /usr/lib/nginx/modules/*.so /usr/local/bin/envsubst \ 213 | | tr ',' '\n' \ 214 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 215 | | xargs apk add --no-cache \ 216 | && \ 217 | apk add --no-cache tzdata 218 | 219 | RUN addgroup -S nginx && \ 220 | adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx && \ 221 | install -g nginx -o nginx -d /var/cache/ngx_pagespeed && \ 222 | mkdir -p /var/log/nginx && \ 223 | ln -sf /dev/stdout /var/log/nginx/access.log && \ 224 | ln -sf /dev/stderr /var/log/nginx/error.log 225 | 226 | EXPOSE 80 227 | 228 | STOPSIGNAL SIGTERM 229 | 230 | CMD ["/usr/sbin/nginx", "-g", "daemon off;"] 231 | -------------------------------------------------------------------------------- /docker/alpine-3.8/nginx-stable/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG ALPINE_VERSION=3.8 2 | 3 | ######################## 4 | # Build pagespeed psol # 5 | ######################## 6 | FROM alpine:$ALPINE_VERSION as pagespeed 7 | 8 | # Check https://github.com/apache/incubator-pagespeed-mod/tags 9 | ARG MOD_PAGESPEED_TAG=v1.13.35.2 10 | 11 | RUN apk add --no-cache \ 12 | apache2-dev \ 13 | apr-dev \ 14 | apr-util-dev \ 15 | build-base \ 16 | curl \ 17 | gettext-dev \ 18 | git \ 19 | gperf \ 20 | icu-dev \ 21 | libjpeg-turbo-dev \ 22 | libpng-dev \ 23 | libressl-dev \ 24 | pcre-dev \ 25 | py-setuptools \ 26 | zlib-dev \ 27 | ; 28 | 29 | WORKDIR /usr/src 30 | RUN git clone -b ${MOD_PAGESPEED_TAG} \ 31 | --recurse-submodules \ 32 | --depth=1 \ 33 | -c advice.detachedHead=false \ 34 | -j`nproc` \ 35 | https://github.com/apache/incubator-pagespeed-mod.git \ 36 | modpagespeed \ 37 | ; 38 | 39 | WORKDIR /usr/src/modpagespeed 40 | 41 | COPY patches/modpagespeed/*.patch ./ 42 | 43 | RUN for i in *.patch; do printf "\r\nApplying patch ${i%%.*}\r\n"; patch -p1 < $i || exit 1; done 44 | 45 | WORKDIR /usr/src/modpagespeed/tools/gyp 46 | RUN ./setup.py install 47 | 48 | WORKDIR /usr/src/modpagespeed 49 | 50 | RUN build/gyp_chromium --depth=. \ 51 | -D use_system_libs=1 \ 52 | && \ 53 | cd /usr/src/modpagespeed/pagespeed/automatic && \ 54 | make psol BUILDTYPE=Release \ 55 | CFLAGS+="-I/usr/include/apr-1" \ 56 | CXXFLAGS+="-I/usr/include/apr-1 -DUCHAR_TYPE=uint16_t" \ 57 | -j`nproc` \ 58 | ; 59 | 60 | RUN mkdir -p /usr/src/ngxpagespeed/psol/lib/Release/linux/x64 && \ 61 | mkdir -p /usr/src/ngxpagespeed/psol/include/out/Release && \ 62 | cp -R out/Release/obj /usr/src/ngxpagespeed/psol/include/out/Release/ && \ 63 | cp -R pagespeed/automatic/pagespeed_automatic.a /usr/src/ngxpagespeed/psol/lib/Release/linux/x64/ && \ 64 | cp -R net \ 65 | pagespeed \ 66 | testing \ 67 | third_party \ 68 | url \ 69 | /usr/src/ngxpagespeed/psol/include/ \ 70 | ; 71 | 72 | 73 | ########################################## 74 | # Build Nginx with support for PageSpeed # 75 | ########################################## 76 | FROM alpine:$ALPINE_VERSION AS nginx 77 | 78 | # Check https://github.com/apache/incubator-pagespeed-ngx/tags 79 | ARG NGX_PAGESPEED_TAG=v1.13.35.2-stable 80 | 81 | # Check http://nginx.org/en/download.html for the latest version. 82 | ARG NGINX_VERSION=1.14.1 83 | ARG NGINX_PGPKEY=520A9993A1C052F8 84 | ARG NGINX_BUILD_CONFIG="\ 85 | --prefix=/etc/nginx \ 86 | --sbin-path=/usr/sbin/nginx \ 87 | --modules-path=/usr/lib/nginx/modules \ 88 | --conf-path=/etc/nginx/nginx.conf \ 89 | --error-log-path=/var/log/nginx/error.log \ 90 | --http-log-path=/var/log/nginx/access.log \ 91 | --pid-path=/var/run/nginx.pid \ 92 | --lock-path=/var/run/nginx.lock \ 93 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 94 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 95 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 96 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 97 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 98 | --user=nginx \ 99 | --group=nginx \ 100 | --with-http_ssl_module \ 101 | --with-http_realip_module \ 102 | --with-http_addition_module \ 103 | --with-http_sub_module \ 104 | --with-http_dav_module \ 105 | --with-http_flv_module \ 106 | --with-http_mp4_module \ 107 | --with-http_gunzip_module \ 108 | --with-http_gzip_static_module \ 109 | --with-http_random_index_module \ 110 | --with-http_secure_link_module \ 111 | --with-http_stub_status_module \ 112 | --with-http_auth_request_module \ 113 | --with-http_xslt_module=dynamic \ 114 | --with-http_image_filter_module=dynamic \ 115 | --with-http_geoip_module=dynamic \ 116 | --with-threads \ 117 | --with-stream \ 118 | --with-stream_ssl_module \ 119 | --with-stream_ssl_preread_module \ 120 | --with-stream_realip_module \ 121 | --with-stream_geoip_module=dynamic \ 122 | --with-http_slice_module \ 123 | --with-mail \ 124 | --with-mail_ssl_module \ 125 | --with-compat \ 126 | --with-file-aio \ 127 | --with-http_v2_module \ 128 | " 129 | 130 | RUN apk add --no-cache \ 131 | apr-dev \ 132 | apr-util-dev \ 133 | build-base \ 134 | ca-certificates \ 135 | gd-dev \ 136 | geoip-dev \ 137 | git \ 138 | gnupg \ 139 | icu-dev \ 140 | libjpeg-turbo-dev \ 141 | libpng-dev \ 142 | libxslt-dev \ 143 | linux-headers \ 144 | libressl-dev \ 145 | pcre-dev \ 146 | tar \ 147 | zlib-dev \ 148 | ; 149 | 150 | WORKDIR /usr/src 151 | RUN git clone -b ${NGX_PAGESPEED_TAG} \ 152 | --recurse-submodules \ 153 | --shallow-submodules \ 154 | --depth=1 \ 155 | -c advice.detachedHead=false \ 156 | -j`nproc` \ 157 | https://github.com/apache/incubator-pagespeed-ngx.git \ 158 | ngxpagespeed \ 159 | ; 160 | 161 | RUN wget https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ 162 | https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz.asc && \ 163 | (gpg --keyserver ha.pool.sks-keyservers.net --keyserver-options timeout=10 --recv-keys ${NGINX_PGPKEY} || \ 164 | gpg --keyserver hkp://keyserver.ubuntu.com:80 --keyserver-options timeout=10 --recv-keys ${NGINX_PGPKEY} || \ 165 | gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --keyserver-options timeout=10 --recv-keys $NGINX_PGPKEY} ) && \ 166 | gpg --trusted-key ${NGINX_PGPKEY} --verify nginx-${NGINX_VERSION}.tar.gz.asc 167 | 168 | COPY --from=pagespeed /usr/src/ngxpagespeed /usr/src/ngxpagespeed/ 169 | 170 | WORKDIR /usr/src/nginx 171 | 172 | RUN tar zxf ../nginx-${NGINX_VERSION}.tar.gz --strip-components=1 -C . && \ 173 | ./configure \ 174 | ${NGINX_BUILD_CONFIG} \ 175 | --add-module=/usr/src/ngxpagespeed \ 176 | --with-ld-opt="-Wl,-z,relro,--start-group -lapr-1 -laprutil-1 -licudata -licuuc -lpng -lturbojpeg -ljpeg" \ 177 | && \ 178 | make install -j`nproc` 179 | 180 | RUN rm -rf /etc/nginx/html/ && \ 181 | mkdir /etc/nginx/conf.d/ && \ 182 | mkdir -p /usr/share/nginx/html/ && \ 183 | sed -i 's|^|

\n|' html/index.html && \ 184 | install -m644 html/index.html /usr/share/nginx/html/ && \ 185 | install -m644 html/50x.html /usr/share/nginx/html/ && \ 186 | ln -s ../../usr/lib/nginx/modules /etc/nginx/modules && \ 187 | strip /usr/sbin/nginx* \ 188 | /usr/lib/nginx/modules/*.so \ 189 | ; 190 | 191 | COPY conf/nginx.conf /etc/nginx/nginx.conf 192 | COPY conf/nginx.vh.default.conf /etc/nginx/conf.d/default.conf 193 | COPY pagespeed.png /usr/share/nginx/html/ 194 | 195 | 196 | ########################################## 197 | # Combine everything with minimal layers # 198 | ########################################## 199 | FROM alpine:$ALPINE_VERSION 200 | LABEL maintainer="Nico Berlee " \ 201 | version.mod-pagespeed="1.13.35.2" \ 202 | version.nginx="1.14.1" \ 203 | version.ngx-pagespeed="1.13.35.2" 204 | 205 | COPY --from=pagespeed /usr/bin/envsubst /usr/local/bin 206 | COPY --from=nginx /usr/sbin/nginx /usr/sbin/nginx 207 | COPY --from=nginx /usr/lib/nginx/modules/ /usr/lib/nginx/modules/ 208 | COPY --from=nginx /etc/nginx /etc/nginx 209 | COPY --from=nginx /usr/share/nginx/html/ /usr/share/nginx/html/ 210 | 211 | RUN apk --no-cache upgrade && \ 212 | scanelf --needed --nobanner --format '%n#p' /usr/sbin/nginx /usr/lib/nginx/modules/*.so /usr/local/bin/envsubst \ 213 | | tr ',' '\n' \ 214 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 215 | | xargs apk add --no-cache \ 216 | && \ 217 | apk add --no-cache tzdata 218 | 219 | RUN addgroup -S nginx && \ 220 | adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx && \ 221 | install -g nginx -o nginx -d /var/cache/ngx_pagespeed && \ 222 | mkdir -p /var/log/nginx && \ 223 | ln -sf /dev/stdout /var/log/nginx/access.log && \ 224 | ln -sf /dev/stderr /var/log/nginx/error.log 225 | 226 | EXPOSE 80 227 | 228 | STOPSIGNAL SIGTERM 229 | 230 | CMD ["/usr/sbin/nginx", "-g", "daemon off;"] 231 | 232 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-mainline/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG ALPINE_VERSION=edge 2 | 3 | ######################## 4 | # Build pagespeed psol # 5 | ######################## 6 | FROM alpine:$ALPINE_VERSION as pagespeed 7 | 8 | # Check https://github.com/apache/incubator-pagespeed-mod/tags 9 | ARG MOD_PAGESPEED_TAG=v1.13.35.2 10 | 11 | RUN apk add --no-cache \ 12 | apache2-dev \ 13 | apr-dev \ 14 | apr-util-dev \ 15 | build-base \ 16 | curl \ 17 | gettext-dev \ 18 | git \ 19 | gperf \ 20 | icu-dev \ 21 | libjpeg-turbo-dev \ 22 | libpng-dev \ 23 | libressl-dev \ 24 | pcre-dev \ 25 | py-setuptools \ 26 | zlib-dev \ 27 | ; 28 | 29 | WORKDIR /usr/src 30 | RUN git clone -b ${MOD_PAGESPEED_TAG} \ 31 | --recurse-submodules \ 32 | --depth=1 \ 33 | -c advice.detachedHead=false \ 34 | -j`nproc` \ 35 | https://github.com/apache/incubator-pagespeed-mod.git \ 36 | modpagespeed \ 37 | ; 38 | 39 | WORKDIR /usr/src/modpagespeed 40 | 41 | COPY patches/modpagespeed/*.patch ./ 42 | 43 | RUN for i in *.patch; do printf "\r\nApplying patch ${i%%.*}\r\n"; patch -p1 < $i || exit 1; done 44 | 45 | WORKDIR /usr/src/modpagespeed/tools/gyp 46 | RUN ./setup.py install 47 | 48 | WORKDIR /usr/src/modpagespeed 49 | 50 | RUN build/gyp_chromium --depth=. \ 51 | -D use_system_libs=1 \ 52 | && \ 53 | cd /usr/src/modpagespeed/pagespeed/automatic && \ 54 | make psol BUILDTYPE=Release \ 55 | CFLAGS+="-I/usr/include/apr-1" \ 56 | CXXFLAGS+="-I/usr/include/apr-1 -DUCHAR_TYPE=uint16_t" \ 57 | -j`nproc` \ 58 | ; 59 | 60 | RUN mkdir -p /usr/src/ngxpagespeed/psol/lib/Release/linux/x64 && \ 61 | mkdir -p /usr/src/ngxpagespeed/psol/include/out/Release && \ 62 | cp -R out/Release/obj /usr/src/ngxpagespeed/psol/include/out/Release/ && \ 63 | cp -R pagespeed/automatic/pagespeed_automatic.a /usr/src/ngxpagespeed/psol/lib/Release/linux/x64/ && \ 64 | cp -R net \ 65 | pagespeed \ 66 | testing \ 67 | third_party \ 68 | url \ 69 | /usr/src/ngxpagespeed/psol/include/ \ 70 | ; 71 | 72 | 73 | ########################################## 74 | # Build Nginx with support for PageSpeed # 75 | ########################################## 76 | FROM alpine:$ALPINE_VERSION AS nginx 77 | 78 | # Check https://github.com/apache/incubator-pagespeed-ngx/tags 79 | ARG NGX_PAGESPEED_TAG=v1.13.35.2-stable 80 | 81 | # Check http://nginx.org/en/download.html for the latest version. 82 | ARG NGINX_VERSION=1.15.6 83 | ARG NGINX_PGPKEY=520A9993A1C052F8 84 | ARG NGINX_BUILD_CONFIG="\ 85 | --prefix=/etc/nginx \ 86 | --sbin-path=/usr/sbin/nginx \ 87 | --modules-path=/usr/lib/nginx/modules \ 88 | --conf-path=/etc/nginx/nginx.conf \ 89 | --error-log-path=/var/log/nginx/error.log \ 90 | --http-log-path=/var/log/nginx/access.log \ 91 | --pid-path=/var/run/nginx.pid \ 92 | --lock-path=/var/run/nginx.lock \ 93 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 94 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 95 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 96 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 97 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 98 | --user=nginx \ 99 | --group=nginx \ 100 | --with-http_ssl_module \ 101 | --with-http_realip_module \ 102 | --with-http_addition_module \ 103 | --with-http_sub_module \ 104 | --with-http_dav_module \ 105 | --with-http_flv_module \ 106 | --with-http_mp4_module \ 107 | --with-http_gunzip_module \ 108 | --with-http_gzip_static_module \ 109 | --with-http_random_index_module \ 110 | --with-http_secure_link_module \ 111 | --with-http_stub_status_module \ 112 | --with-http_auth_request_module \ 113 | --with-http_xslt_module=dynamic \ 114 | --with-http_image_filter_module=dynamic \ 115 | --with-http_geoip_module=dynamic \ 116 | --with-threads \ 117 | --with-stream \ 118 | --with-stream_ssl_module \ 119 | --with-stream_ssl_preread_module \ 120 | --with-stream_realip_module \ 121 | --with-stream_geoip_module=dynamic \ 122 | --with-http_slice_module \ 123 | --with-mail \ 124 | --with-mail_ssl_module \ 125 | --with-compat \ 126 | --with-file-aio \ 127 | --with-http_v2_module \ 128 | " 129 | 130 | RUN apk add --no-cache \ 131 | apr-dev \ 132 | apr-util-dev \ 133 | build-base \ 134 | ca-certificates \ 135 | gd-dev \ 136 | geoip-dev \ 137 | git \ 138 | gnupg \ 139 | icu-dev \ 140 | libjpeg-turbo-dev \ 141 | libpng-dev \ 142 | libxslt-dev \ 143 | linux-headers \ 144 | libressl-dev \ 145 | pcre-dev \ 146 | tar \ 147 | zlib-dev \ 148 | ; 149 | 150 | WORKDIR /usr/src 151 | RUN git clone -b ${NGX_PAGESPEED_TAG} \ 152 | --recurse-submodules \ 153 | --shallow-submodules \ 154 | --depth=1 \ 155 | -c advice.detachedHead=false \ 156 | -j`nproc` \ 157 | https://github.com/apache/incubator-pagespeed-ngx.git \ 158 | ngxpagespeed \ 159 | ; 160 | 161 | RUN wget https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ 162 | https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz.asc && \ 163 | (gpg --keyserver ha.pool.sks-keyservers.net --keyserver-options timeout=10 --recv-keys ${NGINX_PGPKEY} || \ 164 | gpg --keyserver hkp://keyserver.ubuntu.com:80 --keyserver-options timeout=10 --recv-keys ${NGINX_PGPKEY} || \ 165 | gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --keyserver-options timeout=10 --recv-keys $NGINX_PGPKEY} ) && \ 166 | gpg --trusted-key ${NGINX_PGPKEY} --verify nginx-${NGINX_VERSION}.tar.gz.asc 167 | 168 | COPY --from=pagespeed /usr/src/ngxpagespeed /usr/src/ngxpagespeed/ 169 | 170 | WORKDIR /usr/src/nginx 171 | 172 | RUN tar zxf ../nginx-${NGINX_VERSION}.tar.gz --strip-components=1 -C . && \ 173 | ./configure \ 174 | ${NGINX_BUILD_CONFIG} \ 175 | --add-module=/usr/src/ngxpagespeed \ 176 | --with-ld-opt="-Wl,-z,relro,--start-group -lapr-1 -laprutil-1 -licudata -licuuc -lpng -lturbojpeg -ljpeg" \ 177 | && \ 178 | make install -j`nproc` 179 | 180 | RUN rm -rf /etc/nginx/html/ && \ 181 | mkdir /etc/nginx/conf.d/ && \ 182 | mkdir -p /usr/share/nginx/html/ && \ 183 | sed -i 's|^|

\n|' html/index.html && \ 184 | install -m644 html/index.html /usr/share/nginx/html/ && \ 185 | install -m644 html/50x.html /usr/share/nginx/html/ && \ 186 | ln -s ../../usr/lib/nginx/modules /etc/nginx/modules && \ 187 | strip /usr/sbin/nginx* \ 188 | /usr/lib/nginx/modules/*.so \ 189 | ; 190 | 191 | COPY conf/nginx.conf /etc/nginx/nginx.conf 192 | COPY conf/nginx.vh.default.conf /etc/nginx/conf.d/default.conf 193 | COPY pagespeed.png /usr/share/nginx/html/ 194 | 195 | 196 | ########################################## 197 | # Combine everything with minimal layers # 198 | ########################################## 199 | FROM alpine:$ALPINE_VERSION 200 | LABEL maintainer="Nico Berlee " \ 201 | version.mod-pagespeed="1.13.35.2" \ 202 | version.nginx="1.15.6" \ 203 | version.ngx-pagespeed="1.13.35.2" 204 | 205 | COPY --from=pagespeed /usr/bin/envsubst /usr/local/bin 206 | COPY --from=nginx /usr/sbin/nginx /usr/sbin/nginx 207 | COPY --from=nginx /usr/lib/nginx/modules/ /usr/lib/nginx/modules/ 208 | COPY --from=nginx /etc/nginx /etc/nginx 209 | COPY --from=nginx /usr/share/nginx/html/ /usr/share/nginx/html/ 210 | 211 | RUN apk --no-cache upgrade && \ 212 | scanelf --needed --nobanner --format '%n#p' /usr/sbin/nginx /usr/lib/nginx/modules/*.so /usr/local/bin/envsubst \ 213 | | tr ',' '\n' \ 214 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 215 | | xargs apk add --no-cache \ 216 | && \ 217 | apk add --no-cache tzdata 218 | 219 | RUN addgroup -S nginx && \ 220 | adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx && \ 221 | install -g nginx -o nginx -d /var/cache/ngx_pagespeed && \ 222 | mkdir -p /var/log/nginx && \ 223 | ln -sf /dev/stdout /var/log/nginx/access.log && \ 224 | ln -sf /dev/stderr /var/log/nginx/error.log 225 | 226 | EXPOSE 80 227 | 228 | STOPSIGNAL SIGTERM 229 | 230 | CMD ["/usr/sbin/nginx", "-g", "daemon off;"] 231 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG ALPINE_VERSION=edge 2 | 3 | ######################## 4 | # Build pagespeed psol # 5 | ######################## 6 | FROM alpine:$ALPINE_VERSION as pagespeed 7 | 8 | # Check https://github.com/apache/incubator-pagespeed-mod/tags 9 | ARG MOD_PAGESPEED_TAG=v1.13.35.2 10 | 11 | RUN apk add --no-cache \ 12 | apache2-dev \ 13 | apr-dev \ 14 | apr-util-dev \ 15 | build-base \ 16 | curl \ 17 | gettext-dev \ 18 | git \ 19 | gperf \ 20 | icu-dev \ 21 | libjpeg-turbo-dev \ 22 | libpng-dev \ 23 | libressl-dev \ 24 | pcre-dev \ 25 | py-setuptools \ 26 | zlib-dev \ 27 | ; 28 | 29 | WORKDIR /usr/src 30 | RUN git clone -b ${MOD_PAGESPEED_TAG} \ 31 | --recurse-submodules \ 32 | --depth=1 \ 33 | -c advice.detachedHead=false \ 34 | -j`nproc` \ 35 | https://github.com/apache/incubator-pagespeed-mod.git \ 36 | modpagespeed \ 37 | ; 38 | 39 | WORKDIR /usr/src/modpagespeed 40 | 41 | COPY patches/modpagespeed/*.patch ./ 42 | 43 | RUN for i in *.patch; do printf "\r\nApplying patch ${i%%.*}\r\n"; patch -p1 < $i || exit 1; done 44 | 45 | WORKDIR /usr/src/modpagespeed/tools/gyp 46 | RUN ./setup.py install 47 | 48 | WORKDIR /usr/src/modpagespeed 49 | 50 | RUN build/gyp_chromium --depth=. \ 51 | -D use_system_libs=1 \ 52 | && \ 53 | cd /usr/src/modpagespeed/pagespeed/automatic && \ 54 | make psol BUILDTYPE=Release \ 55 | CFLAGS+="-I/usr/include/apr-1" \ 56 | CXXFLAGS+="-I/usr/include/apr-1 -DUCHAR_TYPE=uint16_t" \ 57 | -j`nproc` \ 58 | ; 59 | 60 | RUN mkdir -p /usr/src/ngxpagespeed/psol/lib/Release/linux/x64 && \ 61 | mkdir -p /usr/src/ngxpagespeed/psol/include/out/Release && \ 62 | cp -R out/Release/obj /usr/src/ngxpagespeed/psol/include/out/Release/ && \ 63 | cp -R pagespeed/automatic/pagespeed_automatic.a /usr/src/ngxpagespeed/psol/lib/Release/linux/x64/ && \ 64 | cp -R net \ 65 | pagespeed \ 66 | testing \ 67 | third_party \ 68 | url \ 69 | /usr/src/ngxpagespeed/psol/include/ \ 70 | ; 71 | 72 | 73 | ########################################## 74 | # Build Nginx with support for PageSpeed # 75 | ########################################## 76 | FROM alpine:$ALPINE_VERSION AS nginx 77 | 78 | # Check https://github.com/apache/incubator-pagespeed-ngx/tags 79 | ARG NGX_PAGESPEED_TAG=v1.13.35.2-stable 80 | 81 | # Check http://nginx.org/en/download.html for the latest version. 82 | ARG NGINX_VERSION=1.14.1 83 | ARG NGINX_PGPKEY=520A9993A1C052F8 84 | ARG NGINX_BUILD_CONFIG="\ 85 | --prefix=/etc/nginx \ 86 | --sbin-path=/usr/sbin/nginx \ 87 | --modules-path=/usr/lib/nginx/modules \ 88 | --conf-path=/etc/nginx/nginx.conf \ 89 | --error-log-path=/var/log/nginx/error.log \ 90 | --http-log-path=/var/log/nginx/access.log \ 91 | --pid-path=/var/run/nginx.pid \ 92 | --lock-path=/var/run/nginx.lock \ 93 | --http-client-body-temp-path=/var/cache/nginx/client_temp \ 94 | --http-proxy-temp-path=/var/cache/nginx/proxy_temp \ 95 | --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \ 96 | --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \ 97 | --http-scgi-temp-path=/var/cache/nginx/scgi_temp \ 98 | --user=nginx \ 99 | --group=nginx \ 100 | --with-http_ssl_module \ 101 | --with-http_realip_module \ 102 | --with-http_addition_module \ 103 | --with-http_sub_module \ 104 | --with-http_dav_module \ 105 | --with-http_flv_module \ 106 | --with-http_mp4_module \ 107 | --with-http_gunzip_module \ 108 | --with-http_gzip_static_module \ 109 | --with-http_random_index_module \ 110 | --with-http_secure_link_module \ 111 | --with-http_stub_status_module \ 112 | --with-http_auth_request_module \ 113 | --with-http_xslt_module=dynamic \ 114 | --with-http_image_filter_module=dynamic \ 115 | --with-http_geoip_module=dynamic \ 116 | --with-threads \ 117 | --with-stream \ 118 | --with-stream_ssl_module \ 119 | --with-stream_ssl_preread_module \ 120 | --with-stream_realip_module \ 121 | --with-stream_geoip_module=dynamic \ 122 | --with-http_slice_module \ 123 | --with-mail \ 124 | --with-mail_ssl_module \ 125 | --with-compat \ 126 | --with-file-aio \ 127 | --with-http_v2_module \ 128 | " 129 | 130 | RUN apk add --no-cache \ 131 | apr-dev \ 132 | apr-util-dev \ 133 | build-base \ 134 | ca-certificates \ 135 | gd-dev \ 136 | geoip-dev \ 137 | git \ 138 | gnupg \ 139 | icu-dev \ 140 | libjpeg-turbo-dev \ 141 | libpng-dev \ 142 | libxslt-dev \ 143 | linux-headers \ 144 | libressl-dev \ 145 | pcre-dev \ 146 | tar \ 147 | zlib-dev \ 148 | ; 149 | 150 | WORKDIR /usr/src 151 | RUN git clone -b ${NGX_PAGESPEED_TAG} \ 152 | --recurse-submodules \ 153 | --shallow-submodules \ 154 | --depth=1 \ 155 | -c advice.detachedHead=false \ 156 | -j`nproc` \ 157 | https://github.com/apache/incubator-pagespeed-ngx.git \ 158 | ngxpagespeed \ 159 | ; 160 | 161 | RUN wget https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ 162 | https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz.asc && \ 163 | (gpg --keyserver ha.pool.sks-keyservers.net --keyserver-options timeout=10 --recv-keys ${NGINX_PGPKEY} || \ 164 | gpg --keyserver hkp://keyserver.ubuntu.com:80 --keyserver-options timeout=10 --recv-keys ${NGINX_PGPKEY} || \ 165 | gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --keyserver-options timeout=10 --recv-keys $NGINX_PGPKEY} ) && \ 166 | gpg --trusted-key ${NGINX_PGPKEY} --verify nginx-${NGINX_VERSION}.tar.gz.asc 167 | 168 | COPY --from=pagespeed /usr/src/ngxpagespeed /usr/src/ngxpagespeed/ 169 | 170 | WORKDIR /usr/src/nginx 171 | 172 | RUN tar zxf ../nginx-${NGINX_VERSION}.tar.gz --strip-components=1 -C . 173 | 174 | COPY patches/ngx/*.patch ./ 175 | 176 | RUN for i in *.patch; do printf "\r\nApplying patch ${i%%.*}\r\n"; patch -p1 < $i || exit 1; done 177 | 178 | RUN ./configure \ 179 | ${NGINX_BUILD_CONFIG} \ 180 | --add-module=/usr/src/ngxpagespeed \ 181 | --with-ld-opt="-Wl,-z,relro,--start-group -lapr-1 -laprutil-1 -licudata -licuuc -lpng -lturbojpeg -ljpeg" \ 182 | && \ 183 | make install -j`nproc` 184 | 185 | RUN rm -rf /etc/nginx/html/ && \ 186 | mkdir /etc/nginx/conf.d/ && \ 187 | mkdir -p /usr/share/nginx/html/ && \ 188 | sed -i 's|^|

\n|' html/index.html && \ 189 | install -m644 html/index.html /usr/share/nginx/html/ && \ 190 | install -m644 html/50x.html /usr/share/nginx/html/ && \ 191 | ln -s ../../usr/lib/nginx/modules /etc/nginx/modules && \ 192 | strip /usr/sbin/nginx* \ 193 | /usr/lib/nginx/modules/*.so \ 194 | ; 195 | 196 | COPY conf/nginx.conf /etc/nginx/nginx.conf 197 | COPY conf/nginx.vh.default.conf /etc/nginx/conf.d/default.conf 198 | COPY pagespeed.png /usr/share/nginx/html/ 199 | 200 | 201 | ########################################## 202 | # Combine everything with minimal layers # 203 | ########################################## 204 | FROM alpine:$ALPINE_VERSION 205 | LABEL maintainer="Nico Berlee " \ 206 | version.mod-pagespeed="1.13.35.2" \ 207 | version.nginx="1.14.1" \ 208 | version.ngx-pagespeed="1.13.35.2" 209 | 210 | COPY --from=pagespeed /usr/bin/envsubst /usr/local/bin 211 | COPY --from=nginx /usr/sbin/nginx /usr/sbin/nginx 212 | COPY --from=nginx /usr/lib/nginx/modules/ /usr/lib/nginx/modules/ 213 | COPY --from=nginx /etc/nginx /etc/nginx 214 | COPY --from=nginx /usr/share/nginx/html/ /usr/share/nginx/html/ 215 | 216 | RUN apk --no-cache upgrade && \ 217 | scanelf --needed --nobanner --format '%n#p' /usr/sbin/nginx /usr/lib/nginx/modules/*.so /usr/local/bin/envsubst \ 218 | | tr ',' '\n' \ 219 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 220 | | xargs apk add --no-cache \ 221 | && \ 222 | apk add --no-cache tzdata 223 | 224 | RUN addgroup -S nginx && \ 225 | adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx && \ 226 | install -g nginx -o nginx -d /var/cache/ngx_pagespeed && \ 227 | mkdir -p /var/log/nginx && \ 228 | ln -sf /dev/stdout /var/log/nginx/access.log && \ 229 | ln -sf /dev/stderr /var/log/nginx/error.log 230 | 231 | EXPOSE 80 232 | 233 | STOPSIGNAL SIGTERM 234 | 235 | CMD ["/usr/sbin/nginx", "-g", "daemon off;"] 236 | -------------------------------------------------------------------------------- /docker/alpine-edge/nginx-stable/patches/ngx/gcc8.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c 2 | index bc43f53ed9..3eec1b7dd0 100644 3 | --- a/src/http/modules/ngx_http_fastcgi_module.c 4 | +++ b/src/http/modules/ngx_http_fastcgi_module.c 5 | @@ -3264,7 +3264,8 @@ ngx_http_fastcgi_init_params(ngx_conf_t *cf, ngx_http_fastcgi_loc_conf_t *conf, 6 | return NGX_ERROR; 7 | } 8 | 9 | - copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 10 | + copy->code = (ngx_http_script_code_pt) (void *) 11 | + ngx_http_script_copy_len_code; 12 | copy->len = src[i].key.len; 13 | 14 | copy = ngx_array_push_n(params->lengths, 15 | @@ -3273,7 +3274,8 @@ ngx_http_fastcgi_init_params(ngx_conf_t *cf, ngx_http_fastcgi_loc_conf_t *conf, 16 | return NGX_ERROR; 17 | } 18 | 19 | - copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 20 | + copy->code = (ngx_http_script_code_pt) (void *) 21 | + ngx_http_script_copy_len_code; 22 | copy->len = src[i].skip_empty; 23 | 24 | 25 | diff --git a/src/http/modules/ngx_http_grpc_module.c b/src/http/modules/ngx_http_grpc_module.c 26 | index 837ad9a2ea..300d927047 100644 27 | --- a/src/http/modules/ngx_http_grpc_module.c 28 | +++ b/src/http/modules/ngx_http_grpc_module.c 29 | @@ -4389,7 +4389,8 @@ ngx_http_grpc_init_headers(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf, 30 | return NGX_ERROR; 31 | } 32 | 33 | - copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 34 | + copy->code = (ngx_http_script_code_pt) (void *) 35 | + ngx_http_script_copy_len_code; 36 | copy->len = src[i].key.len; 37 | 38 | size = (sizeof(ngx_http_script_copy_code_t) 39 | diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c 40 | index c9ad638df9..e7f829d653 100644 41 | --- a/src/http/modules/ngx_http_proxy_module.c 42 | +++ b/src/http/modules/ngx_http_proxy_module.c 43 | @@ -3493,7 +3493,8 @@ ngx_http_proxy_init_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf, 44 | return NGX_ERROR; 45 | } 46 | 47 | - copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 48 | + copy->code = (ngx_http_script_code_pt) (void *) 49 | + ngx_http_script_copy_len_code; 50 | copy->len = src[i].key.len; 51 | 52 | size = (sizeof(ngx_http_script_copy_code_t) 53 | diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c 54 | index 3fb227b28c..9bd45bd136 100644 55 | --- a/src/http/modules/ngx_http_scgi_module.c 56 | +++ b/src/http/modules/ngx_http_scgi_module.c 57 | @@ -1724,7 +1724,8 @@ ngx_http_scgi_init_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf, 58 | return NGX_ERROR; 59 | } 60 | 61 | - copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 62 | + copy->code = (ngx_http_script_code_pt) (void *) 63 | + ngx_http_script_copy_len_code; 64 | copy->len = src[i].key.len + 1; 65 | 66 | copy = ngx_array_push_n(params->lengths, 67 | @@ -1733,7 +1734,8 @@ ngx_http_scgi_init_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf, 68 | return NGX_ERROR; 69 | } 70 | 71 | - copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 72 | + copy->code = (ngx_http_script_code_pt) (void *) 73 | + ngx_http_script_copy_len_code; 74 | copy->len = src[i].skip_empty; 75 | 76 | 77 | diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c 78 | index 124da4db56..238bcf8a3b 100644 79 | --- a/src/http/modules/ngx_http_uwsgi_module.c 80 | +++ b/src/http/modules/ngx_http_uwsgi_module.c 81 | @@ -1987,7 +1987,8 @@ ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf, 82 | return NGX_ERROR; 83 | } 84 | 85 | - copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 86 | + copy->code = (ngx_http_script_code_pt) (void *) 87 | + ngx_http_script_copy_len_code; 88 | copy->len = src[i].key.len; 89 | 90 | copy = ngx_array_push_n(params->lengths, 91 | @@ -1996,7 +1997,8 @@ ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf, 92 | return NGX_ERROR; 93 | } 94 | 95 | - copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 96 | + copy->code = (ngx_http_script_code_pt) (void *) 97 | + ngx_http_script_copy_len_code; 98 | copy->len = src[i].skip_empty; 99 | 100 | 101 | diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c 102 | index 96f3ec6965..1a87735617 100644 103 | --- a/src/http/ngx_http_script.c 104 | +++ b/src/http/ngx_http_script.c 105 | @@ -695,7 +695,8 @@ ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value, 106 | return NGX_ERROR; 107 | } 108 | 109 | - code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; 110 | + code->code = (ngx_http_script_code_pt) (void *) 111 | + ngx_http_script_copy_len_code; 112 | code->len = len; 113 | 114 | size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1) 115 | @@ -784,7 +785,8 @@ ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name) 116 | return NGX_ERROR; 117 | } 118 | 119 | - code->code = (ngx_http_script_code_pt) ngx_http_script_copy_var_len_code; 120 | + code->code = (ngx_http_script_code_pt) (void *) 121 | + ngx_http_script_copy_var_len_code; 122 | code->index = (uintptr_t) index; 123 | 124 | code = ngx_http_script_add_code(*sc->values, 125 | @@ -1178,8 +1180,8 @@ ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n) 126 | return NGX_ERROR; 127 | } 128 | 129 | - code->code = (ngx_http_script_code_pt) 130 | - ngx_http_script_copy_capture_len_code; 131 | + code->code = (ngx_http_script_code_pt) (void *) 132 | + ngx_http_script_copy_capture_len_code; 133 | code->n = 2 * n; 134 | 135 | 136 | @@ -1293,7 +1295,8 @@ ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc) 137 | return NGX_ERROR; 138 | } 139 | 140 | - code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code; 141 | + code->code = (ngx_http_script_code_pt) (void *) 142 | + ngx_http_script_full_name_len_code; 143 | code->conf_prefix = sc->conf_prefix; 144 | 145 | code = ngx_http_script_add_code(*sc->values, 146 | diff --git a/src/stream/ngx_stream_script.c b/src/stream/ngx_stream_script.c 147 | index aa555ca2c1..b00e7086f7 100644 148 | --- a/src/stream/ngx_stream_script.c 149 | +++ b/src/stream/ngx_stream_script.c 150 | @@ -587,7 +587,8 @@ ngx_stream_script_add_copy_code(ngx_stream_script_compile_t *sc, 151 | return NGX_ERROR; 152 | } 153 | 154 | - code->code = (ngx_stream_script_code_pt) ngx_stream_script_copy_len_code; 155 | + code->code = (ngx_stream_script_code_pt) (void *) 156 | + ngx_stream_script_copy_len_code; 157 | code->len = len; 158 | 159 | size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1) 160 | @@ -677,8 +678,8 @@ ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name) 161 | return NGX_ERROR; 162 | } 163 | 164 | - code->code = (ngx_stream_script_code_pt) 165 | - ngx_stream_script_copy_var_len_code; 166 | + code->code = (ngx_stream_script_code_pt) (void *) 167 | + ngx_stream_script_copy_var_len_code; 168 | code->index = (uintptr_t) index; 169 | 170 | code = ngx_stream_script_add_code(*sc->values, 171 | @@ -767,8 +768,8 @@ ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc, 172 | return NGX_ERROR; 173 | } 174 | 175 | - code->code = (ngx_stream_script_code_pt) 176 | - ngx_stream_script_copy_capture_len_code; 177 | + code->code = (ngx_stream_script_code_pt) (void *) 178 | + ngx_stream_script_copy_capture_len_code; 179 | code->n = 2 * n; 180 | 181 | 182 | @@ -859,7 +860,7 @@ ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc) 183 | return NGX_ERROR; 184 | } 185 | 186 | - code->code = (ngx_stream_script_code_pt) 187 | + code->code = (ngx_stream_script_code_pt) (void *) 188 | ngx_stream_script_full_name_len_code; 189 | code->conf_prefix = sc->conf_prefix; 190 | 191 | -------------------------------------------------------------------------------- /src/ngx_rewrite_options.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | // Manage configuration for pagespeed. Compare to ApacheConfig. 23 | 24 | #ifndef NGX_REWRITE_OPTIONS_H_ 25 | #define NGX_REWRITE_OPTIONS_H_ 26 | 27 | extern "C" { 28 | #include 29 | #include 30 | #include 31 | } 32 | 33 | #include 34 | 35 | #include "ngx_rewrite_driver_factory.h" 36 | 37 | #include "net/instaweb/rewriter/public/rewrite_options.h" 38 | #include "pagespeed/kernel/base/message_handler.h" 39 | #include "pagespeed/kernel/base/ref_counted_ptr.h" 40 | #include "pagespeed/kernel/base/stl_util.h" // for STLDeleteElements 41 | #include "pagespeed/system/system_rewrite_options.h" 42 | 43 | #define NGX_PAGESPEED_MAX_ARGS 10 44 | 45 | namespace net_instaweb { 46 | 47 | class NgxRewriteDriverFactory; 48 | 49 | class ScriptArgIndex { 50 | public: 51 | explicit ScriptArgIndex(ngx_http_script_compile_t* script, int index) 52 | : script_(script), index_(index) { 53 | CHECK(script != NULL); 54 | CHECK(index > 0 && index < NGX_PAGESPEED_MAX_ARGS); 55 | } 56 | 57 | virtual ~ScriptArgIndex() {} 58 | 59 | ngx_http_script_compile_t* script() { return script_; } 60 | int index() { return index_; } 61 | 62 | private: 63 | // Not owned. 64 | ngx_http_script_compile_t* script_; 65 | int index_; 66 | }; 67 | 68 | // Refcounted, because the ScriptArgIndexes inside data_ can be shared between 69 | // different rewriteoptions. 70 | class ScriptLine : public RefCounted { 71 | public: 72 | explicit ScriptLine(StringPiece* args, int n_args, 73 | RewriteOptions::OptionScope scope) 74 | : n_args_(n_args), 75 | scope_(scope) { 76 | 77 | for (int i = 0; i < n_args; i++) { 78 | args_[i] = args[i]; 79 | } 80 | } 81 | 82 | virtual ~ScriptLine() { 83 | STLDeleteElements(&data_); 84 | data_.clear(); 85 | } 86 | 87 | void AddScriptAndArgIndex(ngx_http_script_compile_t* script, 88 | int script_index) { 89 | CHECK(script != NULL); 90 | CHECK(script_index < NGX_PAGESPEED_MAX_ARGS); 91 | data_.push_back(new ScriptArgIndex(script, script_index)); 92 | } 93 | 94 | int n_args() { return n_args_;} 95 | StringPiece* args() { return args_;} 96 | RewriteOptions::OptionScope scope() { return scope_; } 97 | std::vector& data() { 98 | return data_; 99 | } 100 | 101 | private: 102 | StringPiece args_[NGX_PAGESPEED_MAX_ARGS]; 103 | int n_args_; 104 | RewriteOptions::OptionScope scope_; 105 | std::vector data_; 106 | 107 | DISALLOW_COPY_AND_ASSIGN(ScriptLine); 108 | }; 109 | 110 | class NgxRewriteOptions : public SystemRewriteOptions { 111 | public: 112 | // See rewrite_options::Initialize and ::Terminate 113 | static void Initialize(); 114 | static void Terminate(); 115 | 116 | NgxRewriteOptions(const StringPiece& description, 117 | ThreadSystem* thread_system); 118 | explicit NgxRewriteOptions(ThreadSystem* thread_system); 119 | virtual ~NgxRewriteOptions() { } 120 | 121 | // args is an array of n_args StringPieces together representing a directive. 122 | // For example: 123 | // ["RewriteLevel", "PassThrough"] 124 | // or 125 | // ["EnableFilters", "combine_css,extend_cache,rewrite_images"] 126 | // or 127 | // ["ShardDomain", "example.com", "s1.example.com,s2.example.com"] 128 | // Apply the directive, returning NGX_CONF_OK on success or an error message 129 | // on failure. 130 | // 131 | // pool is a memory pool for allocating error strings. 132 | // cf is only required when compile_scripts is true 133 | // when compile_scripts is true, the rewrite_options will be prepared 134 | // for replacing any script $variables encountered in args. when false, 135 | // script variables will be substituted using the prepared rewrite options. 136 | const char* ParseAndSetOptions( 137 | StringPiece* args, int n_args, ngx_pool_t* pool, MessageHandler* handler, 138 | NgxRewriteDriverFactory* driver_factory, OptionScope scope, 139 | ngx_conf_t* cf, ProcessScriptVariablesMode script_mode); 140 | bool ExecuteScriptVariables( 141 | ngx_http_request_t* r, MessageHandler* handler, 142 | NgxRewriteDriverFactory* driver_factory); 143 | void CopyScriptLinesTo(NgxRewriteOptions* destination) const; 144 | void AppendScriptLinesTo(NgxRewriteOptions* destination) const; 145 | 146 | // Make an identical copy of these options and return it. 147 | virtual NgxRewriteOptions* Clone() const; 148 | 149 | // Returns a suitably down cast version of 'instance' if it is an instance 150 | // of this class, NULL if not. 151 | static const NgxRewriteOptions* DynamicCast(const RewriteOptions* instance); 152 | static NgxRewriteOptions* DynamicCast(RewriteOptions* instance); 153 | 154 | const GoogleString& statistics_path() const { 155 | return statistics_path_.value(); 156 | } 157 | const GoogleString& global_statistics_path() const { 158 | return global_statistics_path_.value(); 159 | } 160 | const GoogleString& console_path() const { 161 | return console_path_.value(); 162 | } 163 | const GoogleString& messages_path() const { 164 | return messages_path_.value(); 165 | } 166 | const GoogleString& admin_path() const { 167 | return admin_path_.value(); 168 | } 169 | const GoogleString& global_admin_path() const { 170 | return global_admin_path_.value(); 171 | } 172 | const std::vector >& script_lines() const { 173 | return script_lines_; 174 | } 175 | const bool& clear_inherited_scripts() const { 176 | return clear_inherited_scripts_; 177 | } 178 | 179 | private: 180 | // Helper methods for ParseAndSetOptions(). Each can: 181 | // - return kOptionNameUnknown and not set msg: 182 | // - directive not handled; continue on with other possible 183 | // interpretations. 184 | // - return kOptionOk and not set msg: 185 | // - directive handled, all's well. 186 | // - return kOptionValueInvalid and set msg: 187 | // - directive handled with an error; return the error to the user. 188 | // 189 | // msg will be shown to the user on kOptionValueInvalid. While it would be 190 | // nice to always use msg and never use the MessageHandler, some option 191 | // parsing code in RewriteOptions expects to write to a MessageHandler. If 192 | // that happens we put a summary on msg so the user sees something, and the 193 | // detailed message goes to their log via handler. 194 | OptionSettingResult ParseAndSetOptions0( 195 | StringPiece directive, GoogleString* msg, MessageHandler* handler); 196 | 197 | virtual OptionSettingResult ParseAndSetOptionFromName1( 198 | StringPiece name, StringPiece arg, 199 | GoogleString* msg, MessageHandler* handler); 200 | 201 | // We may want to override 2- and 3-argument versions as well in the future, 202 | // but they are not needed yet. 203 | 204 | // Keeps the properties added by this subclass. These are merged into 205 | // RewriteOptions::all_properties_ during Initialize(). 206 | // 207 | // RewriteOptions uses static initialization to reduce memory usage and 208 | // construction time. All NgxRewriteOptions instances will have the same 209 | // Properties, so we can build the list when we initialize the first one. 210 | static Properties* ngx_properties_; 211 | static void AddProperties(); 212 | void Init(); 213 | 214 | // Add an option to ngx_properties_ 215 | template 216 | static void add_ngx_option(typename OptionClass::ValueType default_value, 217 | OptionClass NgxRewriteOptions::*offset, 218 | const char* id, 219 | StringPiece option_name, 220 | OptionScope scope, 221 | const char* help, 222 | bool safe_to_print) { 223 | AddProperty(default_value, offset, id, option_name, scope, help, 224 | safe_to_print, ngx_properties_); 225 | } 226 | 227 | Option statistics_path_; 228 | Option global_statistics_path_; 229 | Option console_path_; 230 | Option messages_path_; 231 | Option admin_path_; 232 | Option global_admin_path_; 233 | 234 | bool clear_inherited_scripts_; 235 | std::vector > script_lines_; 236 | 237 | // Helper for ParseAndSetOptions. Returns whether the two directives equal, 238 | // ignoring case. 239 | bool IsDirective(StringPiece config_directive, StringPiece compare_directive); 240 | 241 | // Returns a given option's scope. 242 | RewriteOptions::OptionScope GetOptionScope(StringPiece option_name); 243 | 244 | // TODO(jefftk): support fetch proxy in server and location blocks. 245 | 246 | DISALLOW_COPY_AND_ASSIGN(NgxRewriteOptions); 247 | }; 248 | 249 | } // namespace net_instaweb 250 | 251 | #endif // NGX_REWRITE_OPTIONS_H_ 252 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # Supported tags and respective `Dockerfile` links 2 | 3 | - [`1.13.35.2`, `stable`, `1.13.35`, `1.13`, `1.13.35.2-alpine3.8`, `1.13.35-alpine3.8`, `1.13-alpine3.8`, `stable-alpine3.8`, `1.13.35.2-alpine3.8-ngx1.14`, `1.13.35-alpine3.8-ngx1.14`, `1.13-alpine3.8-ngx1.14`, `stable-alpine3.8-ngx1.14`, `latest` (*alpine-3.8/nginx-stable/Dockerfile*)](https://github.com/apache/incubator-pagespeed-ngx/blob/master/docker/alpine-3.8/nginx-stable/Dockerfile) 4 | - [`1.13.35.2-edge`, `stable-edge`, `edge`, `1.13.35-edge`, `1.13-edge`, `1.13.35.2-edge-ngx1.14`, `1.13.35-edge-ngx1.14`, `1.13-edge-ngx1.14`, `stable-edge-ngx1.14` (*alpine-edge/nginx-stable/Dockerfile*)](https://github.com/apache/incubator-pagespeed-ngx/blob/master/docker/alpine-edge/nginx-stable/Dockerfile) 5 | - [`1.13.35.2-alpine3.8-ngx1.15`, `ngx1.15`, `1.13.35-alpine3.8-ngx1.15`, `1.13-alpine3.8-ngx1.15`, `stable-alpine3.8-ngx1.15` (*alpine-3.8/nginx-mainline/Dockerfile*)](https://github.com/apache/incubator-pagespeed-ngx/blob//master/docker/alpine-3.8/nginx-mainline/Dockerfile) 6 | - [`1.13.35.2-edge-ngx1.15`, `1.13.35-edge-ngx1.15`, `1.13-edge-ngx1.15`, `stable-edge-ngx1.15` (*alpine-edge/nginx-mainline/Dockerfile*)](https://github.com/apache/incubator-pagespeed-ngx/blob/master/docker/alpine-edge/nginx-mainline/Dockerfile) 7 | 8 | # Quick reference 9 | 10 | - **Where to get help**: 11 | [Read the wiki](https://github.com/apache/incubator-pagespeed-mod/wiki), [Ask a question on the mailing list](https://groups.google.com/group/ngx-pagespeed-discuss) 12 | 13 | - **Docker image repository**: 14 | [Dockerhub](https://hub.docker.com/r/pagespeed/nginx-pagespeed) 15 | 16 | - **Git Dockerfile repository**: 17 | [Github](https://github.com/apache/incubator-pagespeed-ngx/tree/master/docker) 18 | 19 | - **Where to file issues**: 20 | [https://github.com/We-Amp/ngx-pagespeed-alpine/issues](https://github.com/apache/incubator-pagespeed-ngx/issues) 21 | 22 | - **Docker images maintained by**: 23 | [Nico Berlee](mailto:nico.berlee@on2it.net) 24 | 25 | - **Supported Docker versions**: 26 | [the latest release](https://github.com/docker/docker-ce/releases/latest) (down to 1.12 on a best-effort basis) 27 | 28 | # What is pagespeed? 29 | 30 | The PageSpeed Modules, [mod_pagespeed](https://github.com/apache/incubator-pagespeed-mod) and [ngx_pagespeed](https://github.com/apache/incubator-pagespeed-ngx), are open-source webserver modules that [optimize your site automatically](https://www.modpagespeed.com/doc/filters). 31 | 32 | ngx_pagespeed speeds up your site and reduces page load time by automatically 33 | applying web performance best practices to pages and associated assets (CSS, 34 | JavaScript, images) without requiring you to modify your existing content or 35 | workflow. Features include: 36 | 37 | - Image optimization: stripping meta-data, dynamic resizing, recompression 38 | - CSS & JavaScript minification, concatenation, inlining, and outlining 39 | - Small resource inlining 40 | - Deferring image and JavaScript loading 41 | - HTML rewriting 42 | - Cache lifetime extension 43 | - and [more](https://developers.google.com/speed/docs/mod_pagespeed/config_filters) 44 | 45 | To see ngx_pagespeed in action, with example pages for each of the 46 | optimizations, see our [demonstration site](http://ngxpagespeed.com). 47 | 48 | ![logo](https://camo.githubusercontent.com/4138679c6cf85adb18c4cf820189c898f7dbf5cb/68747470733a2f2f6c68362e676f6f676c6575736572636f6e74656e742e636f6d2f2d71756665644a494a7137592f55584576565978795976492f4141414141414141446f382f4a48444651687339315f632f733430312f30345f6e67785f7061676573706565642e706e67) 49 | 50 | # What is nginx? 51 | 52 | Nginx (pronounced "engine-x") is an open source reverse proxy server for HTTP, HTTPS, SMTP, POP3, and IMAP protocols, as well as a load balancer, HTTP cache, and a web server (origin server). The nginx project started with a strong focus on high concurrency, high performance and low memory usage. 53 | > [wikipedia.org/wiki/Nginx](https://en.wikipedia.org/wiki/Nginx) 54 | 55 | # What is nginx-pagespeed? 56 | 57 | The nginx-pagespeed brings all the goods of nginx and pagespeed together in one single small alpine docker image. Nginx-pagespeed aims to be 100% compatible with the plain [nginx](https://hub.docker.com/_/nginx/) images. Meaning, nginx-pagespeed can be a safe drop-in replacement for any container running `nginx:alpine`. 58 | 59 | Nginx-pagespeed makes it easy to start optimizing your website by reducing page load time, without requiring you to modify existing content. 60 | 61 | # How to use this image 62 | 63 | ## Hosting some simple static content 64 | 65 | ```console 66 | $ docker run --name pagespeed-nginx -v /some/content:/usr/share/nginx/html:ro -d pagespeed/nginx-pagespeed 67 | ``` 68 | 69 | Alternatively, a simple `Dockerfile` can be used to generate a new image that includes the necessary content (which is a much cleaner solution than the bind mount above): 70 | 71 | ```dockerfile 72 | FROM pagespeed/nginx-pagespeed 73 | COPY static-html-directory /usr/share/nginx/html 74 | ``` 75 | 76 | Place this file in the same directory as your directory of content ("static-html-directory"), run `docker build -t some-content-ngxpagespeed .`, then start your container: 77 | 78 | ```console 79 | $ docker run --name my-nginx-pagespeed -d some-content-ngxpagespeed 80 | ``` 81 | 82 | ## Exposing external port 83 | 84 | ```console 85 | $ docker run --name my-nginx-pagespeed -d -p 8080:80 some-content-ngxpagespeed 86 | ``` 87 | 88 | Then you can hit `http://localhost:8080` or `http://host-ip:8080` in your browser. 89 | 90 | ## Complex configuration 91 | 92 | ```console 93 | $ docker run --name my-custom-nginx-pagespeed -v /host/path/nginx.conf:/etc/nginx/nginx.conf:ro -d pagespeed/nginx-pagespeed 94 | ``` 95 | 96 | For information on the syntax of the nginx configuration files, see [the official documentation](http://nginx.org/en/docs/) (specifically the [Beginner's Guide](http://nginx.org/en/docs/beginners_guide.html#conf_structure)). For pagespeed specific nginx config syntax, see [Beginner's guide](https://www.modpagespeed.com/doc/configuration) or a complete overview of [all pagespeed filters](https://www.ngxpagespeed.com/). 97 | For a quick start on pagespeed specific configuration see [] 98 | 99 | If you wish to adapt the default configuration, use something like the following to copy it from a running nginx-pagespeed container: 100 | 101 | ```console 102 | $ docker run --name tmp-ngxpagespeed-container -d pagespeed/nginx-pagespeed 103 | $ docker cp tmp-ngxpagespeed-container:/etc/nginx/nginx.conf /host/path/nginx.conf 104 | $ docker rm -f tmp-ngxpagespeed-container 105 | ``` 106 | 107 | This can also be accomplished more cleanly using a simple `Dockerfile` (in `/host/path/`): 108 | 109 | ```dockerfile 110 | FROM pagespeed/nginx-pagespeed 111 | COPY nginx.conf /etc/nginx/nginx.conf 112 | ``` 113 | 114 | If you add a custom `CMD` in the Dockerfile, be sure to include `-g daemon off;` in the `CMD` in order for nginx to stay in the foreground, so that Docker can track the process properly (otherwise your container will stop immediately after starting)! 115 | 116 | Then build the image with `docker build -t custom-ngxpagespeed .` and run it as follows: 117 | 118 | ```console 119 | $ docker run --name my-custom-ngxpagespeed-container -d custom-ngxpagespeed 120 | ``` 121 | 122 | ### Using environment variables in nginx configuration 123 | 124 | Out-of-the-box, nginx doesn't support environment variables inside most configuration blocks. But `envsubst` may be used as a workaround if you need to generate your nginx configuration dynamically before nginx starts. 125 | 126 | Here is an example using docker-compose.yml: 127 | 128 | ```yaml 129 | web: 130 | image: pagespeed/nginx-pagespeed 131 | volumes: 132 | - ./mysite.template:/etc/nginx/conf.d/mysite.template 133 | ports: 134 | - "8080:80" 135 | environment: 136 | - NGINX_HOST=foobar.com 137 | - NGINX_PORT=80 138 | command: /bin/bash -c "envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" 139 | ``` 140 | 141 | The `mysite.template` file may then contain variable references like this: 142 | 143 | `listen ${NGINX_PORT}; 144 | ` 145 | 146 | # Image Variants 147 | 148 | The `pagespeed/nginx-pagespeed` images come in many flavors, each designed for a specific use case. 149 | 150 | ## `pagespeed/nginx-pagespeed:` 151 | 152 | This is the defacto image. If you are unsure about what your needs are, you probably want to use this one. It is designed to be used both as a throw away container (mount your source code and start the container to start your app), as well as the base to build other images off of. 153 | 154 | ## `nginx:edge` 155 | 156 | This image has the most up-to-date system packages available in the [Alpine Linux project](http://alpinelinux.org). This means the latest LibreSSL and musl-libc, with the downside of having less tested system packages. 157 | 158 | 159 | ## Using the Dockerfile 160 | ### Use docker build command to build an image from dockerfile: 161 | docker build -t . 162 | $ docker build -t ngxpagespeed-alpine38-ngxstable stable/3.8/nginx-stable 163 | Refer [this](https://docs.docker.com/engine/reference/commandline/build/) for additional options. 164 | 165 | ### Run this container as an independent service: 166 | $ docker run -d -p 80:80 167 | Refer [this](https://docs.docker.com/engine/reference/run/) for additional options. 168 | 169 | ## Requirements for building: 170 | - > 3 GB of free diskspace 171 | - 2GB of memory 172 | - an x86_64 compatible processor 173 | - Docker CE > 17.3.2 174 | 175 | 176 | # Disclaimer 177 | Apache PageSpeed is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF. 178 | 179 | # License 180 | View [PageSpeed license information](https://github.com/apache/incubator-pagespeed-ngx/blob/master/LICENSE) 181 | View [Nginx license information](http://nginx.org/LICENSE) 182 | 183 | As with all Docker images, these likely also contain other software which may be under other licenses (such as Bash, etc from the base distribution, along with any direct or indirect dependencies of the primary software being contained). 184 | 185 | Some additional license information which was able to be auto-detected might be found in [the `repo-info` repository's `nginx/` directory](https://github.com/docker-library/repo-info/tree/master/repos/nginx). 186 | 187 | As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licenses for all software contained within. 188 | -------------------------------------------------------------------------------- /src/ngx_url_async_fetcher.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | 21 | 22 | extern "C" { 23 | #include 24 | #include 25 | } 26 | 27 | #include "ngx_url_async_fetcher.h" 28 | #include "ngx_fetch.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "net/instaweb/http/public/async_fetch.h" 38 | #include "net/instaweb/http/public/inflating_fetch.h" 39 | #include "net/instaweb/public/version.h" 40 | #include "pagespeed/kernel/base/basictypes.h" 41 | #include "pagespeed/kernel/base/condvar.h" 42 | #include "pagespeed/kernel/base/message_handler.h" 43 | #include "pagespeed/kernel/base/pool.h" 44 | #include "pagespeed/kernel/base/pool_element.h" 45 | #include "pagespeed/kernel/base/statistics.h" 46 | #include "pagespeed/kernel/base/string_util.h" 47 | #include "pagespeed/kernel/base/thread_system.h" 48 | #include "pagespeed/kernel/base/timer.h" 49 | #include "pagespeed/kernel/base/writer.h" 50 | #include "pagespeed/kernel/http/request_headers.h" 51 | #include "pagespeed/kernel/http/response_headers.h" 52 | #include "pagespeed/kernel/http/response_headers_parser.h" 53 | 54 | namespace net_instaweb { 55 | 56 | NgxUrlAsyncFetcher::NgxUrlAsyncFetcher(const char* proxy, 57 | ngx_log_t* log, 58 | ngx_msec_t resolver_timeout, 59 | ngx_msec_t fetch_timeout, 60 | ngx_resolver_t* resolver, 61 | int max_keepalive_requests, 62 | ThreadSystem* thread_system, 63 | MessageHandler* handler) 64 | : fetchers_count_(0), 65 | shutdown_(false), 66 | track_original_content_length_(false), 67 | byte_count_(0), 68 | thread_system_(thread_system), 69 | message_handler_(handler), 70 | mutex_(NULL), 71 | max_keepalive_requests_(max_keepalive_requests), 72 | event_connection_(NULL) { 73 | resolver_timeout_ = resolver_timeout; 74 | fetch_timeout_ = fetch_timeout; 75 | ngx_memzero(&proxy_, sizeof(proxy_)); 76 | if (proxy != NULL && *proxy != '\0') { 77 | proxy_.url.data = reinterpret_cast(const_cast(proxy)); 78 | proxy_.url.len = ngx_strlen(proxy); 79 | } 80 | mutex_ = thread_system_->NewMutex(); 81 | log_ = log; 82 | pool_ = NULL; 83 | resolver_ = resolver; 84 | // If init fails, set shutdown_ so no fetches will be attempted. 85 | if (!Init(const_cast(ngx_cycle))) { 86 | shutdown_ = true; 87 | message_handler_->Message( 88 | kError, "NgxUrlAsyncFetcher failed to init, fetching disabled."); 89 | } 90 | } 91 | 92 | NgxUrlAsyncFetcher::~NgxUrlAsyncFetcher() { 93 | DCHECK(shutdown_) << "Shut down before destructing NgxUrlAsyncFetcher."; 94 | message_handler_->Message( 95 | kInfo, 96 | "Destruct NgxUrlAsyncFetcher with [%d] active fetchers", 97 | ApproximateNumActiveFetches()); 98 | 99 | CancelActiveFetches(); 100 | active_fetches_.DeleteAll(); 101 | NgxConnection::Terminate(); 102 | 103 | if (pool_ != NULL) { 104 | ngx_destroy_pool(pool_); 105 | pool_ = NULL; 106 | } 107 | if (mutex_ != NULL) { 108 | delete mutex_; 109 | mutex_ = NULL; 110 | } 111 | } 112 | 113 | 114 | bool NgxUrlAsyncFetcher::ParseUrl(ngx_url_t* url, ngx_pool_t* pool) { 115 | size_t scheme_offset; 116 | u_short port; 117 | if (ngx_strncasecmp(url->url.data, reinterpret_cast( 118 | const_cast("http://")), 7) == 0) { 119 | scheme_offset = 7; 120 | port = 80; 121 | } else if (ngx_strncasecmp(url->url.data, reinterpret_cast( 122 | const_cast("https://")), 8) == 0) { 123 | scheme_offset = 8; 124 | port = 443; 125 | } else { 126 | scheme_offset = 0; 127 | port = 80; 128 | } 129 | 130 | url->url.data += scheme_offset; 131 | url->url.len -= scheme_offset; 132 | url->default_port = port; 133 | // See: http://lxr.evanmiller.org/http/source/core/ngx_inet.c#L875 134 | url->no_resolve = 0; 135 | url->uri_part = 1; 136 | 137 | if (ngx_parse_url(pool, url) == NGX_OK) { 138 | return true; 139 | } 140 | return false; 141 | } 142 | 143 | // If there are still active requests, cancel them. 144 | void NgxUrlAsyncFetcher::CancelActiveFetches() { 145 | // TODO(oschaaf): this seems tricky, this may end up calling 146 | // FetchComplete, modifying the active fetches while we are looping 147 | // it 148 | for (NgxFetchPool::const_iterator p = active_fetches_.begin(), 149 | e = active_fetches_.end(); p != e; ++p) { 150 | NgxFetch* fetch = *p; 151 | fetch->CallbackDone(false); 152 | } 153 | } 154 | 155 | // Create the pool for fetcher, create the pipe, add the read event for main 156 | // thread. It should be called in the worker process. 157 | bool NgxUrlAsyncFetcher::Init(ngx_cycle_t* cycle) { 158 | log_ = cycle->log; 159 | CHECK(event_connection_ == NULL) << "event connection already set"; 160 | event_connection_ = new NgxEventConnection(ReadCallback); 161 | if (!event_connection_->Init(cycle)) { 162 | return false; 163 | } 164 | if (pool_ == NULL) { 165 | pool_ = ngx_create_pool(4096, log_); 166 | if (pool_ == NULL) { 167 | ngx_log_error(NGX_LOG_ERR, log_, 0, 168 | "NgxUrlAsyncFetcher::Init create pool failed"); 169 | return false; 170 | } 171 | } 172 | 173 | if (proxy_.url.len == 0) { 174 | return true; 175 | } 176 | 177 | // TODO(oschaaf): shouldn't we do this earlier? Do we need to clean 178 | // up when parsing the url failed? 179 | if (!ParseUrl(&proxy_, pool_)) { 180 | ngx_log_error(NGX_LOG_ERR, log_, 0, 181 | "NgxUrlAsyncFetcher::Init parse proxy[%V] failed", &proxy_.url); 182 | return false; 183 | } 184 | return true; 185 | } 186 | 187 | void NgxUrlAsyncFetcher::ShutDown() { 188 | shutdown_ = true; 189 | if (!pending_fetches_.empty()) { 190 | for (Pool::iterator p = pending_fetches_.begin(), 191 | e = pending_fetches_.end(); p != e; p++) { 192 | NgxFetch* fetch = *p; 193 | fetch->CallbackDone(false); 194 | } 195 | pending_fetches_.DeleteAll(); 196 | } 197 | 198 | if (!active_fetches_.empty()) { 199 | for (Pool::iterator p = active_fetches_.begin(), 200 | e = active_fetches_.end(); p != e; p++) { 201 | NgxFetch* fetch = *p; 202 | fetch->CallbackDone(false); 203 | } 204 | active_fetches_.Clear(); 205 | } 206 | if (event_connection_ != NULL) { 207 | event_connection_->Shutdown(); 208 | delete event_connection_; 209 | event_connection_ = NULL; 210 | } 211 | } 212 | 213 | // It's called in the rewrite thread. All the fetches are started at 214 | // this function. It will notify the main thread to start the fetch job. 215 | void NgxUrlAsyncFetcher::Fetch(const GoogleString& url, 216 | MessageHandler* message_handler, 217 | AsyncFetch* async_fetch) { 218 | // Don't accept new fetches when shut down. This flow is also entered when 219 | // we did not initialize properly in ::Init(). 220 | if (shutdown_) { 221 | async_fetch->Done(false); 222 | return; 223 | } 224 | async_fetch = EnableInflation(async_fetch); 225 | NgxFetch* fetch = new NgxFetch(url, async_fetch, 226 | message_handler, log_); 227 | ScopedMutex lock(mutex_); 228 | pending_fetches_.Add(fetch); 229 | 230 | // TODO(oschaaf): thread safety on written vs shutdown. 231 | // It is possible that shutdown() is called after writing an event? In that 232 | // case, this could (rarely) fail when it shouldn't. 233 | bool written = event_connection_->WriteEvent(this); 234 | CHECK(written || shutdown_) << "NgxUrlAsyncFetcher: event write failure"; 235 | } 236 | 237 | // This is the read event which is called in the main thread. 238 | // It will do the real work. Add the work event and start the fetch. 239 | void NgxUrlAsyncFetcher::ReadCallback(const ps_event_data& data) { 240 | std::vector to_start; 241 | NgxUrlAsyncFetcher* fetcher = reinterpret_cast( 242 | data.sender); 243 | 244 | fetcher->mutex_->Lock(); 245 | fetcher->completed_fetches_.DeleteAll(); 246 | 247 | for (Pool::iterator p = fetcher->pending_fetches_.begin(), 248 | e = fetcher->pending_fetches_.end(); p != e; p++) { 249 | NgxFetch* fetch = *p; 250 | to_start.push_back(fetch); 251 | } 252 | 253 | fetcher->pending_fetches_.Clear(); 254 | fetcher->mutex_->Unlock(); 255 | 256 | for (size_t i = 0; i < to_start.size(); i++) { 257 | fetcher->StartFetch(to_start[i]); 258 | } 259 | 260 | return; 261 | } 262 | 263 | // TODO(oschaaf): return value is ignored. 264 | bool NgxUrlAsyncFetcher::StartFetch(NgxFetch* fetch) { 265 | mutex_->Lock(); 266 | active_fetches_.Add(fetch); 267 | fetchers_count_++; 268 | mutex_->Unlock(); 269 | 270 | // Don't initiate the fetch when we are shutting down 271 | if (shutdown_) { 272 | fetch->CallbackDone(false); 273 | return false; 274 | } 275 | 276 | bool started = fetch->Start(this); 277 | 278 | if (!started) { 279 | message_handler_->Message(kWarning, "Fetch failed to start: %s", 280 | fetch->str_url()); 281 | fetch->CallbackDone(false); 282 | } 283 | 284 | return started; 285 | } 286 | 287 | void NgxUrlAsyncFetcher::FetchComplete(NgxFetch* fetch) { 288 | ScopedMutex lock(mutex_); 289 | byte_count_ += fetch->bytes_received(); 290 | fetchers_count_--; 291 | active_fetches_.Remove(fetch); 292 | completed_fetches_.Add(fetch); 293 | } 294 | 295 | void NgxUrlAsyncFetcher::PrintActiveFetches(MessageHandler* handler) const { 296 | for (NgxFetchPool::const_iterator p = active_fetches_.begin(), 297 | e = active_fetches_.end(); p != e; ++p) { 298 | NgxFetch* fetch = *p; 299 | handler->Message(kInfo, "Active fetch: %s", fetch->str_url()); 300 | } 301 | } 302 | } // namespace net_instaweb 303 | --------------------------------------------------------------------------------