Compare commits
2 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bd8be0d50 | ||
|
|
9947f2a2f0 |
760 changed files with 14 additions and 155760 deletions
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -1,10 +0,0 @@
|
|||
objs/*
|
||||
!objs/ndk_*
|
||||
.pc/
|
||||
.vscode/
|
||||
modules/media-framework/
|
||||
modules/nginx-srt-module/
|
||||
modules/nginx-vod-module/
|
||||
Makefile
|
||||
*.orig
|
||||
*.txt
|
||||
13
auto/make
13
auto/make
|
|
@ -2,11 +2,6 @@
|
|||
# Copyright (C) Igor Sysoev
|
||||
# Copyright (C) Nginx, Inc.
|
||||
|
||||
basename_last2() {
|
||||
local basename_1=`basename \`dirname $1\``
|
||||
local basename_2=$(basename "$1")
|
||||
echo $(printf "$basename_1/$basename_2" | sed 's/\.\.\///')
|
||||
}
|
||||
|
||||
echo "creating $NGX_MAKEFILE"
|
||||
|
||||
|
|
@ -179,7 +174,7 @@ ngx_all_srcs=`echo $ngx_all_srcs | sed -e "s/\//$ngx_regex_dirsep/g"`
|
|||
|
||||
for ngx_src in $NGX_ADDON_SRCS
|
||||
do
|
||||
ngx_obj="addon/`basename_last2 \`dirname $ngx_src\``"
|
||||
ngx_obj="addon/`basename \`dirname $ngx_src\``"
|
||||
|
||||
test -d $NGX_OBJS/$ngx_obj || mkdir -p $NGX_OBJS/$ngx_obj
|
||||
|
||||
|
|
@ -418,7 +413,7 @@ if test -n "$NGX_ADDON_SRCS"; then
|
|||
|
||||
for ngx_src in $NGX_ADDON_SRCS
|
||||
do
|
||||
ngx_obj="addon/`basename_last2 \`dirname $ngx_src\``"
|
||||
ngx_obj="addon/`basename \`dirname $ngx_src\``"
|
||||
|
||||
ngx_obj=`echo $ngx_obj/\`basename $ngx_src\` \
|
||||
| sed -e "s/\//$ngx_regex_dirsep/g"`
|
||||
|
|
@ -581,7 +576,7 @@ END
|
|||
ngx_obj=$ngx_src
|
||||
;;
|
||||
*)
|
||||
ngx_obj="addon/`basename_last2 \`dirname $ngx_src\``"
|
||||
ngx_obj="addon/`basename \`dirname $ngx_src\``"
|
||||
mkdir -p $NGX_OBJS/$ngx_obj
|
||||
ngx_obj="$ngx_obj/`basename $ngx_src`"
|
||||
;;
|
||||
|
|
@ -643,7 +638,7 @@ END
|
|||
ngx_obj=`echo $ngx_source | sed -e "s/\//$ngx_regex_dirsep/g"`
|
||||
;;
|
||||
*)
|
||||
ngx_obj="addon/`basename_last2 \`dirname $ngx_source\``"
|
||||
ngx_obj="addon/`basename \`dirname $ngx_source\``"
|
||||
ngx_obj=`echo $ngx_obj/\`basename $ngx_source\` \
|
||||
| sed -e "s/\//$ngx_regex_dirsep/g"`
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
#!/bin/bash
|
||||
./configure \
|
||||
--with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -D_FORTIFY_SOURCE=2 -I/tmp/build/quickjs/" \
|
||||
--with-ld-opt="-Wl,-z,relro -Wl,-z,now -fPIC -L/tmp/build/quickjs/" \
|
||||
--sbin-path=/usr/local/sbin/nginx \
|
||||
--conf-path=/video_server/nginx/nginx.conf \
|
||||
--error-log-path=/var/log/nginx/error.log \
|
||||
--pid-path=/var/run/nginx/nginx.pid \
|
||||
--lock-path=/var/lock/nginx/nginx.lock \
|
||||
--http-log-path=/var/log/nginx/access.log \
|
||||
--http-client-body-temp-path=/tmp/nginx-client-body \
|
||||
--with-compat \
|
||||
--with-debug \
|
||||
--with-pcre-jit \
|
||||
--with-http_ssl_module \
|
||||
--with-http_stub_status_module \
|
||||
--with-http_realip_module \
|
||||
--with-http_auth_request_module \
|
||||
--with-http_v2_module \
|
||||
--with-http_dav_module \
|
||||
--with-http_slice_module \
|
||||
--with-threads \
|
||||
--with-http_addition_module \
|
||||
--with-http_flv_module \
|
||||
--with-http_gunzip_module \
|
||||
--with-http_gzip_static_module \
|
||||
--with-http_mp4_module \
|
||||
--with-http_random_index_module \
|
||||
--with-http_secure_link_module \
|
||||
--with-http_sub_module \
|
||||
--with-mail_ssl_module \
|
||||
--with-stream_ssl_module \
|
||||
--with-stream_ssl_preread_module \
|
||||
--with-stream_realip_module \
|
||||
--with-http_geoip_module=dynamic \
|
||||
--with-http_image_filter_module=dynamic \
|
||||
--with-http_perl_module=dynamic \
|
||||
--with-http_xslt_module=dynamic \
|
||||
--with-mail=dynamic \
|
||||
--with-stream=dynamic \
|
||||
--with-stream_geoip_module=dynamic \
|
||||
--add-module=./modules_deb/libnginx-mod-http-ndk-0.3.4 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-brotli-1.0.0~rc \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-cache-purge-2.5.3 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-echo-0.63 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-geoip2-3.4 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-headers-more-filter-0.38 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-memc-0.20 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-set-misc-0.33 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-srcache-filter-0.33 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-subs-filter-0.6.4 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-upstream-fair-0.0~git20120408.a18b409 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-nchan-1.3.7+dfsg \
|
||||
--add-dynamic-module=./modules/njs/nginx \
|
||||
--add-dynamic-module=./modules/nginx-vod-module \
|
||||
--add-module=./modules/media-framework/nginx-common \
|
||||
--add-dynamic-module=./modules/nginx-stream-preread-str-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-kmp-in-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-kmp-out-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-rtmp-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-rtmp-kmp-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-mpegts-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-mpegts-kmp-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-kmp-cc-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-kmp-rtmp-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-live-module \
|
||||
--add-dynamic-module=./modules/nginx-srt-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-pckg-module \
|
||||
--add-dynamic-module=./modules/nginx-secure-token-module
|
||||
66
configure.sh
66
configure.sh
|
|
@ -1,66 +0,0 @@
|
|||
#!/bin/bash
|
||||
./configure \
|
||||
--with-cc-opt="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -D_FORTIFY_SOURCE=2 -I/usr/local/include/quickjs/" \
|
||||
--with-ld-opt="-Wl,-z,relro -Wl,-z,now -fPIC -L/usr/local/lib/quickjs/" \
|
||||
--prefix=/usr/local/temp/nginx/ \
|
||||
--error-log-path=stderr \
|
||||
--lock-path=/var/lock/nginx.lock \
|
||||
--pid-path=/run/nginx.pid \
|
||||
--with-compat \
|
||||
--with-debug \
|
||||
--with-pcre-jit \
|
||||
--with-http_ssl_module \
|
||||
--with-http_stub_status_module \
|
||||
--with-http_realip_module \
|
||||
--with-http_auth_request_module \
|
||||
--with-http_v2_module \
|
||||
--with-http_dav_module \
|
||||
--with-http_slice_module \
|
||||
--with-threads \
|
||||
--with-http_addition_module \
|
||||
--with-http_flv_module \
|
||||
--with-http_gunzip_module \
|
||||
--with-http_gzip_static_module \
|
||||
--with-http_mp4_module \
|
||||
--with-http_random_index_module \
|
||||
--with-http_secure_link_module \
|
||||
--with-http_sub_module \
|
||||
--with-mail_ssl_module \
|
||||
--with-stream_ssl_module \
|
||||
--with-stream_ssl_preread_module \
|
||||
--with-stream_realip_module \
|
||||
--with-http_geoip_module=dynamic \
|
||||
--with-http_image_filter_module=dynamic \
|
||||
--with-http_perl_module=dynamic \
|
||||
--with-http_xslt_module=dynamic \
|
||||
--with-mail=dynamic \
|
||||
--with-stream=dynamic \
|
||||
--with-stream_geoip_module=dynamic \
|
||||
--add-module=./modules_deb/libnginx-mod-http-ndk-0.3.4 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-brotli-1.0.0~rc \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-cache-purge-2.5.3 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-echo-0.63 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-geoip2-3.4 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-headers-more-filter-0.38 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-memc-0.20 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-set-misc-0.33 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-srcache-filter-0.33 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-subs-filter-0.6.4 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-http-upstream-fair-0.0~git20120408.a18b409 \
|
||||
--add-dynamic-module=./modules_deb/libnginx-mod-nchan-1.3.7+dfsg \
|
||||
--add-dynamic-module=./modules/njs/nginx \
|
||||
--add-dynamic-module=./modules/nginx-vod-module \
|
||||
--add-module=./modules/media-framework/nginx-common \
|
||||
--add-dynamic-module=./modules/nginx-stream-preread-str-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-kmp-in-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-kmp-out-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-rtmp-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-rtmp-kmp-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-mpegts-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-mpegts-kmp-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-kmp-cc-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-kmp-rtmp-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-live-module \
|
||||
--add-dynamic-module=./modules/nginx-srt-module \
|
||||
--add-dynamic-module=./modules/media-framework/nginx-pckg-module \
|
||||
--add-dynamic-module=./modules/nginx-secure-token-module
|
||||
13
debian/changelog
vendored
13
debian/changelog
vendored
|
|
@ -1,17 +1,10 @@
|
|||
nginx (1.26.3-3) unstable; urgency=medium
|
||||
nginx (1.26.3-3) UNRELEASED; urgency=medium
|
||||
|
||||
[ Jan Mojžíš ]
|
||||
* d/changelog: fix whitespace in 1.26.3-2 record
|
||||
* d/changelog: fix whitespace
|
||||
* d/control: add libnginx-mod-http-lua dependency for nginx-extras package
|
||||
for riscv64 platform
|
||||
|
||||
[ Thomas Ward ]
|
||||
* d/nginx-common.nginx.service: Add ConditionFileIsExecutable to
|
||||
SystemD service file, prevents starting of service if nginx is
|
||||
not installed (which can happen if nginx-common is installed
|
||||
independently from `nginx` itself (Closes: #1098477)
|
||||
|
||||
-- Jan Mojžíš <janmojzis@debian.org> Thu, 15 May 2025 15:31:38 +0200
|
||||
-- Jan Mojžíš <janmojzis@debian.org> Wed, 12 Feb 2025 19:37:40 +0100
|
||||
|
||||
nginx (1.26.3-2) unstable; urgency=medium
|
||||
|
||||
|
|
|
|||
1
debian/nginx-common.nginx.service
vendored
1
debian/nginx-common.nginx.service
vendored
|
|
@ -15,7 +15,6 @@ Description=A high performance web server and a reverse proxy server
|
|||
Documentation=man:nginx(8)
|
||||
After=network-online.target remote-fs.target nss-lookup.target
|
||||
Wants=network-online.target
|
||||
ConditionFileIsExecutable=/usr/sbin/nginx
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 24f7b99d9b665e11c92e585d6645ed6f45f7d310
|
||||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 7326626fce5d6ec31ac892377e0a734e503d40e6
|
||||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 4fd3ff98e413ede57c88456cf84b116a8382061a
|
||||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 1fdc768fdc8571300755cdd3e4654ce99c0255ce
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# required for http2 support in curl.
|
||||
dist: bionic
|
||||
language: c
|
||||
sudo: false
|
||||
matrix:
|
||||
include:
|
||||
# unfortunately, gcc-4.9 is dropped in bionic
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-5
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
|
||||
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-6
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"
|
||||
- os: linux
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
env:
|
||||
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
|
||||
|
||||
|
||||
script:
|
||||
- script/.travis-compile.sh
|
||||
- script/.travis-before-test.sh
|
||||
- script/.travis-test.sh
|
||||
after_success:
|
||||
- killall nginx
|
||||
after_failure:
|
||||
- killall nginx
|
||||
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# Contributing
|
||||
|
||||
Want to contribute? Great! First, read this page (including the small print at the end).
|
||||
|
||||
### Before you contribute
|
||||
Before we can use your code, you must sign the
|
||||
[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual)
|
||||
(CLA), which you can do online. The CLA is necessary mainly because you own the
|
||||
copyright to your changes, even after your contribution becomes part of our
|
||||
codebase, so we need your permission to use and distribute your code. We also
|
||||
need to be sure of various other things—for instance that you'll tell us if you
|
||||
know that your code infringes on other people's patents. You don't have to sign
|
||||
the CLA until after you've submitted your code for review and a member has
|
||||
approved it, but you must do it before we can put your code into our codebase.
|
||||
Before you start working on a larger contribution, you should get in touch with
|
||||
us first through the issue tracker with your idea so that we can help out and
|
||||
possibly guide you. Coordinating up front makes it much easier to avoid
|
||||
frustration later on.
|
||||
|
||||
### Code reviews
|
||||
All submissions, including submissions by project members, require review. We
|
||||
use Github pull requests for this purpose.
|
||||
|
||||
### The small print
|
||||
Contributions made by corporations are covered by a different agreement than
|
||||
the one above, the
|
||||
[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate).
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2015 Igor Sysoev
|
||||
* Copyright (C) 2011-2015 Nginx, Inc.
|
||||
* Copyright (C) 2015-2019 Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
# ngx_brotli
|
||||
|
||||
Brotli is a generic-purpose lossless compression algorithm that compresses data
|
||||
using a combination of a modern variant of the LZ77 algorithm, Huffman coding
|
||||
and 2nd order context modeling, with a compression ratio comparable to the best
|
||||
currently available general-purpose compression methods. It is similar in speed
|
||||
with deflate but offers more dense compression.
|
||||
|
||||
ngx_brotli is a set of two nginx modules:
|
||||
|
||||
- ngx_brotli filter module - used to compress responses on-the-fly,
|
||||
- ngx_brotli static module - used to serve pre-compressed files.
|
||||
|
||||
[](https://travis-ci.org/google/ngx_brotli)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Status](#status)
|
||||
- [Installation](#installation)
|
||||
- [Configuration directives](#configuration-directives)
|
||||
- [`brotli_static`](#brotli_static)
|
||||
- [`brotli`](#brotli)
|
||||
- [`brotli_types`](#brotli_types)
|
||||
- [`brotli_buffers`](#brotli_buffers)
|
||||
- [`brotli_comp_level`](#brotli_comp_level)
|
||||
- [`brotli_window`](#brotli_window)
|
||||
- [`brotli_min_length`](#brotli_min_length)
|
||||
- [Variables](#variables)
|
||||
- [`$brotli_ratio`](#brotli_ratio)
|
||||
- [Sample configuration](#sample-configuration)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
|
||||
## Status
|
||||
|
||||
Both Brotli library and nginx module are under active development.
|
||||
|
||||
## Installation
|
||||
|
||||
### Dynamically loaded
|
||||
|
||||
$ cd nginx-1.x.x
|
||||
$ ./configure --with-compat --add-dynamic-module=/path/to/ngx_brotli
|
||||
$ make modules
|
||||
|
||||
You will need to use **exactly** the same `./configure` arguments as your Nginx configuration and append `--with-compat --add-dynamic-module=/path/to/ngx_brotli` to the end, otherwise you will get a "module is not binary compatible" error on startup. You can run `nginx -V` to get the configuration arguments for your Nginx installation.
|
||||
|
||||
`make modules` will result in `ngx_http_brotli_filter_module.so` and `ngx_http_brotli_static_module.so` in the `objs` directory. Copy these to `/usr/lib/nginx/modules/` then add the `load_module` directives to `nginx.conf` (above the http block):
|
||||
```nginx
|
||||
load_module modules/ngx_http_brotli_filter_module.so;
|
||||
load_module modules/ngx_http_brotli_static_module.so;
|
||||
```
|
||||
|
||||
### Statically compiled
|
||||
|
||||
$ cd nginx-1.x.x
|
||||
$ ./configure --add-module=/path/to/ngx_brotli
|
||||
$ make && make install
|
||||
|
||||
This will compile the module directly into Nginx.
|
||||
|
||||
## Configuration directives
|
||||
|
||||
### `brotli_static`
|
||||
|
||||
- **syntax**: `brotli_static on|off|always`
|
||||
- **default**: `off`
|
||||
- **context**: `http`, `server`, `location`
|
||||
|
||||
Enables or disables checking of the existence of pre-compressed files with`.br`
|
||||
extension. With the `always` value, pre-compressed file is used in all cases,
|
||||
without checking if the client supports it.
|
||||
|
||||
### `brotli`
|
||||
|
||||
- **syntax**: `brotli on|off`
|
||||
- **default**: `off`
|
||||
- **context**: `http`, `server`, `location`, `if`
|
||||
|
||||
Enables or disables on-the-fly compression of responses.
|
||||
|
||||
### `brotli_types`
|
||||
|
||||
- **syntax**: `brotli_types <mime_type> [..]`
|
||||
- **default**: `text/html`
|
||||
- **context**: `http`, `server`, `location`
|
||||
|
||||
Enables on-the-fly compression of responses for the specified MIME types
|
||||
in addition to `text/html`. The special value `*` matches any MIME type.
|
||||
Responses with the `text/html` MIME type are always compressed.
|
||||
|
||||
### `brotli_buffers`
|
||||
|
||||
- **syntax**: `brotli_buffers <number> <size>`
|
||||
- **default**: `32 4k|16 8k`
|
||||
- **context**: `http`, `server`, `location`
|
||||
|
||||
**Deprecated**, ignored.
|
||||
|
||||
### `brotli_comp_level`
|
||||
|
||||
- **syntax**: `brotli_comp_level <level>`
|
||||
- **default**: `6`
|
||||
- **context**: `http`, `server`, `location`
|
||||
|
||||
Sets on-the-fly compression Brotli quality (compression) `level`.
|
||||
Acceptable values are in the range from `0` to `11`.
|
||||
|
||||
### `brotli_window`
|
||||
|
||||
- **syntax**: `brotli_window <size>`
|
||||
- **default**: `512k`
|
||||
- **context**: `http`, `server`, `location`
|
||||
|
||||
Sets Brotli window `size`. Acceptable values are `1k`, `2k`, `4k`, `8k`, `16k`,
|
||||
`32k`, `64k`, `128k`, `256k`, `512k`, `1m`, `2m`, `4m`, `8m` and `16m`.
|
||||
|
||||
### `brotli_min_length`
|
||||
|
||||
- **syntax**: `brotli_min_length <length>`
|
||||
- **default**: `20`
|
||||
- **context**: `http`, `server`, `location`
|
||||
|
||||
Sets the minimum `length` of a response that will be compressed.
|
||||
The length is determined only from the `Content-Length` response header field.
|
||||
|
||||
## Variables
|
||||
|
||||
### `$brotli_ratio`
|
||||
|
||||
Achieved compression ratio, computed as the ratio between the original
|
||||
and compressed response sizes.
|
||||
|
||||
## Sample configuration
|
||||
|
||||
```
|
||||
brotli on;
|
||||
brotli_comp_level 6;
|
||||
brotli_static on;
|
||||
brotli_types application/atom+xml application/javascript application/json application/rss+xml
|
||||
application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype
|
||||
application/x-font-ttf application/x-javascript application/xhtml+xml application/xml
|
||||
font/eot font/opentype font/otf font/truetype image/svg+xml image/vnd.microsoft.icon
|
||||
image/x-icon image/x-win-bitmap text/css text/javascript text/plain text/xml;
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
See [Contributing](CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
Copyright (C) 2002-2015 Igor Sysoev
|
||||
Copyright (C) 2011-2015 Nginx, Inc.
|
||||
Copyright (C) 2015 Google Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
# Copyright (C) 2019 Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
# Make sure the module knows it is a submodule.
|
||||
ngx_addon_name=ngx_brotli
|
||||
. $ngx_addon_dir/filter/config
|
||||
|
||||
# Make sure the module knows it is a submodule.
|
||||
ngx_addon_name=ngx_brotli
|
||||
. $ngx_addon_dir/static/config
|
||||
|
||||
# The final name for reporting.
|
||||
ngx_addon_name=ngx_brotli
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
libnginx-mod-http-brotli (1.0.0~rc-6) unstable; urgency=medium
|
||||
|
||||
* d/control: update my email to janmojzis@debian.org
|
||||
* d/copyright: update my email to janmojzis@debian.org
|
||||
* d/control: bump Standards-Version: 4.7.2, no changes
|
||||
* d/copyright: bump debian/* copyright year
|
||||
* d/watch: use more generic template
|
||||
|
||||
-- Jan Mojžíš <janmojzis@debian.org> Fri, 11 Apr 2025 14:26:55 +0200
|
||||
|
||||
libnginx-mod-http-brotli (1.0.0~rc-5) unstable; urgency=medium
|
||||
|
||||
* d/control: remove Build-Depends nginx-abi-1.24.0-1
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Sat, 07 Oct 2023 15:31:24 +0200
|
||||
|
||||
libnginx-mod-http-brotli (1.0.0~rc-4) unstable; urgency=medium
|
||||
|
||||
* NEW ABI: rebuild with nginx-abi-1.24.0-1
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Tue, 27 Jun 2023 23:16:35 +0200
|
||||
|
||||
libnginx-mod-http-brotli (1.0.0~rc-3) unstable; urgency=medium
|
||||
|
||||
* d/watch: updated uversionmangle to be more generic
|
||||
* d/copyright: reformat text to be compatible with 'cme update dpkg-copyright'
|
||||
* NEW ABI: rebuild with nginx-abi-1.22.1-7
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Mon, 13 Feb 2023 12:56:11 +0100
|
||||
|
||||
libnginx-mod-http-brotli (1.0.0~rc-2) unstable; urgency=medium
|
||||
|
||||
* d/t/generic rework. The test now checks module after
|
||||
installation/reload/restart.
|
||||
* d/control: bump Standards-Version: 4.6.2, no changes
|
||||
* d/p/0001-Fix-Vary-header.patch added (Closes: 1028153)
|
||||
"brotli_static on;" causes "Vary: Accept-Encoding" to be added to every
|
||||
file (including images, ...)
|
||||
The patch fixes the problem and adds "Vary: Accept-Encoding" only to
|
||||
responses when brotli static compression is used.
|
||||
* d/changelog: bump my copyright year
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Fri, 13 Jan 2023 17:45:13 +0100
|
||||
|
||||
libnginx-mod-http-brotli (1.0.0~rc-1) unstable; urgency=medium
|
||||
|
||||
* Initial release. (Closes: 1025515)
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Tue, 06 Dec 2022 10:25:40 +0100
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
Source: libnginx-mod-http-brotli
|
||||
Section: httpd
|
||||
Priority: optional
|
||||
Maintainer: Debian Nginx Maintainers <pkg-nginx-maintainers@alioth-lists.debian.net>
|
||||
Uploaders: Jan Mojžíš <janmojzis@debian.org>,
|
||||
Build-Depends: debhelper-compat (= 13),
|
||||
dh-sequence-nginx,
|
||||
libbrotli-dev,
|
||||
Standards-Version: 4.7.2
|
||||
Homepage: https://github.com/google/ngx_brotli
|
||||
Vcs-Git: https://salsa.debian.org/nginx-team/libnginx-mod-http-brotli.git
|
||||
Vcs-Browser: https://salsa.debian.org/nginx-team/libnginx-mod-http-brotli
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: libnginx-mod-http-brotli-filter
|
||||
Architecture: any
|
||||
Multi-Arch: foreign
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
Description: Brotli lossless compression support for Nginx - filter
|
||||
Brotli is a generic-purpose lossless compression algorithm that compresses
|
||||
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
||||
coding and 2nd order context modeling, with a compression ratio comparable
|
||||
to the best currently available general-purpose compression methods. It is
|
||||
similar in speed with deflate but offers more dense compression.
|
||||
.
|
||||
ngx_brotli filter module - used to compress responses on-the-fly
|
||||
|
||||
Package: libnginx-mod-http-brotli-static
|
||||
Architecture: any
|
||||
Multi-Arch: foreign
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
Description: Brotli lossless compression support for Nginx - static
|
||||
Brotli is a generic-purpose lossless compression algorithm that compresses
|
||||
data using a combination of a modern variant of the LZ77 algorithm, Huffman
|
||||
coding and 2nd order context modeling, with a compression ratio comparable
|
||||
to the best currently available general-purpose compression methods. It is
|
||||
similar in speed with deflate but offers more dense compression.
|
||||
.
|
||||
ngx_brotli static module - used to serve pre-compressed files
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: ngx-brotli
|
||||
Source: https://github.com/google/ngx_brotli
|
||||
|
||||
Files: *
|
||||
Copyright: 2015-2019, Google Inc.
|
||||
2011-2015, Nginx, Inc.
|
||||
2002-2015, Igor Sysoev
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: CONTRIBUTING.md
|
||||
Copyright: Copyright (C) 2015 Google Inc.
|
||||
Copyright (C) 2011-2015 Nginx, Inc.
|
||||
Copyright (C) 2002-2015 Igor Sysoev
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: config
|
||||
Copyright: 2015-2019, Google Inc.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2022, Miao Wang <shankerwangmiao@gmail.com>
|
||||
2022-2025, Jan Mojzis <janmojzis@debian.org>
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: filter/*
|
||||
Copyright: 2015-2019, Google Inc.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: filter/ngx_http_brotli_filter_module.c
|
||||
Copyright: Nginx, Inc.
|
||||
Igor Sysoev
|
||||
Google Inc.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: script/*
|
||||
Copyright: Copyright (C) 2015 Google Inc.
|
||||
Copyright (C) 2011-2015 Nginx, Inc.
|
||||
Copyright (C) 2002-2015 Igor Sysoev
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: static/*
|
||||
Copyright: 2015-2019, Google Inc.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: static/ngx_http_brotli_static_module.c
|
||||
Copyright: Nginx, Inc.
|
||||
Igor Sysoev
|
||||
Google Inc.
|
||||
License: BSD-2-clause
|
||||
|
||||
License: BSD-2-clause
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
[DEFAULT]
|
||||
debian-branch = main
|
||||
upstream-branch = upstream
|
||||
upstream-tag = upstream/%(version)s
|
||||
pristine-tar = True
|
||||
sign-tags = True
|
||||
|
||||
[import-orig]
|
||||
merge-mode = replace
|
||||
|
|
@ -1 +0,0 @@
|
|||
/usr/lib/nginx/modules/ngx_http_brotli_filter_module.so
|
||||
|
|
@ -1 +0,0 @@
|
|||
/usr/lib/nginx/modules/ngx_http_brotli_static_module.so
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
From: Jan Mojzis <jan.mojzis@gmail.com>
|
||||
Date: Fri, 13 Jan 2023 12:59:07 +0100
|
||||
Subject: Fix 'Vary' header
|
||||
|
||||
The patch fixes problem described here:
|
||||
https://github.com/google/ngx_brotli/issues/97
|
||||
|
||||
"brotli_static on;" causes "Vary: Accept-Encoding" to be added to every
|
||||
file (including images, ...)
|
||||
The patch fixes the problem and adds "Vary: Accept-Encoding" only to
|
||||
responses when brotli static compression is used.
|
||||
---
|
||||
static/ngx_http_brotli_static_module.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/static/ngx_http_brotli_static_module.c b/static/ngx_http_brotli_static_module.c
|
||||
index 8f96177..44f0cb0 100644
|
||||
--- a/static/ngx_http_brotli_static_module.c
|
||||
+++ b/static/ngx_http_brotli_static_module.c
|
||||
@@ -168,7 +168,6 @@ static ngx_int_t handler(ngx_http_request_t* req) {
|
||||
/* Ignore request properties (e.g. Accept-Encoding). */
|
||||
} else {
|
||||
/* NGX_HTTP_BROTLI_STATIC_ON */
|
||||
- req->gzip_vary = 1;
|
||||
rc = check_eligility(req);
|
||||
if (rc != NGX_OK) return NGX_DECLINED;
|
||||
}
|
||||
@@ -227,6 +226,10 @@ static ngx_int_t handler(ngx_http_request_t* req) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
+ if (cfg->enable == NGX_HTTP_BROTLI_STATIC_ON) {
|
||||
+ req->gzip_vary = 1;
|
||||
+ }
|
||||
+
|
||||
/* So far so good. */
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d",
|
||||
file_info.fd);
|
||||
|
|
@ -1 +0,0 @@
|
|||
0001-Fix-Vary-header.patch
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
|
@ -1 +0,0 @@
|
|||
3.0 (quilt)
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
Tests: generic
|
||||
Restrictions: allow-stderr isolation-container needs-root
|
||||
Depends: curl,
|
||||
nginx,
|
||||
nginx-core,
|
||||
@,
|
||||
|
||||
Tests: static
|
||||
Restrictions: allow-stderr isolation-container needs-root
|
||||
Depends: brotli,
|
||||
curl,
|
||||
libnginx-mod-http-brotli-static,
|
||||
nginx,
|
||||
nginx-core,
|
||||
|
||||
Tests: filter
|
||||
Restrictions: allow-stderr isolation-container needs-root
|
||||
Depends: brotli,
|
||||
curl,
|
||||
libnginx-mod-http-brotli-filter,
|
||||
nginx,
|
||||
nginx-core,
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cat <<EOF > "/etc/nginx/sites-enabled/default"
|
||||
server {
|
||||
listen 80 default_server;
|
||||
root /var/www/html;
|
||||
|
||||
location /helloworld {
|
||||
default_type text/plain;
|
||||
brotli on;
|
||||
brotli_types text/plain;
|
||||
brotli_min_length 10;
|
||||
brotli_comp_level 11;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
mkdir -p /var/www/html
|
||||
echo 'hello world' > /var/www/html/helloworld
|
||||
|
||||
exp="content-encoding: br
|
||||
hello world
|
||||
response_code: 200"
|
||||
|
||||
nginx -t
|
||||
invoke-rc.d nginx restart || { journalctl -n all -xu nginx.service; exit 1; }
|
||||
|
||||
out=`curl --compressed --fail -D- -w "response_code: %{http_code}\n" http://127.0.0.1/helloworld`
|
||||
out=`echo "${out}" | sed 's/\r//'`
|
||||
out=`echo "${out}" | awk '{print tolower($0)}'`
|
||||
out=`echo "${out}" | grep '^content-encoding: \|^hello world$\|response_code: '`
|
||||
|
||||
if [ x"${out}" != x"${exp}" ]; then
|
||||
echo "output:"
|
||||
echo "====================="
|
||||
echo "${out}"
|
||||
echo "====================="
|
||||
echo "expected output:"
|
||||
echo "====================="
|
||||
echo "${exp}"
|
||||
echo "====================="
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#!/bin/sh
|
||||
# version 20221215
|
||||
|
||||
# generic test that only verifies that nginx is running with the given
|
||||
# libnginx-... module
|
||||
# - after installation
|
||||
# - after nginx reload
|
||||
# - after nginx restart
|
||||
|
||||
EX=0
|
||||
CURL_CMD="curl --max-time 60 --silent --fail -o /dev/null"
|
||||
|
||||
#change directory to $AUTOPKGTEST_TMP
|
||||
cd "${AUTOPKGTEST_TMP}"
|
||||
|
||||
echo -n "curl after installation: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
echo -n "nginx reload ... "
|
||||
if invoke-rc.d nginx reload; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
sleep 5
|
||||
|
||||
|
||||
echo -n "curl after reload: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
echo -n "nginx restart ... "
|
||||
if invoke-rc.d nginx restart; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
sleep 5
|
||||
|
||||
echo -n "curl after restart: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
if [ ${EX} -ne 0 ]; then
|
||||
echo "=== journalctl ==="
|
||||
journalctl -n all -xu nginx.service || :
|
||||
|
||||
echo "=== error.log ==="
|
||||
if [ `wc -l /var/log/nginx/error.log | cut -d ' ' -f1` -gt 100 ]; then
|
||||
head -n 50 /var/log/nginx/error.log
|
||||
echo '...'
|
||||
tail -n 50 /var/log/nginx/error.log
|
||||
else
|
||||
cat /var/log/nginx/error.log
|
||||
fi
|
||||
fi
|
||||
|
||||
exit ${EX}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cat <<EOF > "/etc/nginx/sites-enabled/default"
|
||||
server {
|
||||
listen 80 default_server;
|
||||
root /var/www/html;
|
||||
|
||||
location /helloworld {
|
||||
brotli_static on;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
mkdir -p /var/www/html
|
||||
echo 'hello world' | brotli -9 > /var/www/html/helloworld.br
|
||||
|
||||
exp="hello world
|
||||
response_code: 200"
|
||||
|
||||
nginx -t
|
||||
invoke-rc.d nginx restart || { journalctl -n all -xu nginx.service; exit 1; }
|
||||
|
||||
out=`curl --compressed --fail -w "response_code: %{http_code}\n" http://127.0.0.1/helloworld`
|
||||
|
||||
if [ x"${out}" != x"${exp}" ]; then
|
||||
echo "output:"
|
||||
echo "====================="
|
||||
echo "${out}"
|
||||
echo "====================="
|
||||
echo "expected output:"
|
||||
echo "====================="
|
||||
echo "${exp}"
|
||||
echo "====================="
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
Bug-Database: https://github.com/google/ngx_brotli/issues
|
||||
Bug-Submit: https://github.com/google/ngx_brotli/issues/new
|
||||
Repository-Browse: https://github.com/google/ngx_brotli
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
version=4
|
||||
opts="\
|
||||
uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha|a|b)\d*)$/$1~$2/,\
|
||||
" \
|
||||
https://github.com/google/ngx_brotli/tags \
|
||||
(?:.*?/)?v?@ANY_VERSION@@ARCHIVE_EXT@
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
# Copyright (C) 2015-2016 Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
if [ "$ngx_addon_name" = "ngx_brotli" ]; then
|
||||
BROTLI_MODULE_SRC_DIR="$ngx_addon_dir/filter"
|
||||
else
|
||||
BROTLI_MODULE_SRC_DIR="$ngx_addon_dir"
|
||||
fi
|
||||
|
||||
ngx_addon_name=ngx_brotli_filter
|
||||
|
||||
if [ -z "$ngx_module_link" ]; then
|
||||
cat << END
|
||||
|
||||
$0: error: Brotli module requires recent version of NGINX (1.9.11+).
|
||||
|
||||
END
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ngx_module_type=HTTP_FILTER
|
||||
ngx_module_name=ngx_http_brotli_filter_module
|
||||
|
||||
brotli="$ngx_addon_dir/deps/brotli/c"
|
||||
if [ ! -f "$brotli/include/brotli/encode.h" ]; then
|
||||
brotli="/usr/local"
|
||||
fi
|
||||
if [ ! -f "$brotli/include/brotli/encode.h" ]; then
|
||||
brotli="/usr"
|
||||
fi
|
||||
if [ ! -f "$brotli/include/brotli/encode.h" ]; then
|
||||
cat << END
|
||||
|
||||
$0: error: \
|
||||
Brotli library is missing from the $brotli directory.
|
||||
|
||||
Please make sure that the git submodule has been checked out:
|
||||
|
||||
cd $ngx_addon_dir && git submodule update --init && cd $PWD
|
||||
|
||||
END
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BROTLI_LISTS_FILE="$brotli/../scripts/sources.lst"
|
||||
|
||||
if [ -f "$BROTLI_LISTS_FILE" ]; then
|
||||
|
||||
BROTLI_LISTS=`cat "$BROTLI_LISTS_FILE" | grep -v "#" | tr '\n' '#' | \
|
||||
sed 's/\\\\#//g' | tr -s ' ' '+' | tr -s '#' ' ' | \
|
||||
sed 's/+c/+$brotli/g' | sed 's/+=+/=/g'`
|
||||
for ITEM in ${BROTLI_LISTS}; do
|
||||
VAR=`echo $ITEM | sed 's/=.*//'`
|
||||
VAL=`echo $ITEM | sed 's/.*=//' | tr '+' ' '`
|
||||
eval ${VAR}=\"$VAL\"
|
||||
done
|
||||
|
||||
else # BROTLI_LISTS_FILE
|
||||
|
||||
BROTLI_ENC_H="$brotli/include/brotli/encode.h \
|
||||
$brotli/include/brotli/port.h \
|
||||
$brotli/include/brotli/types.h"
|
||||
BROTLI_ENC_LIB="-lbrotlienc"
|
||||
|
||||
fi
|
||||
|
||||
ngx_module_incs="$brotli/include"
|
||||
ngx_module_deps="$BROTLI_COMMON_H $BROTLI_ENC_H"
|
||||
ngx_module_srcs="$BROTLI_COMMON_C $BROTLI_ENC_C \
|
||||
$BROTLI_MODULE_SRC_DIR/ngx_http_brotli_filter_module.c"
|
||||
ngx_module_libs="$BROTLI_ENC_LIB -lm"
|
||||
ngx_module_order="$ngx_module_name \
|
||||
ngx_pagespeed \
|
||||
ngx_http_postpone_filter_module \
|
||||
ngx_http_ssi_filter_module \
|
||||
ngx_http_charset_filter_module \
|
||||
ngx_http_xslt_filter_module \
|
||||
ngx_http_image_filter_module \
|
||||
ngx_http_sub_filter_module \
|
||||
ngx_http_addition_filter_module \
|
||||
ngx_http_gunzip_filter_module \
|
||||
ngx_http_userid_filter_module \
|
||||
ngx_http_headers_filter_module \
|
||||
ngx_http_copy_filter_module \
|
||||
ngx_http_range_body_filter_module \
|
||||
ngx_http_not_modified_filter_module \
|
||||
ngx_http_slice_filter_module"
|
||||
|
||||
. auto/module
|
||||
|
||||
if [ "$ngx_module_link" != DYNAMIC ]; then
|
||||
# ngx_module_order doesn't work with static modules,
|
||||
# so we must re-order filters here.
|
||||
|
||||
if [ "$HTTP_GZIP" = YES ]; then
|
||||
next=ngx_http_gzip_filter_module
|
||||
elif echo $HTTP_FILTER_MODULES | grep pagespeed_etag_filter >/dev/null; then
|
||||
next=ngx_pagespeed_etag_filter
|
||||
else
|
||||
next=ngx_http_range_header_filter_module
|
||||
fi
|
||||
|
||||
HTTP_FILTER_MODULES=`echo $HTTP_FILTER_MODULES \
|
||||
| sed "s/$ngx_module_name//" \
|
||||
| sed "s/$next/$next $ngx_module_name/"`
|
||||
fi
|
||||
|
||||
CFLAGS="$CFLAGS -Wno-deprecated-declarations"
|
||||
|
||||
have=NGX_HTTP_BROTLI_FILTER . auto/have
|
||||
have=NGX_HTTP_BROTLI_FILTER_MODULE . auto/have # deprecated
|
||||
|
|
@ -1,770 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
* Copyright (C) Google Inc.
|
||||
*/
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
#if (NGX_HAVE_BROTLI_ENC_ENCODE_H)
|
||||
#include <brotli/enc/encode.h>
|
||||
#else
|
||||
#include <brotli/encode.h>
|
||||
#endif
|
||||
|
||||
/* Brotli and GZip modules never stack, i.e. when one of them sets
|
||||
"Content-Encoding" the other becomes a pass-through filter. Consequently,
|
||||
it is almost legal to reuse this "buffered" bit.
|
||||
IIUC, buffered == some data passed to filter has not been pushed further. */
|
||||
#define NGX_HTTP_BROTLI_BUFFERED NGX_HTTP_GZIP_BUFFERED
|
||||
|
||||
/* Module configuration. */
|
||||
typedef struct {
|
||||
ngx_flag_t enable;
|
||||
|
||||
/* Supported MIME types. */
|
||||
ngx_hash_t types;
|
||||
ngx_array_t* types_keys;
|
||||
|
||||
/* Minimal required length for compression (if known). */
|
||||
ssize_t min_length;
|
||||
|
||||
ngx_bufs_t deprecated_unused_bufs;
|
||||
|
||||
/* Brotli encoder parameter: quality */
|
||||
ngx_int_t quality;
|
||||
|
||||
/* Brotli encoder parameter: (max) lg_win */
|
||||
size_t lg_win;
|
||||
} ngx_http_brotli_conf_t;
|
||||
|
||||
/* Instance context. */
|
||||
typedef struct {
|
||||
/* Brotli encoder instance. */
|
||||
BrotliEncoderState* encoder;
|
||||
|
||||
/* Payload length; -1, if unknown. */
|
||||
off_t content_length;
|
||||
|
||||
/* (uncompressed) bytes pushed to encoder. */
|
||||
size_t bytes_in;
|
||||
/* (compressed) bytes pulled from encoder. */
|
||||
size_t bytes_out;
|
||||
|
||||
/* Input buffer chain. */
|
||||
ngx_chain_t* in;
|
||||
|
||||
/* Output chain. */
|
||||
ngx_chain_t* out_chain;
|
||||
|
||||
/* Output buffer. */
|
||||
ngx_buf_t* out_buf;
|
||||
|
||||
/* Various state flags. */
|
||||
|
||||
/* 1 if encoder is initialized, output chain and buffer are allocated. */
|
||||
unsigned initialized : 1;
|
||||
/* 1 if compression is finished / failed. */
|
||||
unsigned closed : 1;
|
||||
/* 1 if compression is finished. */
|
||||
unsigned success : 1;
|
||||
|
||||
/* 1 if out_chain is ready to be committed, 0 otherwise. */
|
||||
unsigned output_ready : 1;
|
||||
/* 1 if output buffer is committed to the next filter and not yet fully used.
|
||||
0 otherwise. */
|
||||
unsigned output_busy : 1;
|
||||
|
||||
unsigned end_of_input : 1;
|
||||
unsigned end_of_block : 1;
|
||||
|
||||
ngx_http_request_t* request;
|
||||
} ngx_http_brotli_ctx_t;
|
||||
|
||||
/* Forward declarations. */
|
||||
|
||||
/* Initializes encoder, output chain and buffer, if necessary. Returns NGX_OK
|
||||
if encoder is successfully initialized (have been already initialized),
|
||||
and requires objects are allocated. Returns NGX_ERROR otherwise. */
|
||||
static ngx_int_t ngx_http_brotli_filter_ensure_stream_initialized(
|
||||
ngx_http_request_t* r, ngx_http_brotli_ctx_t* ctx);
|
||||
/* Marks instance as closed and performs cleanup. */
|
||||
static void ngx_http_brotli_filter_close(ngx_http_brotli_ctx_t* ctx);
|
||||
|
||||
static void* ngx_http_brotli_filter_alloc(void* opaque, size_t size);
|
||||
static void ngx_http_brotli_filter_free(void* opaque, void* address);
|
||||
|
||||
static ngx_int_t ngx_http_brotli_check_request(ngx_http_request_t* r);
|
||||
|
||||
static ngx_int_t ngx_http_brotli_add_variables(ngx_conf_t* cf);
|
||||
static ngx_int_t ngx_http_brotli_ratio_variable(ngx_http_request_t* r,
|
||||
ngx_http_variable_value_t* v,
|
||||
uintptr_t data);
|
||||
|
||||
static void* ngx_http_brotli_create_conf(ngx_conf_t* cf);
|
||||
static char* ngx_http_brotli_merge_conf(ngx_conf_t* cf, void* parent,
|
||||
void* child);
|
||||
static ngx_int_t ngx_http_brotli_filter_init(ngx_conf_t* cf);
|
||||
|
||||
static char* ngx_http_brotli_parse_wbits(ngx_conf_t* cf, void* post,
|
||||
void* data);
|
||||
|
||||
/* Configuration literals. */
|
||||
|
||||
static ngx_conf_num_bounds_t ngx_http_brotli_comp_level_bounds = {
|
||||
ngx_conf_check_num_bounds, BROTLI_MIN_QUALITY, BROTLI_MAX_QUALITY};
|
||||
|
||||
static ngx_conf_post_handler_pt ngx_http_brotli_parse_wbits_p =
|
||||
ngx_http_brotli_parse_wbits;
|
||||
|
||||
static ngx_command_t ngx_http_brotli_filter_commands[] = {
|
||||
{ngx_string("brotli"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_HTTP_LIF_CONF | NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_brotli_conf_t, enable), NULL},
|
||||
|
||||
/* Deprecated, unused. */
|
||||
{ngx_string("brotli_buffers"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_CONF_TAKE2,
|
||||
ngx_conf_set_bufs_slot, NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_brotli_conf_t, deprecated_unused_bufs), NULL},
|
||||
|
||||
{ngx_string("brotli_types"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_CONF_1MORE,
|
||||
ngx_http_types_slot, NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_brotli_conf_t, types_keys),
|
||||
&ngx_http_html_default_types[0]},
|
||||
|
||||
{ngx_string("brotli_comp_level"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_CONF_TAKE1,
|
||||
ngx_conf_set_num_slot, NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_brotli_conf_t, quality),
|
||||
&ngx_http_brotli_comp_level_bounds},
|
||||
|
||||
{ngx_string("brotli_window"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_CONF_TAKE1,
|
||||
ngx_conf_set_size_slot, NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_brotli_conf_t, lg_win), &ngx_http_brotli_parse_wbits_p},
|
||||
|
||||
{ngx_string("brotli_min_length"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_CONF_TAKE1,
|
||||
ngx_conf_set_size_slot, NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_brotli_conf_t, min_length), NULL},
|
||||
|
||||
ngx_null_command};
|
||||
|
||||
/* Module context hooks. */
|
||||
static ngx_http_module_t ngx_http_brotli_filter_module_ctx = {
|
||||
ngx_http_brotli_add_variables, /* pre-configuration */
|
||||
ngx_http_brotli_filter_init, /* post-configuration */
|
||||
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
ngx_http_brotli_create_conf, /* create location configuration */
|
||||
ngx_http_brotli_merge_conf /* merge location configuration */
|
||||
};
|
||||
|
||||
/* Module descriptor. */
|
||||
ngx_module_t ngx_http_brotli_filter_module = {
|
||||
NGX_MODULE_V1,
|
||||
&ngx_http_brotli_filter_module_ctx, /* module context */
|
||||
ngx_http_brotli_filter_commands, /* module directives */
|
||||
NGX_HTTP_MODULE, /* module type */
|
||||
NULL, /* init master */
|
||||
NULL, /* init module */
|
||||
NULL, /* init process */
|
||||
NULL, /* init thread */
|
||||
NULL, /* exit thread */
|
||||
NULL, /* exit process */
|
||||
NULL, /* exit master */
|
||||
NGX_MODULE_V1_PADDING};
|
||||
|
||||
/* Variable names. */
|
||||
static ngx_str_t ngx_http_brotli_ratio = ngx_string("brotli_ratio");
|
||||
|
||||
/* Next filter in the filter chain. */
|
||||
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
|
||||
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
|
||||
|
||||
static /* const */ char kEncoding[] = "br";
|
||||
static const size_t kEncodingLen = 2;
|
||||
|
||||
static ngx_int_t check_accept_encoding(ngx_http_request_t* req) {
|
||||
ngx_table_elt_t* accept_encoding_entry;
|
||||
ngx_str_t* accept_encoding;
|
||||
u_char* cursor;
|
||||
u_char* end;
|
||||
u_char before;
|
||||
u_char after;
|
||||
|
||||
accept_encoding_entry = req->headers_in.accept_encoding;
|
||||
if (accept_encoding_entry == NULL) return NGX_DECLINED;
|
||||
accept_encoding = &accept_encoding_entry->value;
|
||||
|
||||
cursor = accept_encoding->data;
|
||||
end = cursor + accept_encoding->len;
|
||||
while (1) {
|
||||
u_char digit;
|
||||
/* It would be an idiotic idea to rely on compiler to produce performant
|
||||
binary, that is why we just do -1 at every call site. */
|
||||
cursor = ngx_strcasestrn(cursor, kEncoding, kEncodingLen - 1);
|
||||
if (cursor == NULL) return NGX_DECLINED;
|
||||
before = (cursor == accept_encoding->data) ? ' ' : cursor[-1];
|
||||
cursor += kEncodingLen;
|
||||
after = (cursor >= end) ? ' ' : *cursor;
|
||||
if (before != ',' && before != ' ') continue;
|
||||
if (after != ',' && after != ' ' && after != ';') continue;
|
||||
|
||||
/* Check for ";q=0[.[0[0[0]]]]" */
|
||||
while (*cursor == ' ') cursor++;
|
||||
if (*(cursor++) != ';') break;
|
||||
while (*cursor == ' ') cursor++;
|
||||
if (*(cursor++) != 'q') break;
|
||||
while (*cursor == ' ') cursor++;
|
||||
if (*(cursor++) != '=') break;
|
||||
while (*cursor == ' ') cursor++;
|
||||
if (*(cursor++) != '0') break;
|
||||
if (*(cursor++) != '.') return NGX_DECLINED; /* ;q=0, */
|
||||
digit = *(cursor++);
|
||||
if (digit < '0' || digit > '9') return NGX_DECLINED; /* ;q=0., */
|
||||
if (digit > '0') break;
|
||||
digit = *(cursor++);
|
||||
if (digit < '0' || digit > '9') return NGX_DECLINED; /* ;q=0.0, */
|
||||
if (digit > '0') break;
|
||||
digit = *(cursor++);
|
||||
if (digit < '0' || digit > '9') return NGX_DECLINED; /* ;q=0.00, */
|
||||
if (digit > '0') break;
|
||||
return NGX_DECLINED; /* ;q=0.000 */
|
||||
}
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* Process headers and decide if request is eligible for brotli compression. */
|
||||
static ngx_int_t ngx_http_brotli_header_filter(ngx_http_request_t* r) {
|
||||
ngx_table_elt_t* h;
|
||||
ngx_http_brotli_ctx_t* ctx;
|
||||
ngx_http_brotli_conf_t* conf;
|
||||
|
||||
conf = ngx_http_get_module_loc_conf(r, ngx_http_brotli_filter_module);
|
||||
|
||||
/* Filter only if enabled. */
|
||||
if (!conf->enable) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
/* Only compress OK / forbidden / not found responses. */
|
||||
if (r->headers_out.status != NGX_HTTP_OK &&
|
||||
r->headers_out.status != NGX_HTTP_FORBIDDEN &&
|
||||
r->headers_out.status != NGX_HTTP_NOT_FOUND) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
/* Bypass "header only" responses. */
|
||||
if (r->header_only) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
/* Bypass already compressed responses. */
|
||||
if (r->headers_out.content_encoding &&
|
||||
r->headers_out.content_encoding->value.len) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
/* If response size is known, do not compress tiny responses. */
|
||||
if (r->headers_out.content_length_n != -1 &&
|
||||
r->headers_out.content_length_n < conf->min_length) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
/* Compress only certain MIME-typed responses. */
|
||||
if (ngx_http_test_content_type(r, &conf->types) == NULL) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
r->gzip_vary = 1;
|
||||
|
||||
/* Check if client support brotli encoding. */
|
||||
if (ngx_http_brotli_check_request(r) != NGX_OK) {
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
/* Prepare instance context. */
|
||||
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_brotli_ctx_t));
|
||||
if (ctx == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ctx->request = r;
|
||||
ctx->content_length = r->headers_out.content_length_n;
|
||||
ngx_http_set_ctx(r, ctx, ngx_http_brotli_filter_module);
|
||||
|
||||
/* Prepare response headers, so that following filters in the chain will
|
||||
notice that response body is compressed. */
|
||||
h = ngx_list_push(&r->headers_out.headers);
|
||||
if (h == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
h->hash = 1;
|
||||
ngx_str_set(&h->key, "Content-Encoding");
|
||||
ngx_str_set(&h->value, "br");
|
||||
r->headers_out.content_encoding = h;
|
||||
|
||||
r->main_filter_need_in_memory = 1;
|
||||
|
||||
ngx_http_clear_content_length(r);
|
||||
ngx_http_clear_accept_ranges(r);
|
||||
ngx_http_weak_etag(r);
|
||||
|
||||
return ngx_http_next_header_filter(r);
|
||||
}
|
||||
|
||||
/* Response body filtration (compression). */
|
||||
static ngx_int_t ngx_http_brotli_body_filter(ngx_http_request_t* r,
|
||||
ngx_chain_t* in) {
|
||||
int rc;
|
||||
ngx_http_brotli_ctx_t* ctx;
|
||||
size_t available_output;
|
||||
ptrdiff_t available_busy_output;
|
||||
size_t input_size;
|
||||
size_t available_input;
|
||||
const uint8_t* next_input_byte;
|
||||
size_t consumed_input;
|
||||
BROTLI_BOOL ok;
|
||||
u_char* out;
|
||||
ngx_chain_t* link;
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_brotli_filter_module);
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http brotli filter");
|
||||
|
||||
if (ctx == NULL || ctx->closed || r->header_only) {
|
||||
return ngx_http_next_body_filter(r, in);
|
||||
}
|
||||
|
||||
if (ngx_http_brotli_filter_ensure_stream_initialized(r, ctx) != NGX_OK) {
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* If more input is provided - append it to our input chain. */
|
||||
if (in) {
|
||||
if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
r->connection->buffered |= NGX_HTTP_BROTLI_BUFFERED;
|
||||
}
|
||||
|
||||
/* Main loop:
|
||||
- if output is not yet consumed - stop; encoder should not be touched,
|
||||
until all the output is consumed
|
||||
- if encoder has output - wrap it and send to consumer
|
||||
- if encoder is finished (and all output is consumed) - stop
|
||||
- if there is more input - push it to encoder */
|
||||
for (;;) {
|
||||
if (ctx->output_busy || ctx->output_ready) {
|
||||
if (ctx->output_busy) {
|
||||
available_busy_output = ngx_buf_size(ctx->out_buf);
|
||||
} else {
|
||||
available_busy_output = 0;
|
||||
}
|
||||
|
||||
rc = ngx_http_next_body_filter(r,
|
||||
ctx->output_ready ? ctx->out_chain : NULL);
|
||||
if (ctx->output_ready) {
|
||||
ctx->output_ready = 0;
|
||||
ctx->output_busy = 1;
|
||||
}
|
||||
if (ngx_buf_size(ctx->out_buf) == 0) {
|
||||
ctx->output_busy = 0;
|
||||
}
|
||||
if (rc == NGX_OK) {
|
||||
if (ctx->output_busy &&
|
||||
available_busy_output == ngx_buf_size(ctx->out_buf)) {
|
||||
r->connection->buffered |= NGX_HTTP_BROTLI_BUFFERED;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
continue;
|
||||
} else if (rc == NGX_AGAIN) {
|
||||
if (ctx->output_busy) {
|
||||
/* Can't continue compression, let the outer filer decide. */
|
||||
if (ctx->in != NULL) {
|
||||
r->connection->buffered |= NGX_HTTP_BROTLI_BUFFERED;
|
||||
}
|
||||
return NGX_AGAIN;
|
||||
} else {
|
||||
/* Inner filter has given up, but we can continue processing. */
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (BrotliEncoderHasMoreOutput(ctx->encoder)) {
|
||||
available_output = 0;
|
||||
out = (u_char*)BrotliEncoderTakeOutput(ctx->encoder, &available_output);
|
||||
if (out == NULL || available_output == 0) {
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ctx->out_buf->start = out;
|
||||
ctx->out_buf->pos = out;
|
||||
ctx->out_buf->last = out + available_output;
|
||||
ctx->out_buf->end = out + available_output;
|
||||
ctx->bytes_out += available_output;
|
||||
ctx->out_buf->last_buf = 0;
|
||||
ctx->out_buf->flush = 0;
|
||||
if (ctx->end_of_input && BrotliEncoderIsFinished(ctx->encoder)) {
|
||||
ctx->out_buf->last_buf = 1;
|
||||
r->connection->buffered &= ~NGX_HTTP_BROTLI_BUFFERED;
|
||||
} else if (ctx->end_of_block) {
|
||||
ctx->out_buf->flush = 1;
|
||||
r->connection->buffered &= ~NGX_HTTP_BROTLI_BUFFERED;
|
||||
}
|
||||
ctx->end_of_block = 0;
|
||||
ctx->output_ready = 1;
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"brotli out: %p, size:%uz", ctx->out_buf,
|
||||
ngx_buf_size(ctx->out_buf));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BrotliEncoderIsFinished(ctx->encoder)) {
|
||||
ctx->success = 1;
|
||||
r->connection->buffered &= ~NGX_HTTP_BROTLI_BUFFERED;
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ctx->end_of_input) {
|
||||
// Ask the encoder to dump the leftover.
|
||||
available_input = 0;
|
||||
available_output = 0;
|
||||
ok = BrotliEncoderCompressStream(ctx->encoder, BROTLI_OPERATION_FINISH,
|
||||
&available_input, NULL,
|
||||
&available_output, NULL, NULL);
|
||||
r->connection->buffered |= NGX_HTTP_BROTLI_BUFFERED;
|
||||
if (!ok) {
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->in == NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* TODO: coalesce tiny inputs, if they are not last/flush. */
|
||||
input_size = ngx_buf_size(ctx->in->buf);
|
||||
if (input_size == 0) {
|
||||
if (!ctx->in->buf->last_buf && !ctx->in->buf->flush) {
|
||||
link = ctx->in;
|
||||
ctx->in = ctx->in->next;
|
||||
ngx_free_chain(r->pool, link);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
available_input = input_size;
|
||||
next_input_byte = (const uint8_t*)ctx->in->buf->pos;
|
||||
available_output = 0;
|
||||
ok = BrotliEncoderCompressStream(
|
||||
ctx->encoder,
|
||||
ctx->in->buf->last_buf ? BROTLI_OPERATION_FINISH
|
||||
: ctx->in->buf->flush ? BROTLI_OPERATION_FLUSH
|
||||
: BROTLI_OPERATION_PROCESS,
|
||||
&available_input, &next_input_byte, &available_output, NULL, NULL);
|
||||
r->connection->buffered |= NGX_HTTP_BROTLI_BUFFERED;
|
||||
if (!ok) {
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
consumed_input = input_size - available_input;
|
||||
ctx->bytes_in += consumed_input;
|
||||
ctx->in->buf->pos += consumed_input;
|
||||
|
||||
if (consumed_input == input_size) {
|
||||
if (ctx->in->buf->last_buf) {
|
||||
ctx->end_of_input = 1;
|
||||
} else if (ctx->in->buf->flush) {
|
||||
ctx->end_of_block = 1;
|
||||
}
|
||||
link = ctx->in;
|
||||
ctx->in = ctx->in->next;
|
||||
ngx_free_chain(r->pool, link);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Should never happen, just to make sure we don't enter infinite loop. */
|
||||
if (consumed_input == 0) {
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* unreachable */
|
||||
ngx_http_brotli_filter_close(ctx);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
static ngx_int_t ngx_http_brotli_filter_ensure_stream_initialized(
|
||||
ngx_http_request_t* r, ngx_http_brotli_ctx_t* ctx) {
|
||||
ngx_http_brotli_conf_t* conf;
|
||||
BROTLI_BOOL ok;
|
||||
size_t wbits;
|
||||
|
||||
if (ctx->initialized) {
|
||||
return NGX_OK;
|
||||
}
|
||||
ctx->initialized = 1;
|
||||
|
||||
conf = ngx_http_get_module_loc_conf(r, ngx_http_brotli_filter_module);
|
||||
|
||||
/* Tune lg_win, if size is known. */
|
||||
if (ctx->content_length > 0) {
|
||||
wbits = BROTLI_MIN_WINDOW_BITS;
|
||||
while ((wbits < conf->lg_win) && (ctx->content_length > (1 << wbits))) {
|
||||
wbits++;
|
||||
}
|
||||
} else {
|
||||
wbits = conf->lg_win;
|
||||
}
|
||||
|
||||
ctx->encoder = BrotliEncoderCreateInstance(
|
||||
ngx_http_brotli_filter_alloc, ngx_http_brotli_filter_free, r->pool);
|
||||
if (ctx->encoder == NULL) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"OOM / BrotliEncoderCreateInstance");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ok = BrotliEncoderSetParameter(ctx->encoder, BROTLI_PARAM_QUALITY,
|
||||
(uint32_t)conf->quality);
|
||||
if (!ok) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"BrotliEncoderSetParameter(QUALITY, %uD) failed",
|
||||
(uint32_t)conf->quality);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ok = BrotliEncoderSetParameter(ctx->encoder, BROTLI_PARAM_LGWIN,
|
||||
(uint32_t)wbits);
|
||||
if (!ok) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"BrotliEncoderSetParameter(LGWIN, %uD) failed",
|
||||
(uint32_t)wbits);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->out_buf = ngx_calloc_buf(r->pool);
|
||||
if (ctx->out_buf == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ctx->out_buf->temporary = 1;
|
||||
|
||||
ctx->out_chain = ngx_alloc_chain_link(r->pool);
|
||||
if (ctx->out_chain == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ctx->out_chain->buf = ctx->out_buf;
|
||||
ctx->out_chain->next = NULL;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"brotli encoder initialized: lvl:%i win:%d", conf->quality,
|
||||
(1 << wbits));
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
static void* ngx_http_brotli_filter_alloc(void* opaque, size_t size) {
|
||||
ngx_pool_t* pool = opaque;
|
||||
void* p;
|
||||
|
||||
p = ngx_palloc(pool, size);
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pool->log, 0, "brotli alloc: %p, size:%uz",
|
||||
p, size);
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void ngx_http_brotli_filter_free(void* opaque, void* address) {
|
||||
ngx_pool_t* pool = opaque;
|
||||
|
||||
#if (NGX_DEBUG)
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pool->log, 0, "brotli free: %p", address);
|
||||
#endif
|
||||
|
||||
ngx_pfree(pool, address);
|
||||
}
|
||||
|
||||
static void ngx_http_brotli_filter_close(ngx_http_brotli_ctx_t* ctx) {
|
||||
ctx->closed = 1;
|
||||
if (ctx->encoder) {
|
||||
BrotliEncoderDestroyInstance(ctx->encoder);
|
||||
ctx->encoder = NULL;
|
||||
}
|
||||
if (ctx->out_chain) {
|
||||
ngx_free_chain(ctx->request->pool, ctx->out_chain);
|
||||
ctx->out_chain = NULL;
|
||||
}
|
||||
if (ctx->out_buf) {
|
||||
ngx_pfree(ctx->request->pool, ctx->out_buf);
|
||||
ctx->out_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static ngx_int_t ngx_http_brotli_check_request(ngx_http_request_t* req) {
|
||||
if (req != req->main) return NGX_DECLINED;
|
||||
if (check_accept_encoding(req) != NGX_OK) return NGX_DECLINED;
|
||||
req->gzip_tested = 1;
|
||||
req->gzip_ok = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
static ngx_int_t ngx_http_brotli_add_variables(ngx_conf_t* cf) {
|
||||
ngx_http_variable_t* var;
|
||||
|
||||
var = ngx_http_add_variable(cf, &ngx_http_brotli_ratio, 0);
|
||||
if (var == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
var->get_handler = ngx_http_brotli_ratio_variable;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
static ngx_int_t ngx_http_brotli_ratio_variable(ngx_http_request_t* r,
|
||||
ngx_http_variable_value_t* v,
|
||||
uintptr_t data) {
|
||||
ngx_uint_t ratio_int;
|
||||
ngx_uint_t ratio_frac;
|
||||
ngx_http_brotli_ctx_t* ctx;
|
||||
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_brotli_filter_module);
|
||||
|
||||
/* Only report variable on non-failing streams. */
|
||||
if (ctx == NULL || !ctx->success) {
|
||||
v->not_found = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN + 3);
|
||||
if (v->data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ratio_int = (ngx_uint_t)(ctx->bytes_in / ctx->bytes_out);
|
||||
ratio_frac = (ngx_uint_t)((ctx->bytes_in * 100 / ctx->bytes_out) % 100);
|
||||
|
||||
/* Rounding; e.g. 2.125 to 2.13 */
|
||||
if ((ctx->bytes_in * 1000 / ctx->bytes_out) % 10 > 4) {
|
||||
ratio_frac++;
|
||||
if (ratio_frac > 99) {
|
||||
ratio_int++;
|
||||
ratio_frac = 0;
|
||||
}
|
||||
}
|
||||
|
||||
v->len = ngx_sprintf(v->data, "%ui.%02ui", ratio_int, ratio_frac) - v->data;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
static void* ngx_http_brotli_create_conf(ngx_conf_t* cf) {
|
||||
ngx_http_brotli_conf_t* conf;
|
||||
|
||||
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_brotli_conf_t));
|
||||
if (conf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ngx_pcalloc fills result with zeros ->
|
||||
conf->bufs.num = 0;
|
||||
conf->types = { NULL };
|
||||
conf->types_keys = NULL; */
|
||||
|
||||
conf->enable = NGX_CONF_UNSET;
|
||||
|
||||
conf->quality = NGX_CONF_UNSET;
|
||||
conf->lg_win = NGX_CONF_UNSET_SIZE;
|
||||
conf->min_length = NGX_CONF_UNSET;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
static char* ngx_http_brotli_merge_conf(ngx_conf_t* cf, void* parent,
|
||||
void* child) {
|
||||
ngx_http_brotli_conf_t* prev = parent;
|
||||
ngx_http_brotli_conf_t* conf = child;
|
||||
char* rc;
|
||||
|
||||
ngx_conf_merge_value(conf->enable, prev->enable, 0);
|
||||
|
||||
ngx_conf_merge_value(conf->quality, prev->quality, 6);
|
||||
ngx_conf_merge_size_value(conf->lg_win, prev->lg_win, 19);
|
||||
ngx_conf_merge_value(conf->min_length, prev->min_length, 20);
|
||||
|
||||
rc = ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
|
||||
&prev->types_keys, &prev->types,
|
||||
ngx_http_html_default_types);
|
||||
if (rc != NGX_CONF_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
/* Prepend to filter chain. */
|
||||
static ngx_int_t ngx_http_brotli_filter_init(ngx_conf_t* cf) {
|
||||
ngx_http_next_header_filter = ngx_http_top_header_filter;
|
||||
ngx_http_top_header_filter = ngx_http_brotli_header_filter;
|
||||
|
||||
ngx_http_next_body_filter = ngx_http_top_body_filter;
|
||||
ngx_http_top_body_filter = ngx_http_brotli_body_filter;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* Translate "window size" to window bits (log2), and check bounds. */
|
||||
static char* ngx_http_brotli_parse_wbits(ngx_conf_t* cf, void* post,
|
||||
void* data) {
|
||||
size_t* parameter = data;
|
||||
size_t bits;
|
||||
size_t wsize;
|
||||
|
||||
for (bits = BROTLI_MIN_WINDOW_BITS; bits <= BROTLI_MAX_WINDOW_BITS; bits++) {
|
||||
wsize = 1u << bits;
|
||||
if (*parameter == wsize) {
|
||||
*parameter = bits;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return "must be 1k, 2k, 4k, 8k, 16k, 32k, 64k, 128k, 256k, 512k, 1m, 2m, 4m, "
|
||||
"8m or 16m";
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
# Setup shortcuts.
|
||||
ROOT=`pwd`
|
||||
FILES=$ROOT/script/test
|
||||
|
||||
# Setup directory structure.
|
||||
cd $ROOT/script
|
||||
if [ ! -d test ]; then
|
||||
mkdir test
|
||||
fi
|
||||
cd test
|
||||
if [ ! -d logs ]; then
|
||||
mkdir logs
|
||||
fi
|
||||
|
||||
# Download sample texts.
|
||||
curl --compressed -o $FILES/war-and-peace.txt http://www.gutenberg.org/files/2600/2600-0.txt
|
||||
echo "Kot lomom kolol slona!" > $FILES/small.txt
|
||||
echo "<html>Kot lomom kolol slona!</html>" > $FILES/small.html
|
||||
|
||||
# Restore status-quo.
|
||||
cd $ROOT
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
# Setup shortcuts.
|
||||
ROOT=`pwd`
|
||||
|
||||
# Clone nginx read-only git repository.
|
||||
if [ ! -d "nginx" ]; then
|
||||
git clone https://github.com/nginx/nginx.git
|
||||
fi
|
||||
|
||||
# Build nginx + filter module.
|
||||
cd $ROOT/nginx
|
||||
# Pro memoria: --with-debug
|
||||
./auto/configure \
|
||||
--prefix=$ROOT/script/test \
|
||||
--with-http_v2_module \
|
||||
--add-module=$ROOT
|
||||
make -j 16
|
||||
|
||||
# Build brotli CLI.
|
||||
cd $ROOT/deps/brotli
|
||||
mkdir out
|
||||
cd out
|
||||
cmake ..
|
||||
make -j 16 brotli
|
||||
|
||||
# Restore status-quo.
|
||||
cd $ROOT
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Setup shortcuts.
|
||||
ROOT=`pwd`
|
||||
NGINX=$ROOT/nginx/objs/nginx
|
||||
BROTLI=$ROOT/deps/brotli/out/brotli
|
||||
SERVER=http://localhost:8080
|
||||
FILES=$ROOT/script/test
|
||||
HR="---------------------------------------------------------------------------"
|
||||
|
||||
if [ ! -d tmp ]; then
|
||||
mkdir tmp
|
||||
fi
|
||||
|
||||
rm tmp/*
|
||||
|
||||
add_result() {
|
||||
echo $1 >&2
|
||||
echo $1 >> tmp/results.log
|
||||
}
|
||||
|
||||
get_failed() {
|
||||
echo `cat tmp/results.log | grep -v OK | wc -l`
|
||||
}
|
||||
|
||||
get_count() {
|
||||
echo `cat tmp/results.log | wc -l`
|
||||
}
|
||||
|
||||
expect_equal() {
|
||||
expected=$1
|
||||
actual=$2
|
||||
if cmp $expected $actual; then
|
||||
add_result "OK"
|
||||
else
|
||||
add_result "FAIL (equality)"
|
||||
fi
|
||||
}
|
||||
|
||||
expect_br_equal() {
|
||||
expected=$1
|
||||
actual_br=$2
|
||||
if $BROTLI -dfk ./${actual_br}.br; then
|
||||
expect_equal $expected $actual_br
|
||||
else
|
||||
add_result "FAIL (decompression)"
|
||||
fi
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
||||
# Start default server.
|
||||
echo "Statring NGINX"
|
||||
$NGINX -c $ROOT/script/test.conf
|
||||
# Fetch vanilla 404 response.
|
||||
curl -s -o tmp/notfound.txt $SERVER/notfound
|
||||
|
||||
CURL="curl -s"
|
||||
|
||||
# Run tests.
|
||||
echo $HR
|
||||
|
||||
echo "Test: long file with rate limit"
|
||||
$CURL -H 'Accept-encoding: br' -o tmp/war-and-peace.br --limit-rate 300K $SERVER/war-and-peace.txt
|
||||
expect_br_equal $FILES/war-and-peace.txt tmp/war-and-peace
|
||||
|
||||
echo "Test: compressed 404"
|
||||
$CURL -H 'Accept-encoding: br' -o tmp/notfound.br $SERVER/notfound
|
||||
expect_br_equal tmp/notfound.txt tmp/notfound
|
||||
|
||||
echo "Test: A-E: 'gzip, br'"
|
||||
$CURL -H 'Accept-encoding: gzip, br' -o tmp/ae-01.br $SERVER/small.txt
|
||||
expect_br_equal $FILES/small.txt tmp/ae-01
|
||||
|
||||
echo "Test: A-E: 'gzip, br, deflate'"
|
||||
$CURL -H 'Accept-encoding: gzip, br, deflate' -o tmp/ae-02.br $SERVER/small.txt
|
||||
expect_br_equal $FILES/small.txt tmp/ae-02
|
||||
|
||||
echo "Test: A-E: 'gzip, br;q=1, deflate'"
|
||||
$CURL -H 'Accept-encoding: gzip, br;q=1, deflate' -o tmp/ae-03.br $SERVER/small.txt
|
||||
expect_br_equal $FILES/small.txt tmp/ae-03
|
||||
|
||||
echo "Test: A-E: 'br;q=0.001'"
|
||||
$CURL -H 'Accept-encoding: br;q=0.001' -o tmp/ae-04.br $SERVER/small.txt
|
||||
expect_br_equal $FILES/small.txt tmp/ae-04
|
||||
|
||||
echo "Test: A-E: 'bro'"
|
||||
$CURL -H 'Accept-encoding: bro' -o tmp/ae-05.txt $SERVER/small.txt
|
||||
expect_equal $FILES/small.txt tmp/ae-05.txt
|
||||
|
||||
echo "Test: A-E: 'bo'"
|
||||
$CURL -H 'Accept-encoding: bo' -o tmp/ae-06.txt $SERVER/small.txt
|
||||
expect_equal $FILES/small.txt tmp/ae-06.txt
|
||||
|
||||
echo "Test: A-E: 'br;q=0'"
|
||||
$CURL -H 'Accept-encoding: br;q=0' -o tmp/ae-07.txt $SERVER/small.txt
|
||||
expect_equal $FILES/small.txt tmp/ae-07.txt
|
||||
|
||||
echo "Test: A-E: 'br;q=0.'"
|
||||
$CURL -H 'Accept-encoding: br;q=0.' -o tmp/ae-08.txt $SERVER/small.txt
|
||||
expect_equal $FILES/small.txt tmp/ae-08.txt
|
||||
|
||||
echo "Test: A-E: 'br;q=0.0'"
|
||||
$CURL -H 'Accept-encoding: br;q=0.0' -o tmp/ae-09.txt $SERVER/small.txt
|
||||
expect_equal $FILES/small.txt tmp/ae-09.txt
|
||||
|
||||
echo "Test: A-E: 'br;q=0.00'"
|
||||
$CURL -H 'Accept-encoding: br;q=0.00' -o tmp/ae-10.txt $SERVER/small.txt
|
||||
expect_equal $FILES/small.txt tmp/ae-10.txt
|
||||
|
||||
echo "Test: A-E: 'br ; q = 0.000'"
|
||||
$CURL -H 'Accept-encoding: br ; q = 0.000' -o tmp/ae-11.txt $SERVER/small.txt
|
||||
expect_equal $FILES/small.txt tmp/ae-11.txt
|
||||
|
||||
echo "Test: A-E: 'bar'"
|
||||
$CURL -H 'Accept-encoding: bar' -o tmp/ae-12.txt $SERVER/small.html
|
||||
expect_equal $FILES/small.html tmp/ae-12.txt
|
||||
|
||||
echo "Test: A-E: 'b'"
|
||||
$CURL -H 'Accept-encoding: b' -o tmp/ae-13.txt $SERVER/small.html
|
||||
expect_equal $FILES/small.html tmp/ae-13.txt
|
||||
|
||||
echo $HR
|
||||
echo "Stopping default NGINX"
|
||||
# Stop server.
|
||||
$NGINX -c $ROOT/script/test.conf -s stop
|
||||
|
||||
################################################################################
|
||||
|
||||
# Start default server.
|
||||
echo "Statring h2 NGINX"
|
||||
$NGINX -c $ROOT/script/test_h2.conf
|
||||
|
||||
CURL="curl --http2-prior-knowledge -s"
|
||||
|
||||
# Run tests.
|
||||
echo $HR
|
||||
|
||||
echo "Test: long file with rate limit"
|
||||
$CURL -H 'Accept-encoding: br' -o tmp/h2-war-and-peace.br --limit-rate 300K $SERVER/war-and-peace.txt
|
||||
expect_br_equal $FILES/war-and-peace.txt tmp/h2-war-and-peace
|
||||
|
||||
echo "Test: A-E: 'gzip, br'"
|
||||
$CURL -H 'Accept-encoding: gzip, br' -o tmp/h2-ae-01.br $SERVER/small.txt
|
||||
expect_br_equal $FILES/small.txt tmp/h2-ae-01
|
||||
|
||||
echo "Test: A-E: 'b'"
|
||||
$CURL -H 'Accept-encoding: b' -o tmp/h2-ae-13.txt $SERVER/small.html
|
||||
expect_equal $FILES/small.html tmp/h2-ae-13.txt
|
||||
|
||||
echo $HR
|
||||
echo "Stopping h2 NGINX"
|
||||
# Stop server.
|
||||
$NGINX -c $ROOT/script/test_h2.conf -s stop
|
||||
|
||||
################################################################################
|
||||
|
||||
# Report.
|
||||
|
||||
FAILED=$(get_failed $STATUS)
|
||||
COUNT=$(get_count $STATUS)
|
||||
echo $HR
|
||||
echo "Results: $FAILED of $COUNT tests failed"
|
||||
|
||||
# Restore status-quo.
|
||||
cd $ROOT
|
||||
|
||||
exit $FAILED
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
events {
|
||||
worker_connections 4;
|
||||
}
|
||||
|
||||
daemon on;
|
||||
error_log /dev/stdout info;
|
||||
|
||||
http {
|
||||
access_log ./access.log;
|
||||
error_log ./error.log;
|
||||
|
||||
gzip on;
|
||||
gzip_comp_level 1;
|
||||
gzip_types text/plain text/css;
|
||||
|
||||
brotli on;
|
||||
brotli_comp_level 1;
|
||||
brotli_types text/plain text/css;
|
||||
|
||||
server {
|
||||
listen 8080 default_server;
|
||||
listen [::]:8080 default_server;
|
||||
|
||||
root ./;
|
||||
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
events {
|
||||
worker_connections 4;
|
||||
}
|
||||
|
||||
daemon on;
|
||||
error_log /dev/stdout info;
|
||||
|
||||
http {
|
||||
access_log ./access.log;
|
||||
error_log ./error.log;
|
||||
|
||||
gzip on;
|
||||
gzip_comp_level 1;
|
||||
gzip_types text/plain text/css;
|
||||
|
||||
brotli on;
|
||||
brotli_comp_level 1;
|
||||
brotli_types text/plain text/css;
|
||||
|
||||
server {
|
||||
listen 8080 http2;
|
||||
listen [::]:8080 http2;
|
||||
|
||||
root ./;
|
||||
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# Copyright (C) 2015-2019 Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
if [ "$ngx_addon_name" = "ngx_brotli" ]; then
|
||||
BROTLI_MODULE_SRC_DIR="$ngx_addon_dir/static"
|
||||
else
|
||||
BROTLI_MODULE_SRC_DIR="$ngx_addon_dir"
|
||||
fi
|
||||
|
||||
ngx_addon_name=ngx_brotli_static
|
||||
|
||||
if [ -z "$ngx_module_link" ]; then
|
||||
cat << END
|
||||
|
||||
$0: error: Brotli module requires recent version of NGINX (1.9.11+).
|
||||
|
||||
END
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ngx_module_type=HTTP
|
||||
ngx_module_name=ngx_http_brotli_static_module
|
||||
ngx_module_incs=
|
||||
ngx_module_deps=
|
||||
ngx_module_srcs="$BROTLI_MODULE_SRC_DIR/ngx_http_brotli_static_module.c"
|
||||
ngx_module_libs=
|
||||
ngx_module_order=
|
||||
|
||||
. auto/module
|
||||
|
||||
have=NGX_HTTP_GZIP . auto/have
|
||||
have=NGX_HTTP_BROTLI_STATIC . auto/have
|
||||
have=NGX_HTTP_BROTLI_STATIC_MODULE . auto/have # deprecated
|
||||
|
|
@ -1,323 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
* Copyright (C) Nginx, Inc.
|
||||
* Copyright (C) Google Inc.
|
||||
*/
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
/* >> Configuration */
|
||||
|
||||
#define NGX_HTTP_BROTLI_STATIC_OFF 0
|
||||
#define NGX_HTTP_BROTLI_STATIC_ON 1
|
||||
#define NGX_HTTP_BROTLI_STATIC_ALWAYS 2
|
||||
|
||||
typedef struct {
|
||||
ngx_uint_t enable;
|
||||
} configuration_t;
|
||||
|
||||
static ngx_conf_enum_t kBrotliStaticEnum[] = {
|
||||
{ngx_string("off"), NGX_HTTP_BROTLI_STATIC_OFF},
|
||||
{ngx_string("on"), NGX_HTTP_BROTLI_STATIC_ON},
|
||||
{ngx_string("always"), NGX_HTTP_BROTLI_STATIC_ALWAYS},
|
||||
{ngx_null_string, 0}};
|
||||
|
||||
/* << Configuration */
|
||||
|
||||
/* >> Forward declarations */
|
||||
|
||||
static ngx_int_t handler(ngx_http_request_t* req);
|
||||
static void* create_conf(ngx_conf_t* root_cfg);
|
||||
static char* merge_conf(ngx_conf_t* root_cfg, void* parent, void* child);
|
||||
static ngx_int_t init(ngx_conf_t* root_cfg);
|
||||
|
||||
/* << Forward declarations*/
|
||||
|
||||
/* >> Module definition */
|
||||
|
||||
static ngx_command_t kCommands[] = {
|
||||
{ngx_string("brotli_static"),
|
||||
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
|
||||
NGX_CONF_TAKE1,
|
||||
ngx_conf_set_enum_slot, NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(configuration_t, enable), &kBrotliStaticEnum},
|
||||
ngx_null_command};
|
||||
|
||||
static ngx_http_module_t kModuleContext = {
|
||||
NULL, /* preconfiguration */
|
||||
init, /* postconfiguration */
|
||||
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
create_conf, /* create location configuration */
|
||||
merge_conf /* merge location configuration */
|
||||
};
|
||||
|
||||
ngx_module_t ngx_http_brotli_static_module = {
|
||||
NGX_MODULE_V1,
|
||||
&kModuleContext, /* module context */
|
||||
kCommands, /* module directives */
|
||||
NGX_HTTP_MODULE, /* module type */
|
||||
NULL, /* init master */
|
||||
NULL, /* init module */
|
||||
NULL, /* init process */
|
||||
NULL, /* init thread */
|
||||
NULL, /* exit thread */
|
||||
NULL, /* exit process */
|
||||
NULL, /* exit master */
|
||||
NGX_MODULE_V1_PADDING};
|
||||
|
||||
/* << Module definition*/
|
||||
|
||||
static const u_char kContentEncoding[] = "Content-Encoding";
|
||||
static /* const */ char kEncoding[] = "br";
|
||||
static const size_t kEncodingLen = 2;
|
||||
static /* const */ u_char kSuffix[] = ".br";
|
||||
static const size_t kSuffixLen = 3;
|
||||
|
||||
static ngx_int_t check_accept_encoding(ngx_http_request_t* req) {
|
||||
ngx_table_elt_t* accept_encoding_entry;
|
||||
ngx_str_t* accept_encoding;
|
||||
u_char* cursor;
|
||||
u_char* end;
|
||||
u_char before;
|
||||
u_char after;
|
||||
|
||||
accept_encoding_entry = req->headers_in.accept_encoding;
|
||||
if (accept_encoding_entry == NULL) return NGX_DECLINED;
|
||||
accept_encoding = &accept_encoding_entry->value;
|
||||
|
||||
cursor = accept_encoding->data;
|
||||
end = cursor + accept_encoding->len;
|
||||
while (1) {
|
||||
u_char digit;
|
||||
/* It would be an idiotic idea to rely on compiler to produce performant
|
||||
binary, that is why we just do -1 at every call site. */
|
||||
cursor = ngx_strcasestrn(cursor, kEncoding, kEncodingLen - 1);
|
||||
if (cursor == NULL) return NGX_DECLINED;
|
||||
before = (cursor == accept_encoding->data) ? ' ' : cursor[-1];
|
||||
cursor += kEncodingLen;
|
||||
after = (cursor >= end) ? ' ' : *cursor;
|
||||
if (before != ',' && before != ' ') continue;
|
||||
if (after != ',' && after != ' ' && after != ';') continue;
|
||||
|
||||
/* Check for ";q=0[.[0[0[0]]]]" */
|
||||
while (*cursor == ' ') cursor++;
|
||||
if (*(cursor++) != ';') break;
|
||||
while (*cursor == ' ') cursor++;
|
||||
if (*(cursor++) != 'q') break;
|
||||
while (*cursor == ' ') cursor++;
|
||||
if (*(cursor++) != '=') break;
|
||||
while (*cursor == ' ') cursor++;
|
||||
if (*(cursor++) != '0') break;
|
||||
if (*(cursor++) != '.') return NGX_DECLINED; /* ;q=0, */
|
||||
digit = *(cursor++);
|
||||
if (digit < '0' || digit > '9') return NGX_DECLINED; /* ;q=0., */
|
||||
if (digit > '0') break;
|
||||
digit = *(cursor++);
|
||||
if (digit < '0' || digit > '9') return NGX_DECLINED; /* ;q=0.0, */
|
||||
if (digit > '0') break;
|
||||
digit = *(cursor++);
|
||||
if (digit < '0' || digit > '9') return NGX_DECLINED; /* ;q=0.00, */
|
||||
if (digit > '0') break;
|
||||
return NGX_DECLINED; /* ;q=0.000 */
|
||||
}
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* Test if this request is allowed to have the brotli response. */
|
||||
static ngx_int_t check_eligility(ngx_http_request_t* req) {
|
||||
if (req != req->main) return NGX_DECLINED;
|
||||
if (check_accept_encoding(req) != NGX_OK) return NGX_DECLINED;
|
||||
req->gzip_tested = 1;
|
||||
req->gzip_ok = 0;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
static ngx_int_t handler(ngx_http_request_t* req) {
|
||||
configuration_t* cfg;
|
||||
ngx_int_t rc;
|
||||
u_char* last;
|
||||
ngx_str_t path;
|
||||
size_t root;
|
||||
ngx_log_t* log;
|
||||
ngx_http_core_loc_conf_t* location_cfg;
|
||||
ngx_open_file_info_t file_info;
|
||||
ngx_table_elt_t* content_encoding_entry;
|
||||
ngx_buf_t* buf;
|
||||
ngx_chain_t out;
|
||||
|
||||
/* Only GET and HEAD requensts are supported. */
|
||||
if (!(req->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) return NGX_DECLINED;
|
||||
|
||||
/* Only files are supported. */
|
||||
if (req->uri.data[req->uri.len - 1] == '/') return NGX_DECLINED;
|
||||
|
||||
/* Get configuration and check if module is disabled. */
|
||||
cfg = ngx_http_get_module_loc_conf(req, ngx_http_brotli_static_module);
|
||||
if (cfg->enable == NGX_HTTP_BROTLI_STATIC_OFF) return NGX_DECLINED;
|
||||
|
||||
if (cfg->enable == NGX_HTTP_BROTLI_STATIC_ALWAYS) {
|
||||
/* Ignore request properties (e.g. Accept-Encoding). */
|
||||
} else {
|
||||
/* NGX_HTTP_BROTLI_STATIC_ON */
|
||||
rc = check_eligility(req);
|
||||
if (rc != NGX_OK) return NGX_DECLINED;
|
||||
}
|
||||
|
||||
/* Get path and append the suffix. */
|
||||
last = ngx_http_map_uri_to_path(req, &path, &root, kSuffixLen);
|
||||
if (last == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
/* +1 for reinstating the terminating 0. */
|
||||
ngx_cpystrn(last, kSuffix, kSuffixLen + 1);
|
||||
path.len += kSuffixLen;
|
||||
|
||||
log = req->connection->log;
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http filename: \"%s\"",
|
||||
path.data);
|
||||
|
||||
/* Prepare to read the file. */
|
||||
location_cfg = ngx_http_get_module_loc_conf(req, ngx_http_core_module);
|
||||
ngx_memzero(&file_info, sizeof(ngx_open_file_info_t));
|
||||
file_info.read_ahead = location_cfg->read_ahead;
|
||||
file_info.directio = location_cfg->directio;
|
||||
file_info.valid = location_cfg->open_file_cache_valid;
|
||||
file_info.min_uses = location_cfg->open_file_cache_min_uses;
|
||||
file_info.errors = location_cfg->open_file_cache_errors;
|
||||
file_info.events = location_cfg->open_file_cache_events;
|
||||
rc = ngx_http_set_disable_symlinks(req, location_cfg, &path, &file_info);
|
||||
if (rc != NGX_OK) return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
|
||||
/* Try to fetch file and process errors. */
|
||||
rc = ngx_open_cached_file(location_cfg->open_file_cache, &path, &file_info,
|
||||
req->pool);
|
||||
if (rc != NGX_OK) {
|
||||
ngx_uint_t level;
|
||||
switch (file_info.err) {
|
||||
case 0:
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
|
||||
case NGX_ENOENT:
|
||||
case NGX_ENOTDIR:
|
||||
case NGX_ENAMETOOLONG:
|
||||
return NGX_DECLINED;
|
||||
|
||||
#if (NGX_HAVE_OPENAT)
|
||||
case NGX_EMLINK:
|
||||
case NGX_ELOOP:
|
||||
#endif
|
||||
case NGX_EACCES:
|
||||
level = NGX_LOG_ERR;
|
||||
break;
|
||||
|
||||
default:
|
||||
level = NGX_LOG_CRIT;
|
||||
break;
|
||||
}
|
||||
ngx_log_error(level, log, file_info.err, "%s \"%s\" failed",
|
||||
file_info.failed, path.data);
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
if (cfg->enable == NGX_HTTP_BROTLI_STATIC_ON) {
|
||||
req->gzip_vary = 1;
|
||||
}
|
||||
|
||||
/* So far so good. */
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d",
|
||||
file_info.fd);
|
||||
|
||||
/* Only files are supported. */
|
||||
if (file_info.is_dir) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
#if !(NGX_WIN32)
|
||||
if (!file_info.is_file) {
|
||||
ngx_log_error(NGX_LOG_CRIT, log, 0, "\"%s\" is not a regular file",
|
||||
path.data);
|
||||
return NGX_HTTP_NOT_FOUND;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Prepare request push the body. */
|
||||
req->root_tested = !req->error_page;
|
||||
rc = ngx_http_discard_request_body(req);
|
||||
if (rc != NGX_OK) return rc;
|
||||
log->action = "sending response to client";
|
||||
req->headers_out.status = NGX_HTTP_OK;
|
||||
req->headers_out.content_length_n = file_info.size;
|
||||
req->headers_out.last_modified_time = file_info.mtime;
|
||||
rc = ngx_http_set_etag(req);
|
||||
if (rc != NGX_OK) return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
rc = ngx_http_set_content_type(req);
|
||||
if (rc != NGX_OK) return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
|
||||
/* Set "Content-Encoding" header. */
|
||||
content_encoding_entry = ngx_list_push(&req->headers_out.headers);
|
||||
if (content_encoding_entry == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
content_encoding_entry->hash = 1;
|
||||
ngx_str_set(&content_encoding_entry->key, kContentEncoding);
|
||||
ngx_str_set(&content_encoding_entry->value, kEncoding);
|
||||
req->headers_out.content_encoding = content_encoding_entry;
|
||||
|
||||
/* Setup response body. */
|
||||
buf = ngx_pcalloc(req->pool, sizeof(ngx_buf_t));
|
||||
if (buf == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
buf->file = ngx_pcalloc(req->pool, sizeof(ngx_file_t));
|
||||
if (buf->file == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
buf->file_pos = 0;
|
||||
buf->file_last = file_info.size;
|
||||
buf->in_file = buf->file_last ? 1 : 0;
|
||||
buf->last_buf = (req == req->main) ? 1 : 0;
|
||||
buf->last_in_chain = 1;
|
||||
buf->file->fd = file_info.fd;
|
||||
buf->file->name = path;
|
||||
buf->file->log = log;
|
||||
buf->file->directio = file_info.is_directio;
|
||||
out.buf = buf;
|
||||
out.next = NULL;
|
||||
|
||||
/* Push the response header. */
|
||||
rc = ngx_http_send_header(req);
|
||||
if (rc == NGX_ERROR || rc > NGX_OK || req->header_only) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Push the response body. */
|
||||
return ngx_http_output_filter(req, &out);
|
||||
}
|
||||
|
||||
static void* create_conf(ngx_conf_t* root_cfg) {
|
||||
configuration_t* cfg;
|
||||
cfg = ngx_palloc(root_cfg->pool, sizeof(configuration_t));
|
||||
if (cfg == NULL) return NULL;
|
||||
cfg->enable = NGX_CONF_UNSET_UINT;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static char* merge_conf(ngx_conf_t* root_cfg, void* parent, void* child) {
|
||||
configuration_t* prev = parent;
|
||||
configuration_t* cfg = child;
|
||||
ngx_conf_merge_uint_value(cfg->enable, prev->enable,
|
||||
NGX_HTTP_BROTLI_STATIC_OFF);
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
static ngx_int_t init(ngx_conf_t* root_cfg) {
|
||||
ngx_http_core_main_conf_t* core_cfg;
|
||||
ngx_http_handler_pt* handler_slot;
|
||||
core_cfg = ngx_http_conf_get_module_main_conf(root_cfg, ngx_http_core_module);
|
||||
handler_slot =
|
||||
ngx_array_push(&core_cfg->phases[NGX_HTTP_CONTENT_PHASE].handlers);
|
||||
if (handler_slot == NULL) return NGX_ERROR;
|
||||
*handler_slot = handler;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
# astylerc
|
||||
align-pointer=name
|
||||
align-reference=name
|
||||
break-after-logical
|
||||
#indent=spaces=2
|
||||
max-code-length=120
|
||||
style=google
|
||||
suffix=none
|
||||
|
||||
# Indent
|
||||
indent-preproc-block
|
||||
|
||||
# Padding
|
||||
pad-header
|
||||
unpad-paren
|
||||
|
||||
# Formatting:
|
||||
add-brackets
|
||||
#convert-tabs
|
||||
|
||||
# Output:
|
||||
formatted
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Search in the script folder
|
||||
pushd "$(dirname $0)" >/dev/null
|
||||
CWD="$(pwd -P)"
|
||||
popd >/dev/null
|
||||
FILES='ngx_cache_purge_module.c'
|
||||
|
||||
# The file format in accordance with the style defined in .astylerc
|
||||
astyle -v --options='.astylerc' ${FILES} || (echo 'astyle failed'; exit 1);
|
||||
|
||||
# To correct this, the issuance dos2unix on each file
|
||||
# sometimes adds in Windows as a string-endins (\r\n).
|
||||
dos2unix --quiet ${FILES} || (echo 'dos2unix failed'; exit 2);
|
||||
|
|
@ -1 +0,0 @@
|
|||
*.t linguist-language=Text
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
sudo: required
|
||||
os: linux
|
||||
dist: trusty
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
cache:
|
||||
apt: true
|
||||
directories:
|
||||
- download-cache
|
||||
env:
|
||||
global:
|
||||
- JOBS=4
|
||||
- NGINX_PREFIX=/opt/nginx
|
||||
matrix:
|
||||
- NGINX_VERSION=1.18.0
|
||||
- NGINX_VERSION=1.19.2
|
||||
|
||||
before_install:
|
||||
- mkdir --parents download-cache
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq zlib1g-dev libpcre3-dev cpanminus
|
||||
# Get OpenSSL 1.0.2 from Ubuntu Xenial
|
||||
# https://packages.ubuntu.com/xenial-updates/libssl1.0.0
|
||||
- test -f download-cache/libssl1.0.0_1.0.2g-1ubuntu4.16_amd64.deb || wget -O download-cache/libssl1.0.0_1.0.2g-1ubuntu4.17_amd64.deb "http://de.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.0.0_1.0.2g-1ubuntu4.17_amd64.deb"
|
||||
# https://packages.ubuntu.com/xenial/libssl-dev
|
||||
- test -f download-cache/libssl-dev_1.0.2g-1ubuntu4.16_amd64.deb || wget -O download-cache/libssl-dev_1.0.2g-1ubuntu4.17_amd64.deb "http://de.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl-dev_1.0.2g-1ubuntu4.17_amd64.deb"
|
||||
- sudo dpkg -i download-cache/libssl*_amd64.deb
|
||||
# Test::Nginx
|
||||
- git clone https://github.com/openresty/test-nginx.git test-nginx
|
||||
- cd test-nginx/ && sudo cpanm . && cd ..
|
||||
# NGINX source
|
||||
- test -f download-cache/nginx-$NGINX_VERSION.tar.gz || wget -O download-cache/nginx-$NGINX_VERSION.tar.gz http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz
|
||||
|
||||
install:
|
||||
- tar -xzf download-cache/nginx-${NGINX_VERSION}.tar.gz
|
||||
- cd nginx-${NGINX_VERSION}/
|
||||
- ./configure --prefix=${NGINX_PREFIX} --with-debug --with-http_ssl_module --add-module=${PWD}/..
|
||||
- make -j${JOBS}
|
||||
- sudo make install
|
||||
- cd ..
|
||||
- export PATH="${NGINX_PREFIX}/sbin:$PATH"
|
||||
# - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}
|
||||
|
||||
script:
|
||||
- nginx -V
|
||||
- ldd $(which nginx)
|
||||
- prove t
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
2020-06-27 VERSION 2.5.1
|
||||
* fix: empty key check - it coredumps when cache key is empty, Tuğrul Topuz
|
||||
* fix: purge report calloc fix - Report template has not cache file path but it's length is use in buffer memory allocation, Tuğrul Topuz
|
||||
|
||||
2018-08-04 VERSION 2.5
|
||||
* feat/docs: cache_purge_response_type directive, selecting response type (html|json|xml|text)
|
||||
* break: changed status of HTTP code 404 (Not Found) to 412 (Precondition Failed)
|
||||
* fix: remove path information of response body (#4, 3a8c08a, #11)
|
||||
|
||||
2020-06-27 VERSION 2.4.3
|
||||
* fix: empty key check - it coredumps when cache key is empty, Tuğrul Topuz
|
||||
|
||||
2017-09-28 VERSION 2.4.2
|
||||
* fix: segfault in call to `ngx_read_file` of partial key purge, Frankie Dintino
|
||||
* fix: segfault in `cplcf->conf->purge_all` with separate location syntax, Frankie Dintino
|
||||
|
||||
2017-02-21 VERSION 2.4.1
|
||||
* Fix compatibility with nginx-1.11.6+, Sułowicz Paweł
|
||||
|
||||
2016-11-20 VERSION 2.4
|
||||
* Fix compatibility with nginx-1.7.12+.
|
||||
* explain the purge logic
|
||||
* feat(purge all): Include option to purge all the cached files
|
||||
This option can be slow if a lot of content is cached, or if the
|
||||
storage used for the cache is slow. But you really should be using
|
||||
RAM as your cache storage.
|
||||
* feat(partial keys): Support partial keys to purge multiple keys.
|
||||
Put an '*' at the end of your purge cache URL.
|
||||
e.g:
|
||||
proxy_cache_key $scheme$host$uri$is_args$args$cookie_JSESSIONID;
|
||||
curl -X PURGE https://example.com/pass*
|
||||
This will remove every cached page whose key cache starting with:
|
||||
httpsexample.com/pass*
|
||||
Be careful not passing any value for the values after the $uri, or put
|
||||
it at the end of your cache key.
|
||||
* Convert a config file to build a dynamic module
|
||||
|
||||
2014-12-23 VERSION 2.3
|
||||
* Fix compatibility with nginx-1.7.9+.
|
||||
|
||||
2014-12-02 VERSION 2.2
|
||||
* Fix compatibility with nginx-1.7.8+.
|
||||
|
||||
2014-05-19
|
||||
* Fix build on Solaris with SunCC (Solaris Studio).
|
||||
Reported by Jussi Sallinen.
|
||||
|
||||
2013-03-19 VERSION 2.1
|
||||
* When enabled, cache purge will now catch all requests with
|
||||
PURGE (or specified) method, even if cache isn't configured.
|
||||
Previously, it would pass such requests to the upstream.
|
||||
|
||||
2012-12-07 VERSION 2.0
|
||||
* Add alternative "same location" syntax.
|
||||
From CloudFlare.
|
||||
|
||||
2012-07-02 VERSION 1.6
|
||||
* Fix compatibility with nginx-1.3.2+.
|
||||
Reported by MagicBear, patch from Ruslan Ermilov.
|
||||
|
||||
2011-12-20 VERSION 1.5
|
||||
* Fix on-disk cache size calculation.
|
||||
Since the initial release, recorded on-disk cache size was
|
||||
decreased twice for purged content (once during cache purge
|
||||
and once during subsequent cache update).
|
||||
This resulted in recorded on-disk cache size being much
|
||||
smaller than in reality, which could lead to on-disk cache
|
||||
outgrowing defined "max_size" parameter.
|
||||
Patch from Pyry Hakulinen.
|
||||
|
||||
2011-10-05 VERSION 1.4
|
||||
* Add AIO support.
|
||||
Requested by Emin Hasanov.
|
||||
|
||||
2011-05-03 VERSION 1.3
|
||||
* Fix compatibility with nginx-1.0.1.
|
||||
Reported by Sergey A. Osokin and Markus Linnala.
|
||||
|
||||
2010-08-29
|
||||
* Fix compatibility with nginx-0.8.0 and versions older than
|
||||
nginx-0.7.60.
|
||||
|
||||
2010-08-11 VERSION 1.2
|
||||
* Fix various build scenarios with disabled upstream modules.
|
||||
Reported by Johan Bergstroem.
|
||||
|
||||
* Add ability to purge content from SCGI's cache.
|
||||
Requested by Johan Bergstroem.
|
||||
|
||||
2010-06-08 VERSION 1.1
|
||||
* Fix compatibility with nginx-0.8.40+.
|
||||
|
||||
* Add ability to purge content from uWSGI's cache.
|
||||
|
||||
2010-01-10 VERSION 1.0
|
||||
* Initial module release.
|
||||
|
||||
2009-11-17
|
||||
* Fix patch compatibility with nginx-0.8.11+.
|
||||
Reported by Bing Ran.
|
||||
|
||||
2009-08-11
|
||||
* Initial patch release.
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
Copyright (c) 2009-2014, FRiCKLE <info@frickle.com>
|
||||
Copyright (c) 2009-2014, Piotr Sikora <piotr.sikora@frickle.com>
|
||||
All rights reserved.
|
||||
|
||||
This project was fully funded by yo.se.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -1,283 +0,0 @@
|
|||
About
|
||||
=====
|
||||
`ngx_cache_purge` is `nginx` module which adds ability to purge content from
|
||||
`FastCGI`, `proxy`, `SCGI` and `uWSGI` caches. A purge operation removes the
|
||||
content with the same cache key as the purge request has.
|
||||
|
||||
|
||||
Sponsors
|
||||
========
|
||||
Work on the original patch was fully funded by [yo.se](http://yo.se).
|
||||
|
||||
|
||||
Status
|
||||
======
|
||||
This module is production-ready.
|
||||
|
||||
|
||||
Configuration directives (same location syntax)
|
||||
===============================================
|
||||
fastcgi_cache_purge
|
||||
-------------------
|
||||
* **syntax**: `fastcgi_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]`
|
||||
* **default**: `none`
|
||||
* **context**: `http`, `server`, `location`
|
||||
|
||||
Allow purging of selected pages from `FastCGI`'s cache.
|
||||
|
||||
|
||||
proxy_cache_purge
|
||||
-----------------
|
||||
* **syntax**: `proxy_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]`
|
||||
* **default**: `none`
|
||||
* **context**: `http`, `server`, `location`
|
||||
|
||||
Allow purging of selected pages from `proxy`'s cache.
|
||||
|
||||
|
||||
scgi_cache_purge
|
||||
----------------
|
||||
* **syntax**: `scgi_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]`
|
||||
* **default**: `none`
|
||||
* **context**: `http`, `server`, `location`
|
||||
|
||||
Allow purging of selected pages from `SCGI`'s cache.
|
||||
|
||||
|
||||
uwsgi_cache_purge
|
||||
-----------------
|
||||
* **syntax**: `uwsgi_cache_purge on|off|<method> [purge_all] [from all|<ip> [.. <ip>]]`
|
||||
* **default**: `none`
|
||||
* **context**: `http`, `server`, `location`
|
||||
|
||||
Allow purging of selected pages from `uWSGI`'s cache.
|
||||
|
||||
|
||||
Configuration directives (separate location syntax)
|
||||
===================================================
|
||||
fastcgi_cache_purge
|
||||
-------------------
|
||||
* **syntax**: `fastcgi_cache_purge zone_name key`
|
||||
* **default**: `none`
|
||||
* **context**: `location`
|
||||
|
||||
Sets area and key used for purging selected pages from `FastCGI`'s cache.
|
||||
|
||||
|
||||
proxy_cache_purge
|
||||
-----------------
|
||||
* **syntax**: `proxy_cache_purge zone_name key`
|
||||
* **default**: `none`
|
||||
* **context**: `location`
|
||||
|
||||
Sets area and key used for purging selected pages from `proxy`'s cache.
|
||||
|
||||
|
||||
scgi_cache_purge
|
||||
----------------
|
||||
* **syntax**: `scgi_cache_purge zone_name key`
|
||||
* **default**: `none`
|
||||
* **context**: `location`
|
||||
|
||||
Sets area and key used for purging selected pages from `SCGI`'s cache.
|
||||
|
||||
|
||||
uwsgi_cache_purge
|
||||
-----------------
|
||||
* **syntax**: `uwsgi_cache_purge zone_name key`
|
||||
* **default**: `none`
|
||||
* **context**: `location`
|
||||
|
||||
Sets area and key used for purging selected pages from `uWSGI`'s cache.
|
||||
|
||||
Configuration directives (Optional)
|
||||
===================================================
|
||||
|
||||
cache_purge_response_type
|
||||
-----------------
|
||||
* **syntax**: `cache_purge_response_type html|json|xml|text`
|
||||
* **default**: `html`
|
||||
* **context**: `http`, `server`, `location`
|
||||
|
||||
Sets a response type of purging result.
|
||||
|
||||
|
||||
|
||||
Partial Keys
|
||||
============
|
||||
Sometimes it's not possible to pass the exact key cache to purge a page. For example; when the content of a cookie or the params are part of the key.
|
||||
You can specify a partial key adding an asterisk at the end of the URL.
|
||||
|
||||
curl -X PURGE /page*
|
||||
|
||||
The asterisk must be the last character of the key, so you **must** put the $uri variable at the end.
|
||||
|
||||
|
||||
|
||||
Sample configuration (same location syntax)
|
||||
===========================================
|
||||
http {
|
||||
proxy_cache_path /tmp/cache keys_zone=tmpcache:10m;
|
||||
|
||||
server {
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$uri$is_args$args";
|
||||
proxy_cache_purge PURGE from 127.0.0.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Sample configuration (same location syntax - purge all cached files)
|
||||
====================================================================
|
||||
http {
|
||||
proxy_cache_path /tmp/cache keys_zone=tmpcache:10m;
|
||||
|
||||
server {
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$uri$is_args$args";
|
||||
proxy_cache_purge PURGE purge_all from 127.0.0.1 192.168.0.0/8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Sample configuration (separate location syntax)
|
||||
===============================================
|
||||
http {
|
||||
proxy_cache_path /tmp/cache keys_zone=tmpcache:10m;
|
||||
|
||||
server {
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$uri$is_args$args";
|
||||
}
|
||||
|
||||
location ~ /purge(/.*) {
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$1$is_args$args";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sample configuration (Optional)
|
||||
===============================================
|
||||
http {
|
||||
proxy_cache_path /tmp/cache keys_zone=tmpcache:10m;
|
||||
|
||||
cache_purge_response_type text;
|
||||
|
||||
server {
|
||||
|
||||
cache_purge_response_type json;
|
||||
|
||||
location / { #json
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$uri$is_args$args";
|
||||
}
|
||||
|
||||
location ~ /purge(/.*) { #xml
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$1$is_args$args";
|
||||
cache_purge_response_type xml;
|
||||
}
|
||||
|
||||
location ~ /purge2(/.*) { # json
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$1$is_args$args";
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
|
||||
location / { #text
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$uri$is_args$args";
|
||||
}
|
||||
|
||||
location ~ /purge(/.*) { #text
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$1$is_args$args";
|
||||
}
|
||||
|
||||
location ~ /purge2(/.*) { #html
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
proxy_cache tmpcache;
|
||||
proxy_cache_key "$1$is_args$args";
|
||||
cache_purge_response_type html;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Solve problems
|
||||
==============
|
||||
* Enabling [`gzip_vary`](https://nginx.org/r/gzip_vary) can lead to different results when clearing, when enabling it, you may have problems clearing the cache. For reliable operation, you can disable [`gzip_vary`](https://nginx.org/r/gzip_vary) inside the location [#20](https://github.com/nginx-modules/ngx_cache_purge/issues/20).
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
`ngx_cache_purge` comes with complete test suite based on [Test::Nginx](http://github.com/agentzh/test-nginx).
|
||||
|
||||
You can test it by running:
|
||||
|
||||
`$ prove`
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
Copyright (c) 2009-2014, FRiCKLE <info@frickle.com>
|
||||
Copyright (c) 2009-2014, Piotr Sikora <piotr.sikora@frickle.com>
|
||||
All rights reserved.
|
||||
|
||||
This project was fully funded by yo.se.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
See also
|
||||
========
|
||||
- [ngx_slowfs_cache](http://github.com/FRiCKLE/ngx_slowfs_cache).
|
||||
- http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#purger
|
||||
- http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache_purge
|
||||
- https://github.com/wandenberg/nginx-selective-cache-purge-module
|
||||
- https://github.com/wandenberg/nginx-sorted-querystring-module
|
||||
- https://github.com/ledgetech/ledge
|
||||
- [Faking Surrogate Cache-Keys for Nginx Plus](https://www.innoq.com/en/blog/faking-surrogate-cache-keys-for-nginx-plus/) ([gist](https://gist.github.com/titpetric/2f142e89eaa0f36ba4e4383b16d61474))
|
||||
- [Delete NGINX cached md5 items with a PURGE with wildcard support](https://gist.github.com/nosun/0cfb58d3164f829e2f027fd37b338ede)
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
if [ "$HTTP_PROXY" = "YES" ]; then
|
||||
have=NGX_HTTP_PROXY . auto/have
|
||||
fi
|
||||
|
||||
if [ "$HTTP_FASTCGI" = "YES" ]; then
|
||||
have=NGX_HTTP_FASTCGI . auto/have
|
||||
fi
|
||||
|
||||
if [ "$HTTP_SCGI" = "YES" ]; then
|
||||
have=NGX_HTTP_SCGI . auto/have
|
||||
fi
|
||||
|
||||
if [ "$HTTP_UWSGI" = "YES" ]; then
|
||||
have=NGX_HTTP_UWSGI . auto/have
|
||||
fi
|
||||
|
||||
ngx_addon_name=ngx_http_cache_purge_module
|
||||
CACHE_PURGE_SRCS="$ngx_addon_dir/ngx_cache_purge_module.c"
|
||||
|
||||
if [ -n "$ngx_module_link" ]; then
|
||||
ngx_module_type=HTTP
|
||||
ngx_module_name="$ngx_addon_name"
|
||||
ngx_module_srcs="$CACHE_PURGE_SRCS"
|
||||
|
||||
. auto/module
|
||||
else
|
||||
HTTP_MODULES="$HTTP_MODULES $ngx_addon_name"
|
||||
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $CACHE_PURGE_SRCS"
|
||||
fi
|
||||
|
||||
have=NGX_CACHE_PURGE_MODULE . auto/have
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
libnginx-mod-http-cache-purge (1:2.5.3-3) unstable; urgency=medium
|
||||
|
||||
* d/control: update my email to janmojzis@debian.org
|
||||
* d/copyright: update my email to janmojzis@debian.org
|
||||
* d/control: bump Standards-Version: 4.7.2, no changes
|
||||
* d/copyright: bump debian/* copyright year
|
||||
* d/watch: use more generic template
|
||||
|
||||
-- Jan Mojžíš <janmojzis@debian.org> Fri, 11 Apr 2025 14:26:56 +0200
|
||||
|
||||
libnginx-mod-http-cache-purge (1:2.5.3-2) unstable; urgency=medium
|
||||
|
||||
* d/changelog fix closed bug number 1019003 -> 1055742 (Closes: 1055742)
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Fri, 21 Jun 2024 19:34:05 +0200
|
||||
|
||||
libnginx-mod-http-cache-purge (1:2.5.3-1) unstable; urgency=medium
|
||||
|
||||
* switch to a new upstream
|
||||
https://github.com/nginx-modules/ngx_cache_purge
|
||||
(Closes: 1072836) (Closes: 1055742)
|
||||
* d/p/dynamic-module.patch remove, fixed in upstream
|
||||
* d/p/segfault-1.11.6.patch remove, fixed in upstream
|
||||
* d/t/purgetest added
|
||||
* d/copyright: bump my copyright year
|
||||
* d/gbp.conf: add [pull] track-missing = True
|
||||
* d/control: bump Standards-Version: 4.7.0, no changes
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Fri, 21 Jun 2024 13:36:53 +0200
|
||||
|
||||
libnginx-mod-http-cache-purge (1:2.3-6) unstable; urgency=medium
|
||||
|
||||
* d/control: remove Build-Depends nginx-abi-1.24.0-1
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Sat, 07 Oct 2023 15:31:25 +0200
|
||||
|
||||
libnginx-mod-http-cache-purge (1:2.3-5) unstable; urgency=medium
|
||||
|
||||
* NEW ABI: rebuild with nginx-abi-1.24.0-1
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Tue, 27 Jun 2023 23:16:35 +0200
|
||||
|
||||
libnginx-mod-http-cache-purge (1:2.3-4) unstable; urgency=medium
|
||||
|
||||
* d/t/generic rework. The test now checks module after
|
||||
installation/reload/restart.
|
||||
* d/control: bump Standards-Version: 4.6.2, no changes
|
||||
* d/gbb.conf: switched to debian branch main (debian-branch = main)
|
||||
* d/copyright: bump my copyright year
|
||||
* d/copyright: reformat text to be compatible with 'cme update dpkg-copyright'
|
||||
* NEW ABI: rebuild with nginx-abi-1.22.1-7
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Mon, 13 Feb 2023 12:56:14 +0100
|
||||
|
||||
libnginx-mod-http-cache-purge (1:2.3-3) unstable; urgency=medium
|
||||
|
||||
* d/copyright: fixed typo (empty line ngx_cache_purge_module.c)
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Fri, 09 Dec 2022 14:50:48 +0100
|
||||
|
||||
libnginx-mod-http-cache-purge (1:2.3-2) experimental; urgency=medium
|
||||
|
||||
* d/control: added Multi-Arch: foreign
|
||||
* d/copyright: add Igor Sysoev + Nginx, Inc.
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Mon, 05 Dec 2022 21:15:13 +0100
|
||||
|
||||
libnginx-mod-http-cache-purge (1:2.3-1) experimental; urgency=medium
|
||||
|
||||
* Initial release. (Closes: 1024213)
|
||||
* Additional info: The separate package libnginx-mod-http-cache-purge ships
|
||||
newest version of ngx_cache_purge (Closes: 911099)
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Wed, 30 Nov 2022 14:46:45 +0100
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
Source: libnginx-mod-http-cache-purge
|
||||
Section: httpd
|
||||
Priority: optional
|
||||
Maintainer: Debian Nginx Maintainers <pkg-nginx-maintainers@alioth-lists.debian.net>
|
||||
Uploaders: Jan Mojžíš <janmojzis@debian.org>,
|
||||
Build-Depends: debhelper-compat (= 13),
|
||||
dh-sequence-nginx,
|
||||
Standards-Version: 4.7.2
|
||||
Homepage: https://github.com/FRiCKLE/ngx_cache_purge
|
||||
Vcs-Git: https://salsa.debian.org/nginx-team/libnginx-mod-http-cache-purge.git
|
||||
Vcs-Browser: https://salsa.debian.org/nginx-team/libnginx-mod-http-cache-purge
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: libnginx-mod-http-cache-purge
|
||||
Architecture: any
|
||||
Multi-Arch: foreign
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
Recommends: nginx,
|
||||
Description: Purge content from Nginx caches
|
||||
Cache Purge module adds purging capabilities to Nginx. It allows purging
|
||||
content from caches used by all of Nginx proxy modules, like FastCGI, Proxy,
|
||||
SCGI and uWSGI.
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: ngx_cache_purge
|
||||
Upstream-Contact: FRiCKLE <info@frickle.com>
|
||||
Source: https://github.com/FRiCKLE/ngx_cache_purge
|
||||
|
||||
Files: *
|
||||
Copyright: 2009-2014, Piotr Sikora <piotr.sikora@frickle.com>
|
||||
2009-2014, FRiCKLE <info@frickle.com>
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2022, Miao Wang <shankerwangmiao@gmail.com>
|
||||
2022-2025, Jan Mojzis <janmojzis@debian.org>
|
||||
License: BSD-2-clause
|
||||
|
||||
License: BSD-2-clause
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
[DEFAULT]
|
||||
debian-branch = main
|
||||
upstream-branch = upstream
|
||||
upstream-tag = upstream/%(version)s
|
||||
pristine-tar = True
|
||||
sign-tags = True
|
||||
|
||||
[import-orig]
|
||||
merge-mode = replace
|
||||
|
||||
[pull]
|
||||
track-missing = True
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
|
@ -1 +0,0 @@
|
|||
3.0 (quilt)
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
Tests: generic
|
||||
Restrictions: allow-stderr isolation-container needs-root
|
||||
Depends: curl,
|
||||
nginx,
|
||||
nginx-core,
|
||||
@,
|
||||
|
||||
Tests: purgetest
|
||||
Restrictions: allow-stderr isolation-container needs-root
|
||||
Depends: curl,
|
||||
nginx,
|
||||
nginx-core,
|
||||
@,
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#!/bin/sh
|
||||
# version 20221215
|
||||
|
||||
# generic test that only verifies that nginx is running with the given
|
||||
# libnginx-... module
|
||||
# - after installation
|
||||
# - after nginx reload
|
||||
# - after nginx restart
|
||||
|
||||
EX=0
|
||||
CURL_CMD="curl --max-time 60 --silent --fail -o /dev/null"
|
||||
|
||||
#change directory to $AUTOPKGTEST_TMP
|
||||
cd "${AUTOPKGTEST_TMP}"
|
||||
|
||||
echo -n "curl after installation: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
echo -n "nginx reload ... "
|
||||
if invoke-rc.d nginx reload; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
sleep 5
|
||||
|
||||
|
||||
echo -n "curl after reload: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
echo -n "nginx restart ... "
|
||||
if invoke-rc.d nginx restart; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
sleep 5
|
||||
|
||||
echo -n "curl after restart: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
if [ ${EX} -ne 0 ]; then
|
||||
echo "=== journalctl ==="
|
||||
journalctl -n all -xu nginx.service || :
|
||||
|
||||
echo "=== error.log ==="
|
||||
if [ `wc -l /var/log/nginx/error.log | cut -d ' ' -f1` -gt 100 ]; then
|
||||
head -n 50 /var/log/nginx/error.log
|
||||
echo '...'
|
||||
tail -n 50 /var/log/nginx/error.log
|
||||
else
|
||||
cat /var/log/nginx/error.log
|
||||
fi
|
||||
fi
|
||||
|
||||
exit ${EX}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cat <<EOF > "/etc/nginx/sites-enabled/default"
|
||||
proxy_cache_path /tmp/ngx_cache_purge_cache keys_zone=test_cache:10m;
|
||||
proxy_temp_path /tmp/ngx_cache_purge_temp 1 2;
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:80 default_server;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass \$scheme://127.0.0.1:\$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key \$uri\$is_args\$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status \$upstream_cache_status;
|
||||
}
|
||||
|
||||
location ~ /purge(/.*) {
|
||||
proxy_cache_purge test_cache \$1\$is_args\$args;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
nginx -t
|
||||
invoke-rc.d nginx restart || { journalctl -n all -xu nginx.service; exit 1; }
|
||||
|
||||
curl --fail -s -o /dev/null -w "GET key: %{http_code}\n" http://127.0.0.1/proxy/passwd
|
||||
curl --fail -s -o /dev/null -w "PURGE existing key: %{http_code}\n" -X PURGE http://127.0.0.1/purge/proxy/passwd
|
||||
curl -s -o /dev/null -w "PURGE non-existing key: %{http_code}\n" -X PURGE http://127.0.0.1/purge/proxy/passwd
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
Bug-Database: https://github.com/FRiCKLE/ngx_cache_purge/issues
|
||||
Bug-Submit: https://github.com/FRiCKLE/ngx_cache_purge/issues/new
|
||||
Repository-Browse: https://github.com/FRiCKLE/ngx_cache_purge
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
version=4
|
||||
opts="\
|
||||
uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha|a|b)\d*)$/$1~$2/,\
|
||||
" \
|
||||
https://github.com/nginx-modules/ngx_cache_purge/tags \
|
||||
(?:.*?/)?v?@ANY_VERSION@@ARCHIVE_EXT@
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,136 +0,0 @@
|
|||
# vi:filetype=perl
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
repeat_each(1);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4 + 3 * 1);
|
||||
|
||||
our $http_config = <<'_EOC_';
|
||||
proxy_cache_path /tmp/ngx_cache_purge_cache keys_zone=test_cache:10m;
|
||||
proxy_temp_path /tmp/ngx_cache_purge_temp 1 2;
|
||||
_EOC_
|
||||
|
||||
our $config = <<'_EOC_';
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location ~ /purge(/.*) {
|
||||
proxy_cache_purge test_cache $1$is_args$args;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
worker_connections(128);
|
||||
no_shuffle();
|
||||
run_tests();
|
||||
|
||||
no_diff();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: prepare
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 2: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 3: purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge/proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 4: purge from empty cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge/proxy/passwd
|
||||
--- error_code: 412
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 412 Precondition Failed
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 5: get from source
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 6: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
# vi:filetype=perl
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
repeat_each(1);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4 + 3 * 1);
|
||||
|
||||
our $http_config = <<'_EOC_';
|
||||
proxy_cache_path /tmp/ngx_cache_purge_cache keys_zone=test_cache:10m;
|
||||
proxy_temp_path /tmp/ngx_cache_purge_temp 1 2;
|
||||
_EOC_
|
||||
|
||||
our $config = <<'_EOC_';
|
||||
set $cache test_cache;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache $cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location ~ /purge(/.*) {
|
||||
proxy_cache_purge $cache $1$is_args$args;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
worker_connections(128);
|
||||
no_shuffle();
|
||||
run_tests();
|
||||
|
||||
no_diff();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: prepare
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 2: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 3: purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge/proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 4: purge from empty cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge/proxy/passwd
|
||||
--- error_code: 412
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 412 Precondition Failed
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 5: get from source
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 6: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
|
@ -1,349 +0,0 @@
|
|||
# vi:filetype=perl
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
repeat_each(1);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4 + 6 * 1);
|
||||
|
||||
our $http_config = <<'_EOC_';
|
||||
proxy_cache_path /tmp/ngx_cache_purge_cache keys_zone=test_cache:10m;
|
||||
proxy_temp_path /tmp/ngx_cache_purge_temp 1 2;
|
||||
_EOC_
|
||||
|
||||
our $config = <<'_EOC_';
|
||||
proxy_cache_purge on;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
if ($uri) { }
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
our $config_allowed = <<'_EOC_';
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8 127.0.0.0/8 3.0.0.0/8;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
our $config_forbidden = <<'_EOC_';
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
worker_connections(128);
|
||||
no_shuffle();
|
||||
run_tests();
|
||||
|
||||
no_diff();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: prepare
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 2: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 3: purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 4: purge from empty cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 412
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 412 Precondition Failed
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 5: get from source
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 6: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 7: purge from cache (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_allowed
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 8: purge from empty cache (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_allowed
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 412
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 412 Precondition Failed
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 9: get from source (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_allowed
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 10: get from cache (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_allowed
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 11: purge from cache (PURGE not allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_forbidden
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 403
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 403 Forbidden
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 12: get from cache (PURGE not allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_forbidden
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 13: no cache (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8 127.0.0.0/8 3.0.0.0/8;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 404
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 404 Not Found
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 14: no cache (PURGE not allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 403
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 403 Forbidden
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 15: multiple cache purge directives
|
||||
--- http_config eval: $::http_config
|
||||
--- config
|
||||
fastcgi_cache_purge on;
|
||||
proxy_cache_purge on;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
if ($uri) { }
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
|
@ -1,353 +0,0 @@
|
|||
# vi:filetype=perl
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
repeat_each(1);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4 + 6 * 1);
|
||||
|
||||
our $http_config = <<'_EOC_';
|
||||
proxy_cache_path /tmp/ngx_cache_purge_cache keys_zone=test_cache:10m;
|
||||
proxy_temp_path /tmp/ngx_cache_purge_temp 1 2;
|
||||
_EOC_
|
||||
|
||||
our $config = <<'_EOC_';
|
||||
proxy_cache_purge on;
|
||||
set $cache test_cache;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache $cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
if ($uri) { }
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
our $config_allowed = <<'_EOC_';
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8 127.0.0.0/8 3.0.0.0/8;
|
||||
set $cache test_cache;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache $cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
our $config_forbidden = <<'_EOC_';
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8;
|
||||
set $cache test_cache;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache $cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
worker_connections(128);
|
||||
no_shuffle();
|
||||
run_tests();
|
||||
|
||||
no_diff();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: prepare
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 2: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 3: purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 4: purge from empty cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 412
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 412 Precondition Failed
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 5: get from source
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 6: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 7: purge from cache (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_allowed
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 8: purge from empty cache (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_allowed
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 412
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 412 Precondition Failed
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 9: get from source (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_allowed
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 10: get from cache (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_allowed
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 11: purge from cache (PURGE not allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_forbidden
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 403
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 403 Forbidden
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 12: get from cache (PURGE not allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config_forbidden
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 5: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 13: no cache (PURGE allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8 127.0.0.0/8 3.0.0.0/8;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 404
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 404 Not Found
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 14: no cache (PURGE not allowed)
|
||||
--- http_config eval: $::http_config
|
||||
--- config
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 403
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 403 Forbidden
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
||||
|
||||
|
||||
=== TEST 15: multiple cache purge directives
|
||||
--- http_config eval: $::http_config
|
||||
--- config
|
||||
fastcgi_cache_purge on;
|
||||
proxy_cache_purge on;
|
||||
set $cache test_cache;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache $cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
if ($uri) { }
|
||||
}
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
--- request
|
||||
PURGE /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx: 4: < 1.7.9
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
# vi:filetype=perl
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
repeat_each(1);
|
||||
|
||||
plan tests => 32;
|
||||
|
||||
our $http_config = <<'_EOC_';
|
||||
proxy_cache_path /tmp/ngx_cache_purge_cache keys_zone=test_cache:10m;
|
||||
proxy_temp_path /tmp/ngx_cache_purge_temp 1 2;
|
||||
_EOC_
|
||||
|
||||
our $config = <<'_EOC_';
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
proxy_cache_purge PURGE purge_all from 1.0.0.0/8 127.0.0.0/8 3.0.0.0/8;
|
||||
}
|
||||
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
worker_connections(128);
|
||||
no_shuffle();
|
||||
run_tests();
|
||||
|
||||
no_diff();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: prepare passwd
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 2: prepare shadow
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/shadow
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
|
||||
=== TEST 3: get from cache passwd
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 4: get from cache shadow
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/shadow
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 5: purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /proxy/any
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 6: get from empty cache passwd
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 7: get from empty cache shadow
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/shadow
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
# vi:filetype=perl
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
repeat_each(1);
|
||||
|
||||
plan tests => 41;
|
||||
|
||||
our $http_config = <<'_EOC_';
|
||||
proxy_cache_path /tmp/ngx_cache_purge_cache keys_zone=test_cache:10m;
|
||||
proxy_temp_path /tmp/ngx_cache_purge_temp 1 2;
|
||||
_EOC_
|
||||
|
||||
our $config = <<'_EOC_';
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
|
||||
proxy_cache_purge PURGE from 1.0.0.0/8 127.0.0.0/8 3.0.0.0/8;
|
||||
}
|
||||
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
worker_connections(128);
|
||||
no_shuffle();
|
||||
run_tests();
|
||||
|
||||
no_diff();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: prepare passwd
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 2: prepare passwd2
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd2
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 3: prepare shadow
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/shadow
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 4: get from cache passwd
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 5: get from cache passwd2
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd2
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 6: purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /proxy/pass*
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 7: get from empty cache passwd
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 8: get from empty cache passwd2
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd2
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
||||
|
||||
=== TEST 9: get from cache shadow
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/shadow
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
|
|
@ -1,245 +0,0 @@
|
|||
# vi:filetype=perl
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx::Socket;
|
||||
|
||||
repeat_each(1);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4 + 3 * 1);
|
||||
|
||||
our $http_config = <<'_EOC_';
|
||||
proxy_cache_path /tmp/ngx_cache_purge_cache keys_zone=test_cache:10m;
|
||||
proxy_temp_path /tmp/ngx_cache_purge_temp 1 2;
|
||||
_EOC_
|
||||
|
||||
our $config = <<'_EOC_';
|
||||
|
||||
cache_purge_response_type json;
|
||||
|
||||
location /proxy {
|
||||
proxy_pass $scheme://127.0.0.1:$server_port/etc/passwd;
|
||||
proxy_cache test_cache;
|
||||
proxy_cache_key $uri$is_args$args;
|
||||
proxy_cache_valid 3m;
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location ~ /purge(/.*) {
|
||||
proxy_cache_purge test_cache $1$is_args$args;
|
||||
cache_purge_response_type html;
|
||||
}
|
||||
|
||||
location ~ /purge_json(/.*) {
|
||||
proxy_cache_purge test_cache $1$is_args$args;
|
||||
}
|
||||
|
||||
location ~ /purge_xml(/.*) {
|
||||
proxy_cache_purge test_cache $1$is_args$args;
|
||||
cache_purge_response_type xml;
|
||||
}
|
||||
|
||||
location ~ /purge_text(/.*) {
|
||||
proxy_cache_purge test_cache $1$is_args$args;
|
||||
cache_purge_response_type text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
location = /etc/passwd {
|
||||
root /;
|
||||
}
|
||||
_EOC_
|
||||
|
||||
worker_connections(128);
|
||||
no_shuffle();
|
||||
run_tests();
|
||||
|
||||
no_diff();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: prepare
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 2: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 3: purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge/proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: Successful purge
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 4: purge from empty cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge/proxy/passwd
|
||||
--- error_code: 412
|
||||
--- response_headers
|
||||
Content-Type: text/html
|
||||
--- response_body_like: 412 Precondition Failed
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 5: get from source
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: MISS
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
||||
=== TEST 6: get from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
X-Cache-Status: HIT
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 5: < 0.8.3 or < 0.7.62
|
||||
|
||||
=== TEST 7-prepare: prepare purge
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd?t=7
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
=== TEST 7: get a JSON response after purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge_json/proxy/passwd?t=7
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: application/json
|
||||
--- response_body_like: {\"Key\": \"\/proxy\/passwd\?t=7\"
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
=== TEST 8-prepare: prepare purge
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd?t=8
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
=== TEST 8: get a XML response after purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge_xml/proxy/passwd?t=8
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/xml
|
||||
--- response_body_like: \<\?xml version=\"1.0\" encoding=\"UTF-8\"\?><status><Key><\!\[CDATA\[\/proxy\/passwd\?t=8\]\]><\/Key>
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
=== TEST 9-prepare: prepare purge
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
GET /proxy/passwd?t=9
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: root
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
=== TEST 9: get a TEXT response after purge from cache
|
||||
--- http_config eval: $::http_config
|
||||
--- config eval: $::config
|
||||
--- request
|
||||
PURGE /purge_text/proxy/passwd?t=9
|
||||
--- error_code: 200
|
||||
--- response_headers
|
||||
Content-Type: text/plain
|
||||
--- response_body_like: Key
|
||||
--- timeout: 10
|
||||
--- no_error_log eval
|
||||
qr/\[(warn|error|crit|alert|emerg)\]/
|
||||
--- skip_nginx2: 4: < 0.8.3 or < 0.7.62
|
||||
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
*.t linguist-language=Text
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
.libs
|
||||
*.swp
|
||||
*.slo
|
||||
*.la
|
||||
*.swo
|
||||
*.lo
|
||||
*.mobi
|
||||
genmobi.sh
|
||||
*~
|
||||
*.o
|
||||
print.txt
|
||||
.rsync
|
||||
*.tar.gz
|
||||
dist
|
||||
build[789]
|
||||
build
|
||||
tags
|
||||
update-readme
|
||||
*.tmp
|
||||
test/Makefile
|
||||
test/blib
|
||||
test.sh
|
||||
t.sh
|
||||
t/t.sh
|
||||
test/t/servroot/
|
||||
releng
|
||||
reset
|
||||
*.t_
|
||||
reindex
|
||||
src/location.h
|
||||
src/filter.c
|
||||
src/subrequest.h
|
||||
src/sleep.h
|
||||
src/util.c
|
||||
src/echo.c
|
||||
src/info.c
|
||||
src/util.h
|
||||
src/var.h
|
||||
src/filter.h
|
||||
src/sleep.c
|
||||
src/var.c
|
||||
src/timer.c
|
||||
src/module.h
|
||||
src/echo.h
|
||||
src/info.h
|
||||
src/foreach.c
|
||||
src/location.c
|
||||
src/timer.h
|
||||
src/module.c
|
||||
src/subrequest.c
|
||||
src/handler.h
|
||||
src/foreach.h
|
||||
src/handler.c
|
||||
nginx
|
||||
*.html
|
||||
ctags
|
||||
t/servroot
|
||||
all
|
||||
buildroot/
|
||||
go
|
||||
Changes
|
||||
build1[0-9]
|
||||
analyze
|
||||
Makefile
|
||||
*.plist
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
sudo: required
|
||||
dist: bionic
|
||||
|
||||
os: linux
|
||||
|
||||
language: c
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
env:
|
||||
global:
|
||||
- LUAJIT_PREFIX=/opt/luajit21
|
||||
- LUAJIT_LIB=$LUAJIT_PREFIX/lib
|
||||
- LUAJIT_INC=$LUAJIT_PREFIX/include/luajit-2.1
|
||||
- LD_LIBRARY_PATH=$LUAJIT_LIB:$LD_LIBRARY_PATH
|
||||
matrix:
|
||||
- NGINX_VERSION=1.17.8
|
||||
- NGINX_VERSION=1.19.9
|
||||
|
||||
before_install:
|
||||
- sudo apt-get install -qq -y cpanminus libgd-dev ca-certificates
|
||||
- sudo cpanm -v --notest Test::Nginx > build.log 2>&1 || (cat build.log && exit 1)
|
||||
|
||||
install:
|
||||
- wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz && tar -xzf nginx-${NGINX_VERSION}.tar.gz
|
||||
- git clone https://github.com/simpl/ngx_devel_kit.git
|
||||
- git clone https://github.com/openresty/set-misc-nginx-module.git
|
||||
- git clone https://github.com/openresty/xss-nginx-module.git
|
||||
- git clone https://github.com/openresty/rds-json-nginx-module.git
|
||||
- git clone https://github.com/openresty/headers-more-nginx-module.git
|
||||
- git clone https://github.com/openresty/lua-nginx-module.git
|
||||
- git clone https://github.com/openresty/lua-resty-core.git ../lua-resty-core
|
||||
- git clone https://github.com/openresty/lua-resty-lrucache.git ../lua-resty-lrucache
|
||||
- git clone https://github.com/openresty/nginx-eval-module.git
|
||||
- git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git luajit2
|
||||
|
||||
script:
|
||||
- cd luajit2/
|
||||
- make -j$JOBS CCDEBUG=-g Q= PREFIX=$LUAJIT_PREFIX CC=$CC XCFLAGS='-DLUA_USE_APICHECK -DLUA_USE_ASSERT -msse4.2' > build.log 2>&1 || (cat build.log && exit 1)
|
||||
- sudo make install PREFIX=$LUAJIT_PREFIX > build.log 2>&1 || (cat build.log && exit 1)
|
||||
- cd ..
|
||||
- cd nginx-${NGINX_VERSION}/
|
||||
- ./configure --without-http_ssi_module --with-debug --with-select_module --with-poll_module --with-http_stub_status_module --with-http_image_filter_module --add-module=../ngx_devel_kit --add-module=../set-misc-nginx-module --add-module=../nginx-eval-module --add-module=../xss-nginx-module --add-module=../rds-json-nginx-module --add-module=../headers-more-nginx-module --add-module=../lua-nginx-module --add-module=.. > build.log 2>&1 || (cat build.log && exit 1)
|
||||
- make -j2 > build.log 2>&1 || (cat build.log && exit 1)
|
||||
- export PATH=$PATH:`pwd`/objs
|
||||
- cd ..
|
||||
- prove -I. -r t
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
Copyright (C) 2009-2014, Yichun "agentzh" Zhang <agentzh@gmail.com>.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,63 +0,0 @@
|
|||
ngx_addon_name=ngx_http_echo_module
|
||||
|
||||
ECHO_SRCS=" \
|
||||
$ngx_addon_dir/src/ngx_http_echo_module.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_util.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_timer.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_var.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_handler.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_filter.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_sleep.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_location.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_echo.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_request_info.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_subrequest.c \
|
||||
$ngx_addon_dir/src/ngx_http_echo_foreach.c \
|
||||
"
|
||||
|
||||
ECHO_DEPS=" \
|
||||
$ngx_addon_dir/src/ddebug.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_module.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_handler.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_util.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_sleep.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_filter.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_var.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_location.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_echo.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_request_info.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_subrequest.h \
|
||||
$ngx_addon_dir/src/ngx_http_echo_foreach.h \
|
||||
"
|
||||
|
||||
# nginx 1.17.0+ unconditionally enables the postpone filter
|
||||
if [ ! -z "$HTTP_POSTPONE" ]; then
|
||||
# nginx won't have HTTP_POSTPONE_FILTER_MODULE & HTTP_POSTPONE_FILTER_SRCS
|
||||
# defined since 1.9.11
|
||||
if [ -z "$HTTP_POSTPONE_FILTER_MODULE" ]; then
|
||||
HTTP_POSTPONE_FILTER_MODULE=ngx_http_postpone_filter_module
|
||||
HTTP_POSTPONE_FILTER_SRCS=src/http/ngx_http_postpone_filter_module.c
|
||||
fi
|
||||
|
||||
# This module depends upon the postpone filter being activated
|
||||
if [ "$HTTP_POSTPONE" != YES ]; then
|
||||
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_POSTPONE_FILTER_MODULE"
|
||||
HTTP_SRCS="$HTTP_SRCS $HTTP_POSTPONE_FILTER_SRCS"
|
||||
HTTP_POSTPONE=YES
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$ngx_module_link" ]; then
|
||||
ngx_module_type=HTTP_AUX_FILTER
|
||||
ngx_module_name=$ngx_addon_name
|
||||
ngx_module_incs=
|
||||
ngx_module_deps="$ECHO_DEPS"
|
||||
ngx_module_srcs="$ECHO_SRCS"
|
||||
ngx_module_libs=
|
||||
|
||||
. auto/module
|
||||
else
|
||||
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
|
||||
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ECHO_SRCS"
|
||||
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ECHO_DEPS"
|
||||
fi
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
libnginx-mod-http-echo (1:0.63-7) unstable; urgency=medium
|
||||
|
||||
* d/control: update my email to janmojzis@debian.org
|
||||
* d/copyright: update my email to janmojzis@debian.org
|
||||
* d/control: bump Standards-Version: 4.7.2, no changes
|
||||
* d/copyright: bump debian/* copyright year
|
||||
* d/watch: use more generic template
|
||||
|
||||
-- Jan Mojžíš <janmojzis@debian.org> Fri, 11 Apr 2025 14:26:58 +0200
|
||||
|
||||
libnginx-mod-http-echo (1:0.63-6) unstable; urgency=medium
|
||||
|
||||
* d/control: remove Build-Depends nginx-abi-1.24.0-1
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Sat, 07 Oct 2023 15:31:26 +0200
|
||||
|
||||
libnginx-mod-http-echo (1:0.63-5) unstable; urgency=medium
|
||||
|
||||
* NEW ABI: rebuild with nginx-abi-1.24.0-1
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Tue, 27 Jun 2023 23:16:36 +0200
|
||||
|
||||
libnginx-mod-http-echo (1:0.63-4) unstable; urgency=medium
|
||||
|
||||
* d/t/generic rework. The test now checks module after
|
||||
installation/reload/restart.
|
||||
* d/control: bump Standards-Version: 4.6.2, no changes
|
||||
* d/gbb.conf: added
|
||||
* d/copyright: bump my copyright year
|
||||
* d/copyright: reformat text to be compatible with 'cme update dpkg-copyright'
|
||||
* d/fix.scanned.copyright: added, fixes upstream author name parsing
|
||||
* NEW ABI: rebuild with nginx-abi-1.22.1-7
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Mon, 13 Feb 2023 15:03:42 +0100
|
||||
|
||||
libnginx-mod-http-echo (1:0.63-3) unstable; urgency=medium
|
||||
|
||||
* No source change upload to unstable.
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Fri, 09 Dec 2022 14:36:45 +0100
|
||||
|
||||
libnginx-mod-http-echo (1:0.63-2) experimental; urgency=medium
|
||||
|
||||
* d/control: added Multi-Arch: foreign
|
||||
* d/copyright: update, add Igor Sysoev
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Mon, 05 Dec 2022 21:14:02 +0100
|
||||
|
||||
libnginx-mod-http-echo (1:0.63-1) experimental; urgency=medium
|
||||
|
||||
* Initial release. (Closes: 1024153)
|
||||
|
||||
-- Jan Mojžíš <jan.mojzis@gmail.com> Wed, 30 Nov 2022 14:46:48 +0100
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
Source: libnginx-mod-http-echo
|
||||
Section: httpd
|
||||
Priority: optional
|
||||
Maintainer: Debian Nginx Maintainers <pkg-nginx-maintainers@alioth-lists.debian.net>
|
||||
Uploaders: Jan Mojžíš <janmojzis@debian.org>,
|
||||
Build-Depends: debhelper-compat (= 13),
|
||||
dh-sequence-nginx,
|
||||
Standards-Version: 4.7.2
|
||||
Homepage: https://github.com/agentzh/echo-nginx-module
|
||||
Vcs-Git: https://salsa.debian.org/nginx-team/libnginx-mod-http-echo.git
|
||||
Vcs-Browser: https://salsa.debian.org/nginx-team/libnginx-mod-http-echo
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: libnginx-mod-http-echo
|
||||
Architecture: any
|
||||
Multi-Arch: foreign
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
Recommends: nginx,
|
||||
Description: Bring echo and more shell style goodies to Nginx
|
||||
Echo module wraps lots of Nginx internal APIs for streaming input and output,
|
||||
parallel/sequential subrequests, timers and sleeping, as well as various meta
|
||||
data accessing.
|
||||
.
|
||||
Basically it provides various utilities that help testing and debugging of
|
||||
other modules by trivially emulating different kinds of faked subrequest
|
||||
locations.
|
||||
.
|
||||
People will also find it useful in real-world applications that need to:
|
||||
.
|
||||
1. Serve static contents directly from memory.
|
||||
2. Wrap the upstream response with custom header and footer (kinda like the
|
||||
addition module but with contents read directly from the config file and
|
||||
Nginx variables).
|
||||
3. Merge contents of various "Nginx locations" (i.e., subrequests) together in
|
||||
a single main request (using echo_location and its friends).
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: echo-nginx-module
|
||||
Upstream-Contact: Yichun "agentzh" Zhang <agentzh@gmail.com>
|
||||
Source: https://github.com/agentzh/echo-nginx-module
|
||||
|
||||
Files: *
|
||||
Copyright: 2009-2018, Yichun "agentzh" Zhang (章亦春) <agentzh@gmail.com>, OpenResty Inc.
|
||||
2009-2014, Yichun "agentzh" Zhang <agentzh@gmail.com>.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: README.markdown
|
||||
Copyright: 2009-2018, Yichun "agentzh" Zhang (章亦春) <agentzh@gmail.com>, OpenResty Inc.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: config
|
||||
Copyright: 2009-2018, Yichun "agentzh" Zhang <agentzh@gmail.com>.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2022, Miao Wang <shankerwangmiao@gmail.com>
|
||||
2022-2025, Jan Mojzis <janmojzis@debian.org>
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: src/*
|
||||
Copyright: 2009-2018, Yichun "agentzh" Zhang <agentzh@gmail.com>.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: src/ngx_http_echo_handler.c
|
||||
src/ngx_http_echo_module.c
|
||||
src/ngx_http_echo_module.h
|
||||
src/ngx_http_echo_request_info.c
|
||||
src/ngx_http_echo_sleep.c
|
||||
src/ngx_http_echo_subrequest.c
|
||||
src/ngx_http_echo_util.c
|
||||
src/ngx_http_echo_util.h
|
||||
Copyright: Yichun Zhang (agentzh)
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: t/*
|
||||
Copyright: 2009-2018, Yichun "agentzh" Zhang <agentzh@gmail.com>.
|
||||
License: BSD-2-clause
|
||||
|
||||
Files: util/*
|
||||
Copyright: 2009-2018, Yichun "agentzh" Zhang <agentzh@gmail.com>.
|
||||
License: BSD-2-clause
|
||||
|
||||
License: BSD-2-clause
|
||||
All rights reserved.
|
||||
.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
# fixes upstream author name parsing
|
||||
! copyright Files:~/.*/ Copyright=~"s/(Zhang)\s\(.*x\{6625\}\)/$1\ (章亦春)/"
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
[DEFAULT]
|
||||
debian-branch = main
|
||||
upstream-branch = upstream
|
||||
upstream-tag = upstream/%(version)s
|
||||
pristine-tar = False
|
||||
sign-tags = True
|
||||
|
||||
[import-orig]
|
||||
merge-mode = replace
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
|
@ -1 +0,0 @@
|
|||
3.0 (quilt)
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
Tests: generic
|
||||
Restrictions: allow-stderr isolation-container needs-root
|
||||
Depends: curl,
|
||||
nginx,
|
||||
nginx-core,
|
||||
@,
|
||||
|
||||
Tests: helloworld
|
||||
Restrictions: allow-stderr isolation-container needs-root
|
||||
Depends: curl,
|
||||
nginx,
|
||||
nginx-core,
|
||||
@,
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#!/bin/sh
|
||||
# version 20221215
|
||||
|
||||
# generic test that only verifies that nginx is running with the given
|
||||
# libnginx-... module
|
||||
# - after installation
|
||||
# - after nginx reload
|
||||
# - after nginx restart
|
||||
|
||||
EX=0
|
||||
CURL_CMD="curl --max-time 60 --silent --fail -o /dev/null"
|
||||
|
||||
#change directory to $AUTOPKGTEST_TMP
|
||||
cd "${AUTOPKGTEST_TMP}"
|
||||
|
||||
echo -n "curl after installation: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
echo -n "nginx reload ... "
|
||||
if invoke-rc.d nginx reload; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
sleep 5
|
||||
|
||||
|
||||
echo -n "curl after reload: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
echo -n "nginx restart ... "
|
||||
if invoke-rc.d nginx restart; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
sleep 5
|
||||
|
||||
echo -n "curl after restart: http status="
|
||||
if $CURL_CMD -w "response_code: %{http_code}, ... " http://127.0.0.1/; then
|
||||
echo "OK"
|
||||
else
|
||||
EX=1
|
||||
echo "FAILED"
|
||||
fi
|
||||
|
||||
if [ ${EX} -ne 0 ]; then
|
||||
echo "=== journalctl ==="
|
||||
journalctl -n all -xu nginx.service || :
|
||||
|
||||
echo "=== error.log ==="
|
||||
if [ `wc -l /var/log/nginx/error.log | cut -d ' ' -f1` -gt 100 ]; then
|
||||
head -n 50 /var/log/nginx/error.log
|
||||
echo '...'
|
||||
tail -n 50 /var/log/nginx/error.log
|
||||
else
|
||||
cat /var/log/nginx/error.log
|
||||
fi
|
||||
fi
|
||||
|
||||
exit ${EX}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cat <<EOF > "/etc/nginx/sites-enabled/default"
|
||||
server {
|
||||
listen 80 default_server;
|
||||
|
||||
location /helloworld {
|
||||
echo "hello world";
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
exp="hello world
|
||||
response_code: 200"
|
||||
|
||||
nginx -t
|
||||
invoke-rc.d nginx restart || { journalctl -n all -xu nginx.service; exit 1; }
|
||||
|
||||
out=`curl --fail -w "response_code: %{http_code}\n" http://127.0.0.1/helloworld`
|
||||
|
||||
if [ x"${out}" != x"${exp}" ]; then
|
||||
echo "output:"
|
||||
echo "====================="
|
||||
echo "${out}"
|
||||
echo "====================="
|
||||
echo "expected output:"
|
||||
echo "====================="
|
||||
echo "${exp}"
|
||||
echo "====================="
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
Bug-Database: https://github.com/agentzh/echo-nginx-module/issues
|
||||
Bug-Submit: https://github.com/agentzh/echo-nginx-module/issues/new
|
||||
Repository-Browse: https://github.com/agentzh/echo-nginx-module
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
version=4
|
||||
opts="\
|
||||
uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha|a|b)\d*)$/$1~$2/,\
|
||||
" \
|
||||
https://github.com/agentzh/echo-nginx-module/tags \
|
||||
(?:.*?/)?v?@ANY_VERSION@@ARCHIVE_EXT@
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
#ifndef DDEBUG_H
|
||||
#define DDEBUG_H
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
#if defined(DDEBUG) && (DDEBUG)
|
||||
|
||||
# if (NGX_HAVE_VARIADIC_MACROS)
|
||||
|
||||
# define dd(...) fprintf(stderr, "echo *** %s: ", __func__); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, " at %s line %d.\n", __FILE__, __LINE__)
|
||||
|
||||
# else
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static ngx_inline void
|
||||
dd(const char * fmt, ...) {
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
# if DDEBUG > 1
|
||||
|
||||
# define dd_enter() dd_enter_helper(r, __func__)
|
||||
|
||||
static ngx_inline void
|
||||
dd_enter_helper(ngx_http_request_t *r, const char *func) {
|
||||
ngx_http_posted_request_t *pr;
|
||||
|
||||
fprintf(stderr, ">enter %s %.*s %.*s?%.*s c:%d m:%p r:%p ar:%p pr:%p",
|
||||
func,
|
||||
(int) r->method_name.len, r->method_name.data,
|
||||
(int) r->uri.len, r->uri.data,
|
||||
(int) r->args.len, r->args.data,
|
||||
0/*(int) r->main->count*/, r->main,
|
||||
r, r->connection->data, r->parent);
|
||||
|
||||
if (r->posted_requests) {
|
||||
fprintf(stderr, " posted:");
|
||||
|
||||
for (pr = r->posted_requests; pr; pr = pr->next) {
|
||||
fprintf(stderr, "%p,", pr);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
# define dd_enter()
|
||||
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
# if (NGX_HAVE_VARIADIC_MACROS)
|
||||
|
||||
# define dd(...)
|
||||
|
||||
# define dd_enter()
|
||||
|
||||
# else
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static ngx_inline void
|
||||
dd(const char * fmt, ...) {
|
||||
}
|
||||
|
||||
static ngx_inline void
|
||||
dd_enter() {
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(DDEBUG) && (DDEBUG)
|
||||
|
||||
#define dd_check_read_event_handler(r) \
|
||||
dd("r->read_event_handler = %s", \
|
||||
r->read_event_handler == ngx_http_block_reading ? \
|
||||
"ngx_http_block_reading" : \
|
||||
r->read_event_handler == ngx_http_test_reading ? \
|
||||
"ngx_http_test_reading" : \
|
||||
r->read_event_handler == ngx_http_request_empty_handler ? \
|
||||
"ngx_http_request_empty_handler" : "UNKNOWN")
|
||||
|
||||
#define dd_check_write_event_handler(r) \
|
||||
dd("r->write_event_handler = %s", \
|
||||
r->write_event_handler == ngx_http_handler ? \
|
||||
"ngx_http_handler" : \
|
||||
r->write_event_handler == ngx_http_core_run_phases ? \
|
||||
"ngx_http_core_run_phases" : \
|
||||
r->write_event_handler == ngx_http_request_empty_handler ? \
|
||||
"ngx_http_request_empty_handler" : "UNKNOWN")
|
||||
|
||||
#else
|
||||
|
||||
#define dd_check_read_event_handler(r)
|
||||
#define dd_check_write_event_handler(r)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* DDEBUG_H */
|
||||
|
||||
|
|
@ -1,342 +0,0 @@
|
|||
#ifndef DDEBUG
|
||||
#define DDEBUG 0
|
||||
#endif
|
||||
#include "ddebug.h"
|
||||
|
||||
#include "ngx_http_echo_echo.h"
|
||||
#include "ngx_http_echo_util.h"
|
||||
#include "ngx_http_echo_filter.h"
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
static ngx_buf_t ngx_http_echo_space_buf;
|
||||
|
||||
static ngx_buf_t ngx_http_echo_newline_buf;
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_echo_init(ngx_conf_t *cf)
|
||||
{
|
||||
static u_char space_str[] = " ";
|
||||
static u_char newline_str[] = "\n";
|
||||
|
||||
dd("global init...");
|
||||
|
||||
ngx_memzero(&ngx_http_echo_space_buf, sizeof(ngx_buf_t));
|
||||
|
||||
ngx_http_echo_space_buf.memory = 1;
|
||||
|
||||
ngx_http_echo_space_buf.start =
|
||||
ngx_http_echo_space_buf.pos =
|
||||
space_str;
|
||||
|
||||
ngx_http_echo_space_buf.end =
|
||||
ngx_http_echo_space_buf.last =
|
||||
space_str + sizeof(space_str) - 1;
|
||||
|
||||
ngx_memzero(&ngx_http_echo_newline_buf, sizeof(ngx_buf_t));
|
||||
|
||||
ngx_http_echo_newline_buf.memory = 1;
|
||||
|
||||
ngx_http_echo_newline_buf.start =
|
||||
ngx_http_echo_newline_buf.pos =
|
||||
newline_str;
|
||||
|
||||
ngx_http_echo_newline_buf.end =
|
||||
ngx_http_echo_newline_buf.last =
|
||||
newline_str + sizeof(newline_str) - 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_sync(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx)
|
||||
{
|
||||
ngx_buf_t *buf;
|
||||
ngx_chain_t *cl = NULL; /* the head of the chain link */
|
||||
|
||||
buf = ngx_calloc_buf(r->pool);
|
||||
if (buf == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
buf->sync = 1;
|
||||
|
||||
cl = ngx_alloc_chain_link(r->pool);
|
||||
if (cl == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
cl->buf = buf;
|
||||
cl->next = NULL;
|
||||
|
||||
return ngx_http_echo_send_chain_link(r, ctx, cl);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args,
|
||||
ngx_flag_t in_filter, ngx_array_t *opts)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
|
||||
ngx_buf_t *space_buf;
|
||||
ngx_buf_t *newline_buf;
|
||||
ngx_buf_t *buf;
|
||||
|
||||
ngx_str_t *computed_arg;
|
||||
ngx_str_t *computed_arg_elts;
|
||||
ngx_str_t *opt;
|
||||
|
||||
ngx_chain_t *cl = NULL; /* the head of the chain link */
|
||||
ngx_chain_t **ll = &cl; /* always point to the address of the last link */
|
||||
|
||||
dd_enter();
|
||||
|
||||
if (computed_args == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
computed_arg_elts = computed_args->elts;
|
||||
for (i = 0; i < computed_args->nelts; i++) {
|
||||
computed_arg = &computed_arg_elts[i];
|
||||
|
||||
if (computed_arg->len == 0) {
|
||||
buf = NULL;
|
||||
|
||||
} else {
|
||||
buf = ngx_calloc_buf(r->pool);
|
||||
if (buf == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
buf->start = buf->pos = computed_arg->data;
|
||||
buf->last = buf->end = computed_arg->data +
|
||||
computed_arg->len;
|
||||
|
||||
buf->memory = 1;
|
||||
}
|
||||
|
||||
if (cl == NULL) {
|
||||
cl = ngx_alloc_chain_link(r->pool);
|
||||
if (cl == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
cl->buf = buf;
|
||||
cl->next = NULL;
|
||||
ll = &cl->next;
|
||||
|
||||
} else {
|
||||
/* append a space first */
|
||||
*ll = ngx_alloc_chain_link(r->pool);
|
||||
|
||||
if (*ll == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
space_buf = ngx_calloc_buf(r->pool);
|
||||
|
||||
if (space_buf == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
/* nginx clears buf flags at the end of each request handling,
|
||||
* so we have to make a clone here. */
|
||||
*space_buf = ngx_http_echo_space_buf;
|
||||
|
||||
(*ll)->buf = space_buf;
|
||||
(*ll)->next = NULL;
|
||||
|
||||
ll = &(*ll)->next;
|
||||
|
||||
/* then append the buf only if it's non-empty */
|
||||
if (buf) {
|
||||
*ll = ngx_alloc_chain_link(r->pool);
|
||||
if (*ll == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
(*ll)->buf = buf;
|
||||
(*ll)->next = NULL;
|
||||
|
||||
ll = &(*ll)->next;
|
||||
}
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
if (cl && cl->buf == NULL) {
|
||||
cl = cl->next;
|
||||
}
|
||||
|
||||
if (opts && opts->nelts > 0) {
|
||||
opt = opts->elts;
|
||||
/* FIXME handle other unrecognized options here */
|
||||
if (opt[0].len == 1 && opt[0].data[0] == 'n') {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* append the newline character */
|
||||
|
||||
newline_buf = ngx_calloc_buf(r->pool);
|
||||
|
||||
if (newline_buf == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
*newline_buf = ngx_http_echo_newline_buf;
|
||||
|
||||
if (cl == NULL) {
|
||||
cl = ngx_alloc_chain_link(r->pool);
|
||||
|
||||
if (cl == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
cl->buf = newline_buf;
|
||||
cl->next = NULL;
|
||||
/* ll = &cl->next; */
|
||||
|
||||
} else {
|
||||
*ll = ngx_alloc_chain_link(r->pool);
|
||||
|
||||
if (*ll == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
(*ll)->buf = newline_buf;
|
||||
(*ll)->next = NULL;
|
||||
/* ll = &(*ll)->next; */
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (cl == NULL || cl->buf == NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (in_filter) {
|
||||
return ngx_http_echo_next_body_filter(r, cl);
|
||||
}
|
||||
|
||||
return ngx_http_echo_send_chain_link(r, ctx, cl);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_flush(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx)
|
||||
{
|
||||
return ngx_http_send_special(r, NGX_HTTP_FLUSH);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_request_body(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx)
|
||||
{
|
||||
ngx_buf_t *b;
|
||||
ngx_chain_t *out, *cl, **ll;
|
||||
|
||||
if (r->request_body == NULL || r->request_body->bufs == NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
out = NULL;
|
||||
ll = &out;
|
||||
|
||||
for (cl = r->request_body->bufs; cl; cl = cl->next) {
|
||||
if (ngx_buf_special(cl->buf)) {
|
||||
/* we do not want to create zero-size bufs */
|
||||
continue;
|
||||
}
|
||||
|
||||
*ll = ngx_alloc_chain_link(r->pool);
|
||||
if (*ll == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
b = ngx_alloc_buf(r->pool);
|
||||
if (b == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
(*ll)->buf = b;
|
||||
(*ll)->next = NULL;
|
||||
|
||||
ngx_memcpy(b, cl->buf, sizeof(ngx_buf_t));
|
||||
b->tag = (ngx_buf_tag_t) &ngx_http_echo_exec_echo_request_body;
|
||||
b->last_buf = 0;
|
||||
b->last_in_chain = 0;
|
||||
|
||||
ll = &(*ll)->next;
|
||||
}
|
||||
|
||||
if (out == NULL) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
return ngx_http_echo_send_chain_link(r, ctx, out);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_duplicate(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args)
|
||||
{
|
||||
ngx_str_t *computed_arg;
|
||||
ngx_str_t *computed_arg_elts;
|
||||
ssize_t i, count;
|
||||
ngx_str_t *str;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_buf_t *buf;
|
||||
ngx_chain_t *cl;
|
||||
|
||||
dd_enter();
|
||||
|
||||
computed_arg_elts = computed_args->elts;
|
||||
|
||||
computed_arg = &computed_arg_elts[0];
|
||||
|
||||
count = ngx_http_echo_atosz(computed_arg->data, computed_arg->len);
|
||||
|
||||
if (count == NGX_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"invalid size specified: \"%V\"", computed_arg);
|
||||
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
str = &computed_arg_elts[1];
|
||||
|
||||
if (count == 0 || str->len == 0) {
|
||||
rc = ngx_http_echo_send_header_if_needed(r, ctx);
|
||||
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
buf = ngx_create_temp_buf(r->pool, count * str->len);
|
||||
if (buf == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
p = buf->pos;
|
||||
for (i = 0; i < count; i++) {
|
||||
p = ngx_copy(p, str->data, str->len);
|
||||
}
|
||||
buf->last = p;
|
||||
|
||||
cl = ngx_alloc_chain_link(r->pool);
|
||||
if (cl == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
cl->next = NULL;
|
||||
cl->buf = buf;
|
||||
|
||||
return ngx_http_echo_send_chain_link(r, ctx, cl);
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
#ifndef ECHO_ECHO_H
|
||||
#define ECHO_ECHO_H
|
||||
|
||||
#include "ngx_http_echo_module.h"
|
||||
|
||||
ngx_int_t ngx_http_echo_echo_init(ngx_conf_t *cf);
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo_sync(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx);
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args,
|
||||
ngx_flag_t in_filter, ngx_array_t *opts);
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo_request_body(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx);
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo_flush(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx);
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo_duplicate(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args);
|
||||
|
||||
#endif /* ECHO_ECHO_H */
|
||||
|
||||
|
|
@ -1,282 +0,0 @@
|
|||
#ifndef DDEBUG
|
||||
#define DDEBUG 0
|
||||
#endif
|
||||
#include "ddebug.h"
|
||||
|
||||
#include "ngx_http_echo_filter.h"
|
||||
#include "ngx_http_echo_util.h"
|
||||
#include "ngx_http_echo_echo.h"
|
||||
|
||||
#include <ngx_log.h>
|
||||
|
||||
|
||||
|
||||
ngx_http_output_header_filter_pt ngx_http_echo_next_header_filter;
|
||||
|
||||
ngx_http_output_body_filter_pt ngx_http_echo_next_body_filter;
|
||||
|
||||
static ngx_int_t ngx_http_echo_header_filter(ngx_http_request_t *r);
|
||||
|
||||
static ngx_int_t ngx_http_echo_body_filter(ngx_http_request_t *r,
|
||||
ngx_chain_t *in);
|
||||
|
||||
/* filter handlers */
|
||||
static ngx_int_t ngx_http_echo_exec_filter_cmds(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *cmds, ngx_uint_t *iterator);
|
||||
|
||||
|
||||
static volatile ngx_cycle_t *ngx_http_echo_prev_cycle = NULL;
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_filter_init(ngx_conf_t *cf)
|
||||
{
|
||||
int multi_http_blocks;
|
||||
ngx_http_echo_main_conf_t *emcf;
|
||||
|
||||
emcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_echo_module);
|
||||
|
||||
if (ngx_http_echo_prev_cycle != ngx_cycle) {
|
||||
ngx_http_echo_prev_cycle = ngx_cycle;
|
||||
multi_http_blocks = 0;
|
||||
|
||||
} else {
|
||||
multi_http_blocks = 1;
|
||||
}
|
||||
|
||||
if (multi_http_blocks || emcf->requires_filter) {
|
||||
dd("top header filter: %ld",
|
||||
(unsigned long) ngx_http_top_header_filter);
|
||||
|
||||
ngx_http_echo_next_header_filter = ngx_http_top_header_filter;
|
||||
ngx_http_top_header_filter = ngx_http_echo_header_filter;
|
||||
|
||||
dd("top body filter: %ld", (unsigned long) ngx_http_top_body_filter);
|
||||
|
||||
ngx_http_echo_next_body_filter = ngx_http_top_body_filter;
|
||||
ngx_http_top_body_filter = ngx_http_echo_body_filter;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_echo_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *conf;
|
||||
ngx_http_echo_ctx_t *ctx;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"echo header filter, uri \"%V?%V\"", &r->uri, &r->args);
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
|
||||
|
||||
/* XXX we should add option to insert contents for responses
|
||||
* of non-200 status code here... */
|
||||
/*
|
||||
if (r->headers_out.status != NGX_HTTP_OK) {
|
||||
if (ctx != NULL) {
|
||||
ctx->skip_filter = 1;
|
||||
}
|
||||
return ngx_http_echo_next_header_filter(r);
|
||||
}
|
||||
*/
|
||||
|
||||
conf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
|
||||
if (conf->before_body_cmds == NULL && conf->after_body_cmds == NULL) {
|
||||
if (ctx != NULL) {
|
||||
ctx->skip_filter = 1;
|
||||
}
|
||||
return ngx_http_echo_next_header_filter(r);
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = ngx_http_echo_create_ctx(r);
|
||||
if (ctx == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_http_set_ctx(r, ctx, ngx_http_echo_module);
|
||||
}
|
||||
|
||||
/* enable streaming here (use chunked encoding) */
|
||||
ngx_http_clear_content_length(r);
|
||||
ngx_http_clear_accept_ranges(r);
|
||||
|
||||
return ngx_http_echo_next_header_filter(r);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_echo_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
{
|
||||
ngx_http_echo_ctx_t *ctx;
|
||||
ngx_int_t rc;
|
||||
ngx_http_echo_loc_conf_t *conf;
|
||||
unsigned last;
|
||||
ngx_chain_t *cl;
|
||||
ngx_buf_t *b;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"echo body filter, uri \"%V?%V\"", &r->uri, &r->args);
|
||||
|
||||
if (in == NULL || r->header_only) {
|
||||
return ngx_http_echo_next_body_filter(r, in);
|
||||
}
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
|
||||
|
||||
if (ctx == NULL || ctx->skip_filter) {
|
||||
return ngx_http_echo_next_body_filter(r, in);
|
||||
}
|
||||
|
||||
conf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
|
||||
|
||||
if (!ctx->before_body_sent) {
|
||||
ctx->before_body_sent = 1;
|
||||
|
||||
if (conf->before_body_cmds != NULL) {
|
||||
rc = ngx_http_echo_exec_filter_cmds(r, ctx, conf->before_body_cmds,
|
||||
&ctx->next_before_body_cmd);
|
||||
if (rc != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->after_body_cmds == NULL) {
|
||||
ctx->skip_filter = 1;
|
||||
return ngx_http_echo_next_body_filter(r, in);
|
||||
}
|
||||
|
||||
last = 0;
|
||||
|
||||
for (cl = in; cl; cl = cl->next) {
|
||||
dd("cl %p, special %d", cl, ngx_buf_special(cl->buf));
|
||||
|
||||
if (cl->buf->last_buf || cl->buf->last_in_chain) {
|
||||
cl->buf->last_buf = 0;
|
||||
cl->buf->last_in_chain = 0;
|
||||
cl->buf->sync = 1;
|
||||
last = 1;
|
||||
}
|
||||
}
|
||||
|
||||
dd("in %p, last %d", in, (int) last);
|
||||
|
||||
if (in) {
|
||||
rc = ngx_http_echo_next_body_filter(r, in);
|
||||
|
||||
#if 0
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
dd("next filter returns %d, last %d", (int) rc, (int) last);
|
||||
|
||||
if (rc == NGX_ERROR || rc > NGX_OK || !last) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
dd("exec filter cmds for after body cmds");
|
||||
|
||||
rc = ngx_http_echo_exec_filter_cmds(r, ctx, conf->after_body_cmds,
|
||||
&ctx->next_after_body_cmd);
|
||||
if (rc == NGX_ERROR || rc > NGX_OK) {
|
||||
dd("FAILED: exec filter cmds for after body cmds");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->skip_filter = 1;
|
||||
|
||||
dd("after body cmds executed...terminating...");
|
||||
|
||||
/* XXX we can NOT use
|
||||
* ngx_http_send_special(r, NGX_HTTP_LAST) here
|
||||
* because we should bypass the upstream filters. */
|
||||
|
||||
b = ngx_calloc_buf(r->pool);
|
||||
if (b == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (r == r->main && !r->post_action) {
|
||||
b->last_buf = 1;
|
||||
|
||||
} else {
|
||||
b->sync = 1;
|
||||
b->last_in_chain = 1;
|
||||
}
|
||||
|
||||
cl = ngx_alloc_chain_link(r->pool);
|
||||
if (cl == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
cl->next = NULL;
|
||||
cl->buf = b;
|
||||
|
||||
return ngx_http_echo_next_body_filter(r, cl);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_echo_exec_filter_cmds(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *cmds, ngx_uint_t *iterator)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_array_t *opts = NULL;
|
||||
ngx_array_t *computed_args = NULL;
|
||||
ngx_http_echo_cmd_t *cmd;
|
||||
ngx_http_echo_cmd_t *cmd_elts;
|
||||
|
||||
for (cmd_elts = cmds->elts; *iterator < cmds->nelts; (*iterator)++) {
|
||||
cmd = &cmd_elts[*iterator];
|
||||
|
||||
/* evaluate arguments for the current cmd (if any) */
|
||||
if (cmd->args) {
|
||||
computed_args = ngx_array_create(r->pool, cmd->args->nelts,
|
||||
sizeof(ngx_str_t));
|
||||
if (computed_args == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
opts = ngx_array_create(r->pool, 1, sizeof(ngx_str_t));
|
||||
if (opts == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
rc = ngx_http_echo_eval_cmd_args(r, cmd, computed_args, opts);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"Failed to evaluate arguments for "
|
||||
"the directive.");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
/* do command dispatch based on the opcode */
|
||||
switch (cmd->opcode) {
|
||||
case echo_opcode_echo_before_body:
|
||||
case echo_opcode_echo_after_body:
|
||||
dd("exec echo_before_body or echo_after_body...");
|
||||
|
||||
rc = ngx_http_echo_exec_echo(r, ctx, computed_args,
|
||||
1 /* in filter */, opts);
|
||||
|
||||
if (rc == NGX_ERROR || rc > NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef ECHO_FILTER_H
|
||||
#define ECHO_FILTER_H
|
||||
|
||||
#include "ngx_http_echo_module.h"
|
||||
|
||||
|
||||
extern ngx_http_output_header_filter_pt ngx_http_echo_next_header_filter;
|
||||
|
||||
extern ngx_http_output_body_filter_pt ngx_http_echo_next_body_filter;
|
||||
|
||||
|
||||
ngx_int_t ngx_http_echo_filter_init (ngx_conf_t *cf);
|
||||
|
||||
#endif /* ECHO_FILTER_H */
|
||||
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
#ifndef DDEBUG
|
||||
#define DDEBUG 0
|
||||
#endif
|
||||
#include "ddebug.h"
|
||||
|
||||
#include "ngx_http_echo_foreach.h"
|
||||
#include "ngx_http_echo_util.h"
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_it_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
ngx_http_echo_ctx_t *ctx;
|
||||
ngx_uint_t i;
|
||||
ngx_array_t *choices;
|
||||
ngx_str_t *choice_elts, *choice;
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
|
||||
|
||||
if (ctx && ctx->foreach != NULL) {
|
||||
|
||||
choices = ctx->foreach->choices;
|
||||
i = ctx->foreach->next_choice;
|
||||
|
||||
if (i < choices->nelts) {
|
||||
choice_elts = choices->elts;
|
||||
choice = &choice_elts[i];
|
||||
|
||||
v->len = choice->len;
|
||||
v->data = choice->data;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 1;
|
||||
v->not_found = 0;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
||||
v->not_found = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_foreach_split(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf;
|
||||
ngx_str_t *delimiter, *compound;
|
||||
u_char *pos, *last, *end;
|
||||
ngx_str_t *choice;
|
||||
ngx_str_t *computed_arg_elts;
|
||||
ngx_array_t *cmds;
|
||||
ngx_http_echo_cmd_t *cmd;
|
||||
ngx_http_echo_cmd_t *cmd_elts;
|
||||
|
||||
if (ctx->foreach != NULL) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"Nested echo_foreach not supported yet.");
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (computed_args->nelts < 2) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"echo_foreach should take at least two arguments. "
|
||||
"(if your delimiter starts with \"-\", preceding it "
|
||||
"with a \"--\".)");
|
||||
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
computed_arg_elts = computed_args->elts;
|
||||
|
||||
compound = &computed_arg_elts[1];
|
||||
|
||||
dd("HEY coumpound len: %u", (int) compound->len);
|
||||
|
||||
ctx->foreach = ngx_palloc(r->pool, sizeof(ngx_http_echo_foreach_ctx_t));
|
||||
|
||||
if (ctx->foreach == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->foreach->cmd_index = ctx->next_handler_cmd;
|
||||
|
||||
ctx->foreach->next_choice = 0;
|
||||
|
||||
ctx->foreach->choices = ngx_array_create(r->pool, 10, sizeof(ngx_str_t));
|
||||
if (ctx->foreach->choices == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
delimiter = &computed_arg_elts[0];
|
||||
|
||||
pos = compound->data;
|
||||
end = compound->data + compound->len;
|
||||
|
||||
while ((last = ngx_http_echo_strlstrn(pos, end, delimiter->data,
|
||||
delimiter->len - 1)) != NULL)
|
||||
{
|
||||
dd("entered the loop");
|
||||
|
||||
if (last == pos) {
|
||||
dd("!!! len == 0");
|
||||
pos = last + delimiter->len;
|
||||
continue;
|
||||
}
|
||||
|
||||
choice = ngx_array_push(ctx->foreach->choices);
|
||||
if (choice == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
choice->data = pos;
|
||||
choice->len = last - pos;
|
||||
pos = last + delimiter->len;
|
||||
}
|
||||
|
||||
if (pos < end) {
|
||||
choice = ngx_array_push(ctx->foreach->choices);
|
||||
if (choice == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
choice->data = pos;
|
||||
choice->len = end - pos;
|
||||
}
|
||||
|
||||
if (ctx->foreach->choices->nelts == 0) {
|
||||
/* skip the foreach body entirely */
|
||||
elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
|
||||
cmds = elcf->handler_cmds;
|
||||
cmd_elts = cmds->elts;
|
||||
for (/* void */; ctx->next_handler_cmd < cmds->nelts;
|
||||
ctx->next_handler_cmd++)
|
||||
{
|
||||
cmd = &cmd_elts[ctx->next_handler_cmd + 1];
|
||||
if (cmd->opcode == echo_opcode_echo_end) {
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_end(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx)
|
||||
{
|
||||
if (ctx->foreach == NULL) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"Found a echo_end that has no corresponding echo_foreach "
|
||||
"before it.");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->foreach->next_choice++;
|
||||
|
||||
if (ctx->foreach->next_choice >= ctx->foreach->choices->nelts) {
|
||||
/* TODO We need to explicitly free the foreach ctx from
|
||||
* the pool */
|
||||
ctx->foreach = NULL;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
dd("echo_end: ++ next_choice (total: %u): %u",
|
||||
(unsigned) ctx->foreach->choices->nelts,
|
||||
(unsigned) ctx->foreach->next_choice);
|
||||
|
||||
/* the main handler dispatcher loop will increment
|
||||
* ctx->next_handler_cmd for us anyway. */
|
||||
ctx->next_handler_cmd = ctx->foreach->cmd_index;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef ECHO_FOREACH_H
|
||||
#define ECHO_FOREACH_H
|
||||
|
||||
#include "ngx_http_echo_module.h"
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo_foreach_split(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args);
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo_end(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx);
|
||||
|
||||
ngx_int_t ngx_http_echo_it_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
|
||||
#endif /* ECHO_FOREACH_H */
|
||||
|
||||
|
|
@ -1,433 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Yichun Zhang (agentzh)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DDEBUG
|
||||
#define DDEBUG 0
|
||||
#endif
|
||||
#include "ddebug.h"
|
||||
|
||||
|
||||
#include "ngx_http_echo_filter.h"
|
||||
#include "ngx_http_echo_handler.h"
|
||||
#include "ngx_http_echo_echo.h"
|
||||
#include "ngx_http_echo_util.h"
|
||||
#include "ngx_http_echo_sleep.h"
|
||||
#include "ngx_http_echo_var.h"
|
||||
#include "ngx_http_echo_timer.h"
|
||||
#include "ngx_http_echo_location.h"
|
||||
#include "ngx_http_echo_subrequest.h"
|
||||
#include "ngx_http_echo_request_info.h"
|
||||
#include "ngx_http_echo_foreach.h"
|
||||
|
||||
#include <nginx.h>
|
||||
#include <ngx_log.h>
|
||||
|
||||
|
||||
void
|
||||
ngx_http_echo_wev_handler(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_http_echo_ctx_t *ctx;
|
||||
|
||||
dd("wev handler");
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
|
||||
|
||||
if (ctx == NULL) {
|
||||
ngx_http_finalize_request(r, NGX_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
dd("waiting: %d, done: %d", (int) ctx->waiting, (int) ctx->done);
|
||||
|
||||
if (ctx->waiting && ! ctx->done) {
|
||||
|
||||
if (r == r->connection->data && r->postponed) {
|
||||
|
||||
if (r->postponed->request) {
|
||||
r->connection->data = r->postponed->request;
|
||||
|
||||
#if defined(nginx_version) && nginx_version >= 8012
|
||||
ngx_http_post_request(r->postponed->request, NULL);
|
||||
#else
|
||||
ngx_http_post_request(r->postponed->request);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
ngx_http_echo_flush_postponed_outputs(r);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->done = 0;
|
||||
|
||||
ctx->next_handler_cmd++;
|
||||
|
||||
rc = ngx_http_echo_run_cmds(r);
|
||||
|
||||
dd("rc: %d", (int) rc);
|
||||
|
||||
if (rc == NGX_ERROR || rc == NGX_DONE) {
|
||||
ngx_http_finalize_request(r, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
dd("mark busy %d for %.*s", (int) ctx->next_handler_cmd,
|
||||
(int) r->uri.len,
|
||||
r->uri.data);
|
||||
|
||||
ctx->waiting = 1;
|
||||
ctx->done = 0;
|
||||
|
||||
} else {
|
||||
dd("mark ready %d", (int) ctx->next_handler_cmd);
|
||||
ctx->waiting = 0;
|
||||
ctx->done = 1;
|
||||
|
||||
dd("finalizing with rc %d", (int) rc);
|
||||
|
||||
dd("finalize request %.*s with %d", (int) r->uri.len, r->uri.data,
|
||||
(int) rc);
|
||||
|
||||
ngx_http_finalize_request(r, rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_handler(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_http_echo_ctx_t *ctx;
|
||||
|
||||
dd("subrequest in memory: %d", (int) r->subrequest_in_memory);
|
||||
|
||||
rc = ngx_http_echo_run_cmds(r);
|
||||
|
||||
dd("run cmds returned %d", (int) rc);
|
||||
|
||||
if (rc == NGX_ERROR
|
||||
|| rc == NGX_OK
|
||||
|| rc == NGX_DONE
|
||||
|| rc == NGX_DECLINED)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
|
||||
|
||||
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
||||
if (ctx && r->header_sent) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* rc == NGX_AGAIN */
|
||||
|
||||
#if defined(nginx_version) && nginx_version >= 8011
|
||||
r->main->count++;
|
||||
#endif
|
||||
|
||||
dd("%d", r->connection->destroyed);
|
||||
dd("%d", r->done);
|
||||
|
||||
if (ctx) {
|
||||
dd("mark busy %d for %.*s", (int) ctx->next_handler_cmd,
|
||||
(int) r->uri.len,
|
||||
r->uri.data);
|
||||
|
||||
ctx->waiting = 1;
|
||||
ctx->done = 0;
|
||||
}
|
||||
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_run_cmds(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf;
|
||||
ngx_http_echo_ctx_t *ctx;
|
||||
ngx_int_t rc;
|
||||
ngx_array_t *cmds;
|
||||
ngx_array_t *computed_args = NULL;
|
||||
ngx_http_echo_cmd_t *cmd;
|
||||
ngx_http_echo_cmd_t *cmd_elts;
|
||||
ngx_array_t *opts = NULL;
|
||||
|
||||
elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module);
|
||||
cmds = elcf->handler_cmds;
|
||||
if (cmds == NULL) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
|
||||
if (ctx == NULL) {
|
||||
ctx = ngx_http_echo_create_ctx(r);
|
||||
if (ctx == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
ngx_http_set_ctx(r, ctx, ngx_http_echo_module);
|
||||
}
|
||||
|
||||
dd("exec handler: %.*s: %i", (int) r->uri.len, r->uri.data,
|
||||
(int) ctx->next_handler_cmd);
|
||||
|
||||
cmd_elts = cmds->elts;
|
||||
|
||||
for (; ctx->next_handler_cmd < cmds->nelts; ctx->next_handler_cmd++) {
|
||||
|
||||
cmd = &cmd_elts[ctx->next_handler_cmd];
|
||||
|
||||
/* evaluate arguments for the current cmd (if any) */
|
||||
if (cmd->args) {
|
||||
computed_args = ngx_array_create(r->pool, cmd->args->nelts,
|
||||
sizeof(ngx_str_t));
|
||||
|
||||
if (computed_args == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
opts = ngx_array_create(r->pool, 1, sizeof(ngx_str_t));
|
||||
|
||||
if (opts == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
rc = ngx_http_echo_eval_cmd_args(r, cmd, computed_args, opts);
|
||||
if (rc != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"Failed to evaluate arguments for "
|
||||
"the directive.");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (computed_args == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
/* do command dispatch based on the opcode */
|
||||
|
||||
switch (cmd->opcode) {
|
||||
|
||||
case echo_opcode_echo_sync:
|
||||
rc = ngx_http_echo_exec_echo_sync(r, ctx);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo:
|
||||
/* XXX moved the following code to a separate
|
||||
* function */
|
||||
dd("found echo opcode");
|
||||
rc = ngx_http_echo_exec_echo(r, ctx, computed_args,
|
||||
0 /* in filter */, opts);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_request_body:
|
||||
rc = ngx_http_echo_exec_echo_request_body(r, ctx);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_location_async:
|
||||
if (!r->request_body) {
|
||||
/* we require reading the request body before doing
|
||||
* subrequests */
|
||||
|
||||
ctx->next_handler_cmd--; /* re-run the current cmd */
|
||||
goto read_request_body;
|
||||
}
|
||||
|
||||
dd("found opcode echo location async...");
|
||||
rc = ngx_http_echo_exec_echo_location_async(r, ctx,
|
||||
computed_args);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_location:
|
||||
if (!r->request_body) {
|
||||
/* we require reading the request body before doing
|
||||
* subrequests */
|
||||
|
||||
ctx->next_handler_cmd--; /* re-run the current cmd */
|
||||
goto read_request_body;
|
||||
}
|
||||
|
||||
return ngx_http_echo_exec_echo_location(r, ctx, computed_args);
|
||||
|
||||
case echo_opcode_echo_subrequest_async:
|
||||
if (!r->request_body) {
|
||||
/* we require reading the request body before doing
|
||||
* subrequests */
|
||||
|
||||
ctx->next_handler_cmd--; /* re-run the current cmd */
|
||||
goto read_request_body;
|
||||
}
|
||||
|
||||
dd("found opcode echo subrequest async...");
|
||||
rc = ngx_http_echo_exec_echo_subrequest_async(r, ctx,
|
||||
computed_args);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_subrequest:
|
||||
if (!r->request_body) {
|
||||
/* we require reading the request body before doing
|
||||
* subrequests */
|
||||
|
||||
ctx->next_handler_cmd--; /* re-run the current cmd */
|
||||
goto read_request_body;
|
||||
}
|
||||
|
||||
return ngx_http_echo_exec_echo_subrequest(r, ctx, computed_args);
|
||||
|
||||
case echo_opcode_echo_sleep:
|
||||
return ngx_http_echo_exec_echo_sleep(r, ctx, computed_args);
|
||||
|
||||
case echo_opcode_echo_flush:
|
||||
rc = ngx_http_echo_exec_echo_flush(r, ctx);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_blocking_sleep:
|
||||
rc = ngx_http_echo_exec_echo_blocking_sleep(r, ctx,
|
||||
computed_args);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_reset_timer:
|
||||
rc = ngx_http_echo_exec_echo_reset_timer(r, ctx);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_duplicate:
|
||||
rc = ngx_http_echo_exec_echo_duplicate(r, ctx, computed_args);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_read_request_body:
|
||||
|
||||
read_request_body:
|
||||
|
||||
ctx->wait_read_request_body = 0;
|
||||
|
||||
rc = ngx_http_echo_exec_echo_read_request_body(r, ctx);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
||||
#if (nginx_version >= 8011 && nginx_version < 1002006) \
|
||||
|| (nginx_version >= 1003000 && nginx_version < 1003009)
|
||||
r->main->count--;
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if nginx_version >= 8011
|
||||
r->main->count--;
|
||||
#endif
|
||||
dd("read request body: %d", (int) rc);
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* rc == NGX_AGAIN */
|
||||
ctx->wait_read_request_body = 1;
|
||||
return NGX_AGAIN;
|
||||
|
||||
case echo_opcode_echo_foreach_split:
|
||||
rc = ngx_http_echo_exec_echo_foreach_split(r, ctx, computed_args);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_end:
|
||||
rc = ngx_http_echo_exec_echo_end(r, ctx);
|
||||
break;
|
||||
|
||||
case echo_opcode_echo_exec:
|
||||
dd("echo_exec");
|
||||
return ngx_http_echo_exec_exec(r, ctx, computed_args);
|
||||
|
||||
default:
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"unknown opcode: %d", cmd->opcode);
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ngx_http_echo_send_chain_link(r, ctx, NULL /* indicate LAST */);
|
||||
|
||||
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!r->request_body) {
|
||||
if (ngx_http_discard_request_body(r) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_post_subrequest(ngx_http_request_t *r,
|
||||
void *data, ngx_int_t rc)
|
||||
{
|
||||
ngx_http_echo_ctx_t *ctx = data;
|
||||
ngx_http_request_t *pr;
|
||||
ngx_http_echo_ctx_t *pr_ctx;
|
||||
|
||||
dd("echo post_subrequest: %.*s", (int) r->uri.len, r->uri.data);
|
||||
|
||||
if (ctx->run_post_subrequest) {
|
||||
dd("already run post_subrequest: %p: %.*s", ctx,
|
||||
(int) r->uri.len, r->uri.data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
dd("setting run_post_subrequest to 1 for %p for %.*s", ctx,
|
||||
(int) r->uri.len, r->uri.data);
|
||||
|
||||
ctx->run_post_subrequest = 1;
|
||||
|
||||
pr = r->parent;
|
||||
|
||||
pr_ctx = ngx_http_get_module_ctx(pr, ngx_http_echo_module);
|
||||
if (pr_ctx == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
dd("mark ready %d", (int) pr_ctx->next_handler_cmd);
|
||||
|
||||
pr_ctx->waiting = 0;
|
||||
pr_ctx->done = 1;
|
||||
|
||||
pr->write_event_handler = ngx_http_echo_wev_handler;
|
||||
|
||||
/* work-around issues in nginx's event module */
|
||||
|
||||
if (r != r->connection->data
|
||||
&& r->postponed
|
||||
&& (r->main->posted_requests == NULL
|
||||
|| r->main->posted_requests->request != pr))
|
||||
{
|
||||
#if defined(nginx_version) && nginx_version >= 8012
|
||||
ngx_http_post_request(pr, NULL);
|
||||
#else
|
||||
ngx_http_post_request(pr);
|
||||
#endif
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef ECHO_HANDLER_H
|
||||
#define ECHO_HANDLER_H
|
||||
|
||||
#include "ngx_http_echo_module.h"
|
||||
|
||||
|
||||
void ngx_http_echo_wev_handler(ngx_http_request_t *r);
|
||||
|
||||
ngx_int_t ngx_http_echo_handler(ngx_http_request_t *r);
|
||||
|
||||
ngx_int_t ngx_http_echo_run_cmds(ngx_http_request_t *r);
|
||||
|
||||
ngx_int_t ngx_http_echo_post_subrequest(ngx_http_request_t *r,
|
||||
void *data, ngx_int_t rc);
|
||||
|
||||
|
||||
#endif /* ECHO_HANDLER_H */
|
||||
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
#ifndef DDEBUG
|
||||
#define DDEBUG 0
|
||||
#endif
|
||||
#include "ddebug.h"
|
||||
|
||||
#include "ngx_http_echo_util.h"
|
||||
#include "ngx_http_echo_location.h"
|
||||
#include "ngx_http_echo_handler.h"
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
static ngx_int_t ngx_http_echo_adjust_subrequest(ngx_http_request_t *sr);
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_location_async(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_http_request_t *sr; /* subrequest object */
|
||||
ngx_str_t *computed_arg_elts;
|
||||
ngx_str_t location;
|
||||
ngx_str_t *url_args;
|
||||
ngx_str_t args;
|
||||
ngx_uint_t flags = 0;
|
||||
|
||||
dd_enter();
|
||||
|
||||
computed_arg_elts = computed_args->elts;
|
||||
|
||||
location = computed_arg_elts[0];
|
||||
|
||||
if (location.len == 0) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (computed_args->nelts > 1) {
|
||||
url_args = &computed_arg_elts[1];
|
||||
} else {
|
||||
url_args = NULL;
|
||||
}
|
||||
|
||||
args.data = NULL;
|
||||
args.len = 0;
|
||||
|
||||
if (ngx_http_parse_unsafe_uri(r, &location, &args, &flags) != NGX_OK) {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"echo_location_async sees unsafe uri: \"%V\"",
|
||||
&location);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (args.len > 0 && url_args == NULL) {
|
||||
url_args = &args;
|
||||
}
|
||||
|
||||
rc = ngx_http_echo_send_header_if_needed(r, ctx);
|
||||
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ngx_http_subrequest(r, &location, url_args, &sr, NULL, 0);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
rc = ngx_http_echo_adjust_subrequest(sr);
|
||||
if (rc != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_location(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_http_request_t *sr; /* subrequest object */
|
||||
ngx_str_t *computed_arg_elts;
|
||||
ngx_str_t location;
|
||||
ngx_str_t *url_args;
|
||||
ngx_http_post_subrequest_t *psr;
|
||||
ngx_str_t args;
|
||||
ngx_uint_t flags = 0;
|
||||
ngx_http_echo_ctx_t *sr_ctx;
|
||||
|
||||
if (computed_args == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
computed_arg_elts = computed_args->elts;
|
||||
|
||||
location = computed_arg_elts[0];
|
||||
|
||||
if (location.len == 0) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (computed_args->nelts > 1) {
|
||||
url_args = &computed_arg_elts[1];
|
||||
|
||||
} else {
|
||||
url_args = NULL;
|
||||
}
|
||||
|
||||
args.data = NULL;
|
||||
args.len = 0;
|
||||
|
||||
if (ngx_http_parse_unsafe_uri(r, &location, &args, &flags) != NGX_OK) {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"echo_location sees unsafe uri: \"%V\"",
|
||||
&location);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (args.len > 0 && url_args == NULL) {
|
||||
url_args = &args;
|
||||
}
|
||||
|
||||
rc = ngx_http_echo_send_header_if_needed(r, ctx);
|
||||
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
sr_ctx = ngx_http_echo_create_ctx(r);
|
||||
|
||||
psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
|
||||
if (psr == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
psr->handler = ngx_http_echo_post_subrequest;
|
||||
psr->data = sr_ctx;
|
||||
|
||||
rc = ngx_http_subrequest(r, &location, url_args, &sr, psr, 0);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
rc = ngx_http_echo_adjust_subrequest(sr);
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_echo_adjust_subrequest(ngx_http_request_t *sr)
|
||||
{
|
||||
ngx_http_core_main_conf_t *cmcf;
|
||||
ngx_http_request_t *r;
|
||||
|
||||
/* we do not inherit the parent request's variables */
|
||||
cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module);
|
||||
|
||||
r = sr->parent;
|
||||
|
||||
sr->header_in = r->header_in;
|
||||
|
||||
/* XXX work-around a bug in ngx_http_subrequest */
|
||||
if (r->headers_in.headers.last == &r->headers_in.headers.part) {
|
||||
sr->headers_in.headers.last = &sr->headers_in.headers.part;
|
||||
}
|
||||
|
||||
sr->variables = ngx_pcalloc(sr->pool, cmcf->variables.nelts
|
||||
* sizeof(ngx_http_variable_value_t));
|
||||
|
||||
if (sr->variables == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef ECHO_LOCATION_H
|
||||
#define ECHO_LOCATION_H
|
||||
|
||||
#include "ngx_http_echo_module.h"
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo_location_async(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args);
|
||||
|
||||
ngx_int_t ngx_http_echo_exec_echo_location(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args);
|
||||
|
||||
#endif /* ECHO_LOCATION_H */
|
||||
|
||||
|
|
@ -1,682 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Yichun Zhang (agentzh)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DDEBUG
|
||||
#define DDEBUG 0
|
||||
#endif
|
||||
#include "ddebug.h"
|
||||
|
||||
|
||||
#include "ngx_http_echo_handler.h"
|
||||
#include "ngx_http_echo_filter.h"
|
||||
#include "ngx_http_echo_echo.h"
|
||||
#include "ngx_http_echo_request_info.h"
|
||||
#include "ngx_http_echo_var.h"
|
||||
#include "ngx_http_echo_util.h"
|
||||
|
||||
|
||||
#include <nginx.h>
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_log.h>
|
||||
|
||||
|
||||
/* config init handler */
|
||||
static void *ngx_http_echo_create_loc_conf(ngx_conf_t *cf);
|
||||
static char *ngx_http_echo_merge_loc_conf(ngx_conf_t *cf, void *parent,
|
||||
void *child);
|
||||
static void *ngx_http_echo_create_main_conf(ngx_conf_t *cf);
|
||||
static ngx_int_t ngx_http_echo_post_config(ngx_conf_t *cf);
|
||||
|
||||
/* config directive handlers */
|
||||
static char *ngx_http_echo_echo(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_echo_echo_request_body(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_sleep(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_echo_echo_flush(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_echo_echo_blocking_sleep(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_reset_timer(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_before_body(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_after_body(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_location_async(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_location(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_subrequest_async(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_subrequest(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_duplicate(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_read_request_body(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_foreach_split(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_end(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_abort_parent(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_echo_exec(ngx_conf_t *cf,
|
||||
ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_http_echo_helper(ngx_http_echo_opcode_t opcode,
|
||||
ngx_http_echo_cmd_category_t cat,
|
||||
ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
|
||||
|
||||
static ngx_http_module_t ngx_http_echo_module_ctx = {
|
||||
NULL, /* preconfiguration */
|
||||
ngx_http_echo_post_config, /* postconfiguration */
|
||||
|
||||
ngx_http_echo_create_main_conf, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
ngx_http_echo_create_loc_conf, /* create location configuration */
|
||||
ngx_http_echo_merge_loc_conf /* merge location configuration */
|
||||
};
|
||||
|
||||
|
||||
static ngx_command_t ngx_http_echo_commands[] = {
|
||||
|
||||
{ ngx_string("echo"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY,
|
||||
ngx_http_echo_echo,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_request_body"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
|
||||
ngx_http_echo_echo_request_body,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_sleep"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
|
||||
ngx_http_echo_echo_sleep,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_flush"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
|
||||
ngx_http_echo_echo_flush,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_blocking_sleep"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
|
||||
ngx_http_echo_echo_blocking_sleep,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_reset_timer"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
|
||||
ngx_http_echo_echo_reset_timer,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_before_body"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY,
|
||||
ngx_http_echo_echo_before_body,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, before_body_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_after_body"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY,
|
||||
ngx_http_echo_echo_after_body,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, after_body_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_location_async"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12,
|
||||
ngx_http_echo_echo_location_async,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_location"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12,
|
||||
ngx_http_echo_echo_location,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_subrequest_async"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
|
||||
ngx_http_echo_echo_subrequest_async,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_subrequest"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
|
||||
ngx_http_echo_echo_subrequest,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_duplicate"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
|
||||
ngx_http_echo_echo_duplicate,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_read_request_body"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
|
||||
ngx_http_echo_echo_read_request_body,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_foreach_split"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE,
|
||||
ngx_http_echo_echo_foreach_split,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_end"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
|
||||
ngx_http_echo_echo_end,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_abort_parent"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS,
|
||||
ngx_http_echo_echo_abort_parent,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_exec"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12,
|
||||
ngx_http_echo_echo_exec,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, handler_cmds),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("echo_status"),
|
||||
NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_num_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_echo_loc_conf_t, status),
|
||||
NULL },
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_http_echo_module = {
|
||||
NGX_MODULE_V1,
|
||||
&ngx_http_echo_module_ctx, /* module context */
|
||||
ngx_http_echo_commands, /* module directives */
|
||||
NGX_HTTP_MODULE, /* module type */
|
||||
NULL, /* init master */
|
||||
NULL, /* init module */
|
||||
NULL, /* init process */
|
||||
NULL, /* init thread */
|
||||
NULL, /* exit thread */
|
||||
NULL, /* exit process */
|
||||
NULL, /* exit master */
|
||||
NGX_MODULE_V1_PADDING
|
||||
};
|
||||
|
||||
|
||||
static void *
|
||||
ngx_http_echo_create_loc_conf(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *conf;
|
||||
|
||||
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_loc_conf_t));
|
||||
if (conf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set by ngx_pcalloc
|
||||
* conf->handler_cmds = NULL
|
||||
* conf->before_body_cmds = NULL
|
||||
* conf->after_body_cmds = NULL
|
||||
* conf->seen_leading_output = 0
|
||||
* conf->seen_trailing_output = 0
|
||||
*/
|
||||
|
||||
conf->status = NGX_CONF_UNSET;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *prev = parent;
|
||||
ngx_http_echo_loc_conf_t *conf = child;
|
||||
|
||||
if (conf->handler_cmds == NULL) {
|
||||
conf->handler_cmds = prev->handler_cmds;
|
||||
conf->seen_leading_output = prev->seen_leading_output;
|
||||
}
|
||||
|
||||
if (conf->before_body_cmds == NULL) {
|
||||
conf->before_body_cmds = prev->before_body_cmds;
|
||||
}
|
||||
|
||||
if (conf->after_body_cmds == NULL) {
|
||||
conf->after_body_cmds = prev->after_body_cmds;
|
||||
}
|
||||
|
||||
ngx_conf_merge_value(conf->status, prev->status, 200);
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_helper(ngx_http_echo_opcode_t opcode,
|
||||
ngx_http_echo_cmd_category_t cat,
|
||||
ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_str_t *raw_args;
|
||||
ngx_uint_t i, n;
|
||||
ngx_array_t **args_ptr;
|
||||
ngx_array_t **cmds_ptr;
|
||||
ngx_http_echo_cmd_t *echo_cmd;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
ngx_http_script_compile_t sc;
|
||||
ngx_http_echo_main_conf_t *emcf;
|
||||
ngx_http_echo_arg_template_t *arg;
|
||||
|
||||
emcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_echo_module);
|
||||
|
||||
/* cmds_ptr points to ngx_http_echo_loc_conf_t's
|
||||
* handler_cmds, before_body_cmds, or after_body_cmds
|
||||
* array, depending on the actual offset */
|
||||
cmds_ptr = (ngx_array_t **) (((u_char *) conf) + cmd->offset);
|
||||
|
||||
if (*cmds_ptr == NULL) {
|
||||
*cmds_ptr = ngx_array_create(cf->pool, 1,
|
||||
sizeof(ngx_http_echo_cmd_t));
|
||||
|
||||
if (*cmds_ptr == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (cat == echo_handler_cmd) {
|
||||
dd("registering the content handler");
|
||||
/* register the content handler */
|
||||
clcf = ngx_http_conf_get_module_loc_conf(cf,
|
||||
ngx_http_core_module);
|
||||
|
||||
dd("registering the content handler (2)");
|
||||
clcf->handler = ngx_http_echo_handler;
|
||||
|
||||
} else {
|
||||
dd("filter used = 1");
|
||||
emcf->requires_filter = 1;
|
||||
}
|
||||
}
|
||||
|
||||
echo_cmd = ngx_array_push(*cmds_ptr);
|
||||
|
||||
if (echo_cmd == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
echo_cmd->opcode = opcode;
|
||||
|
||||
args_ptr = &echo_cmd->args;
|
||||
*args_ptr = ngx_array_create(cf->pool, 1,
|
||||
sizeof(ngx_http_echo_arg_template_t));
|
||||
|
||||
if (*args_ptr == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
raw_args = cf->args->elts;
|
||||
|
||||
/* we skip the first arg and start from the second */
|
||||
|
||||
for (i = 1 ; i < cf->args->nelts; i++) {
|
||||
arg = ngx_array_push(*args_ptr);
|
||||
|
||||
if (arg == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
arg->raw_value = raw_args[i];
|
||||
|
||||
dd("found raw arg %s", raw_args[i].data);
|
||||
|
||||
arg->lengths = NULL;
|
||||
arg->values = NULL;
|
||||
|
||||
n = ngx_http_script_variables_count(&arg->raw_value);
|
||||
|
||||
if (n > 0) {
|
||||
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
|
||||
|
||||
sc.cf = cf;
|
||||
sc.source = &arg->raw_value;
|
||||
sc.lengths = &arg->lengths;
|
||||
sc.values = &arg->values;
|
||||
sc.variables = n;
|
||||
sc.complete_lengths = 1;
|
||||
sc.complete_values = 1;
|
||||
|
||||
if (ngx_http_script_compile(&sc) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf = conf;
|
||||
|
||||
if (!elcf->seen_leading_output) {
|
||||
elcf->seen_leading_output = 1;
|
||||
}
|
||||
|
||||
dd("in echo_echo...");
|
||||
return ngx_http_echo_helper(echo_opcode_echo, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_request_body(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf = conf;
|
||||
|
||||
if (!elcf->seen_leading_output) {
|
||||
elcf->seen_leading_output = 1;
|
||||
}
|
||||
|
||||
dd("in echo_echo_request_body...");
|
||||
return ngx_http_echo_helper(echo_opcode_echo_request_body, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_sleep(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
dd("in echo_sleep...");
|
||||
return ngx_http_echo_helper(echo_opcode_echo_sleep, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_flush(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf = conf;
|
||||
|
||||
if (!elcf->seen_leading_output) {
|
||||
elcf->seen_leading_output = 1;
|
||||
}
|
||||
|
||||
dd("in echo_flush...");
|
||||
return ngx_http_echo_helper(echo_opcode_echo_flush, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_blocking_sleep(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
dd("in echo_blocking_sleep...");
|
||||
return ngx_http_echo_helper(echo_opcode_echo_blocking_sleep,
|
||||
echo_handler_cmd, cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_reset_timer(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
return ngx_http_echo_helper(echo_opcode_echo_reset_timer, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_before_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
dd("processing echo_before_body directive...");
|
||||
return ngx_http_echo_helper(echo_opcode_echo_before_body, echo_filter_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_after_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
return ngx_http_echo_helper(echo_opcode_echo_after_body, echo_filter_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_location_async(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf = conf;
|
||||
char *ret;
|
||||
|
||||
if (!elcf->seen_leading_output) {
|
||||
elcf->seen_leading_output = 1;
|
||||
|
||||
ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
|
||||
if (ret != NGX_CONF_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_http_echo_helper(echo_opcode_echo_location_async,
|
||||
echo_handler_cmd, cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_location(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf = conf;
|
||||
char *ret;
|
||||
|
||||
if (!elcf->seen_leading_output) {
|
||||
elcf->seen_leading_output = 1;
|
||||
|
||||
ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
|
||||
if (ret != NGX_CONF_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_http_echo_helper(echo_opcode_echo_location, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_subrequest_async(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
char *ret;
|
||||
ngx_http_echo_loc_conf_t *elcf = conf;
|
||||
|
||||
if (!elcf->seen_leading_output) {
|
||||
elcf->seen_leading_output = 1;
|
||||
|
||||
ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
|
||||
if (ret != NGX_CONF_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_http_echo_helper(echo_opcode_echo_subrequest_async,
|
||||
echo_handler_cmd, cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_subrequest(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf = conf;
|
||||
char *ret;
|
||||
|
||||
if (!elcf->seen_leading_output) {
|
||||
elcf->seen_leading_output = 1;
|
||||
|
||||
ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
|
||||
if (ret != NGX_CONF_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_http_echo_helper(echo_opcode_echo_subrequest, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_duplicate(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_echo_loc_conf_t *elcf = conf;
|
||||
|
||||
if (!elcf->seen_leading_output) {
|
||||
elcf->seen_leading_output = 1;
|
||||
}
|
||||
|
||||
return ngx_http_echo_helper(echo_opcode_echo_duplicate, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_read_request_body(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
return ngx_http_echo_helper(echo_opcode_echo_read_request_body,
|
||||
echo_handler_cmd, cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_foreach_split(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
return ngx_http_echo_helper(echo_opcode_echo_foreach_split,
|
||||
echo_handler_cmd, cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_end(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
return ngx_http_echo_helper(echo_opcode_echo_end, echo_handler_cmd, cf,
|
||||
cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_abort_parent(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
return ngx_http_echo_helper(echo_opcode_echo_abort_parent, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_echo_echo_exec(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
return ngx_http_echo_helper(echo_opcode_echo_exec, echo_handler_cmd,
|
||||
cf, cmd, conf);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
ngx_http_echo_create_main_conf(ngx_conf_t *cf)
|
||||
{
|
||||
#if nginx_version >= 1011011
|
||||
ngx_pool_cleanup_t *cln;
|
||||
#endif
|
||||
ngx_http_echo_main_conf_t *emcf;
|
||||
|
||||
emcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_main_conf_t));
|
||||
if (emcf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set by ngx_pcalloc:
|
||||
* hmcf->requires_filter = 0;
|
||||
*/
|
||||
|
||||
#if nginx_version >= 1011011
|
||||
cln = ngx_pool_cleanup_add(cf->pool, 0);
|
||||
if (cln == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cln->data = emcf;
|
||||
cln->handler = ngx_http_echo_request_headers_cleanup;
|
||||
#endif
|
||||
|
||||
return emcf;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_echo_post_config(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
|
||||
rc = ngx_http_echo_filter_init(cf);
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ngx_http_echo_echo_init(cf);
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
ngx_http_echo_content_length_hash =
|
||||
ngx_http_echo_hash_literal("content-length");
|
||||
|
||||
return ngx_http_echo_add_variables(cf);
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Yichun Zhang (agentzh)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef NGX_HTTP_ECHO_MODULE_H
|
||||
#define NGX_HTTP_ECHO_MODULE_H
|
||||
|
||||
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
extern ngx_module_t ngx_http_echo_module;
|
||||
|
||||
|
||||
/* config directive's opcode */
|
||||
typedef enum {
|
||||
echo_opcode_echo_sync,
|
||||
echo_opcode_echo,
|
||||
echo_opcode_echo_request_body,
|
||||
echo_opcode_echo_sleep,
|
||||
echo_opcode_echo_flush,
|
||||
echo_opcode_echo_blocking_sleep,
|
||||
echo_opcode_echo_reset_timer,
|
||||
echo_opcode_echo_before_body,
|
||||
echo_opcode_echo_after_body,
|
||||
echo_opcode_echo_location_async,
|
||||
echo_opcode_echo_location,
|
||||
echo_opcode_echo_subrequest_async,
|
||||
echo_opcode_echo_subrequest,
|
||||
echo_opcode_echo_duplicate,
|
||||
echo_opcode_echo_read_request_body,
|
||||
echo_opcode_echo_foreach_split,
|
||||
echo_opcode_echo_end,
|
||||
echo_opcode_echo_abort_parent,
|
||||
echo_opcode_echo_exec
|
||||
} ngx_http_echo_opcode_t;
|
||||
|
||||
|
||||
/* all the various config directives (or commands) are
|
||||
* divided into two categories: "handler commands",
|
||||
* and "filter commands". For instance, the "echo"
|
||||
* directive is a handler command while
|
||||
* "echo_before_body" is a filter one. */
|
||||
typedef enum {
|
||||
echo_handler_cmd,
|
||||
echo_filter_cmd
|
||||
|
||||
} ngx_http_echo_cmd_category_t;
|
||||
|
||||
|
||||
/* compiled form of a config directive argument's value */
|
||||
typedef struct {
|
||||
/* holds the raw string of the argument value */
|
||||
ngx_str_t raw_value;
|
||||
|
||||
/* fields "lengths" and "values" are set by
|
||||
* the function ngx_http_script_compile,
|
||||
* iff the argument value indeed contains
|
||||
* nginx variables like "$foo" */
|
||||
ngx_array_t *lengths;
|
||||
ngx_array_t *values;
|
||||
|
||||
} ngx_http_echo_arg_template_t;
|
||||
|
||||
|
||||
/* represent a config directive (or command) like "echo". */
|
||||
typedef struct {
|
||||
ngx_http_echo_opcode_t opcode;
|
||||
|
||||
/* each argument is of type echo_arg_template_t: */
|
||||
ngx_array_t *args;
|
||||
} ngx_http_echo_cmd_t;
|
||||
|
||||
|
||||
/* location config struct */
|
||||
typedef struct {
|
||||
/* elements of the following arrays are of type
|
||||
* ngx_http_echo_cmd_t */
|
||||
ngx_array_t *handler_cmds;
|
||||
ngx_array_t *before_body_cmds;
|
||||
ngx_array_t *after_body_cmds;
|
||||
|
||||
unsigned seen_leading_output;
|
||||
|
||||
ngx_int_t status;
|
||||
} ngx_http_echo_loc_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_int_t requires_filter;
|
||||
#if nginx_version >= 1011011
|
||||
ngx_buf_t **busy_buf_ptrs;
|
||||
ngx_int_t busy_buf_ptr_count;
|
||||
#endif
|
||||
} ngx_http_echo_main_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_array_t *choices; /* items after splitting */
|
||||
ngx_uint_t next_choice; /* current item index */
|
||||
ngx_uint_t cmd_index; /* cmd index for the echo_foreach direcitve */
|
||||
} ngx_http_echo_foreach_ctx_t;
|
||||
|
||||
|
||||
/* context struct in the request handling cycle, holding
|
||||
* the current states of the command evaluator */
|
||||
typedef struct {
|
||||
/* index of the next handler command in
|
||||
* ngx_http_echo_loc_conf_t's "handler_cmds" array. */
|
||||
ngx_uint_t next_handler_cmd;
|
||||
|
||||
/* index of the next before-body filter command in
|
||||
* ngx_http_echo_loc_conf_t's "before_body_cmds" array. */
|
||||
ngx_uint_t next_before_body_cmd;
|
||||
|
||||
/* index of the next after-body filter command in
|
||||
* ngx_http_echo_loc_conf_t's "after_body_cmds" array. */
|
||||
ngx_uint_t next_after_body_cmd;
|
||||
|
||||
ngx_http_echo_foreach_ctx_t *foreach;
|
||||
|
||||
ngx_time_t timer_begin;
|
||||
|
||||
ngx_event_t sleep;
|
||||
|
||||
ngx_uint_t counter;
|
||||
|
||||
unsigned before_body_sent:1;
|
||||
unsigned skip_filter:1;
|
||||
|
||||
unsigned wait_read_request_body:1;
|
||||
|
||||
unsigned waiting:1;
|
||||
unsigned done:1;
|
||||
|
||||
unsigned run_post_subrequest:1;
|
||||
unsigned header_sent:1; /* r->header_sent is not sufficient
|
||||
* because special header filters like
|
||||
* ngx_http_image_filter_module's may
|
||||
* intercept the whole header filter chain
|
||||
* leaving r->header_sent unset. So we
|
||||
* should always test both flags. */
|
||||
|
||||
} ngx_http_echo_ctx_t;
|
||||
|
||||
|
||||
#endif /* NGX_HTTP_ECHO_MODULE_H */
|
||||
|
|
@ -1,522 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) Yichun Zhang (agentzh)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DDEBUG
|
||||
#define DDEBUG 0
|
||||
#endif
|
||||
#include "ddebug.h"
|
||||
|
||||
#include "ngx_http_echo_request_info.h"
|
||||
#include "ngx_http_echo_util.h"
|
||||
#include "ngx_http_echo_handler.h"
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
static void ngx_http_echo_post_read_request_body(ngx_http_request_t *r);
|
||||
#if nginx_version >= 1011011
|
||||
void ngx_http_echo_request_headers_cleanup(void *data);
|
||||
#endif
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_exec_echo_read_request_body(ngx_http_request_t *r,
|
||||
ngx_http_echo_ctx_t *ctx)
|
||||
{
|
||||
return ngx_http_read_client_request_body(r,
|
||||
ngx_http_echo_post_read_request_body);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_echo_post_read_request_body(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_http_echo_ctx_t *ctx;
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module);
|
||||
|
||||
dd("wait read request body %d", (int) ctx->wait_read_request_body);
|
||||
|
||||
if (ctx->wait_read_request_body) {
|
||||
ctx->waiting = 0;
|
||||
ctx->done = 1;
|
||||
|
||||
r->write_event_handler = ngx_http_echo_wev_handler;
|
||||
|
||||
ngx_http_echo_wev_handler(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* this function's implementation is borrowed from nginx 0.8.20
|
||||
* and modified a bit to work with subrequests.
|
||||
* Copyrighted (C) by Igor Sysoev */
|
||||
ngx_int_t
|
||||
ngx_http_echo_request_method_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
if (r->method_name.data) {
|
||||
v->len = r->method_name.len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
v->data = r->method_name.data;
|
||||
|
||||
} else {
|
||||
v->not_found = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
/* this function's implementation is borrowed from nginx 0.8.20
|
||||
* and modified a bit to work with subrequests.
|
||||
* Copyrighted (C) by Igor Sysoev */
|
||||
ngx_int_t
|
||||
ngx_http_echo_client_request_method_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
if (r->main->method_name.data) {
|
||||
v->len = r->main->method_name.len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
v->data = r->main->method_name.data;
|
||||
|
||||
} else {
|
||||
v->not_found = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
/* this function's implementation is borrowed from nginx 0.8.20
|
||||
* and modified a bit to work with subrequests.
|
||||
* Copyrighted (C) by Igor Sysoev */
|
||||
ngx_int_t
|
||||
ngx_http_echo_request_body_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
u_char *p;
|
||||
size_t len;
|
||||
ngx_buf_t *b;
|
||||
ngx_chain_t *cl;
|
||||
ngx_chain_t *in;
|
||||
|
||||
if (r->request_body == NULL
|
||||
|| r->request_body->bufs == NULL
|
||||
|| r->request_body->temp_file)
|
||||
{
|
||||
v->not_found = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
in = r->request_body->bufs;
|
||||
|
||||
len = 0;
|
||||
for (cl = in; cl; cl = cl->next) {
|
||||
b = cl->buf;
|
||||
|
||||
if (!ngx_buf_in_memory(b)) {
|
||||
if (b->in_file) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"variable echo_request_body sees in-file only "
|
||||
"buffers and discard the whole body data");
|
||||
|
||||
v->not_found = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
} else {
|
||||
len += b->last - b->pos;
|
||||
}
|
||||
}
|
||||
|
||||
p = ngx_pnalloc(r->pool, len);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
v->data = p;
|
||||
|
||||
for (cl = in; cl; cl = cl->next) {
|
||||
b = cl->buf;
|
||||
|
||||
if (ngx_buf_in_memory(b)) {
|
||||
p = ngx_copy(p, b->pos, b->last - b->pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (p - v->data != (ssize_t) len) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"variable echo_request_body: buffer error");
|
||||
|
||||
v->not_found = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
v->len = len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
int line_break_len;
|
||||
size_t size;
|
||||
u_char *p, *last, *pos;
|
||||
ngx_int_t i, j;
|
||||
ngx_buf_t *b, *first = NULL;
|
||||
unsigned found;
|
||||
#if nginx_version >= 1011011
|
||||
ngx_buf_t **bb;
|
||||
ngx_chain_t *cl;
|
||||
ngx_http_echo_main_conf_t *emcf;
|
||||
#endif
|
||||
ngx_connection_t *c;
|
||||
ngx_http_request_t *mr;
|
||||
ngx_http_connection_t *hc;
|
||||
|
||||
mr = r->main;
|
||||
hc = r->main->http_connection;
|
||||
c = mr->connection;
|
||||
|
||||
#if (NGX_HTTP_V2)
|
||||
/* TODO */
|
||||
if (mr->stream) {
|
||||
v->not_found = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if nginx_version >= 1011011
|
||||
emcf = ngx_http_get_module_main_conf(r, ngx_http_echo_module);
|
||||
#endif
|
||||
|
||||
size = 0;
|
||||
b = c->buffer;
|
||||
|
||||
if (mr->request_line.data[mr->request_line.len] == CR) {
|
||||
line_break_len = 2;
|
||||
|
||||
} else {
|
||||
line_break_len = 1;
|
||||
}
|
||||
|
||||
if (mr->request_line.data >= b->start
|
||||
&& mr->request_line.data + mr->request_line.len + line_break_len
|
||||
<= b->pos)
|
||||
{
|
||||
first = b;
|
||||
size += b->pos - mr->request_line.data;
|
||||
}
|
||||
|
||||
if (hc->nbusy) {
|
||||
b = NULL;
|
||||
|
||||
#if nginx_version >= 1011011
|
||||
if (hc->nbusy > emcf->busy_buf_ptr_count) {
|
||||
if (emcf->busy_buf_ptrs) {
|
||||
ngx_free(emcf->busy_buf_ptrs);
|
||||
}
|
||||
|
||||
emcf->busy_buf_ptrs = ngx_alloc(hc->nbusy * sizeof(ngx_buf_t *),
|
||||
r->connection->log);
|
||||
|
||||
if (emcf->busy_buf_ptrs == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
emcf->busy_buf_ptr_count = hc->nbusy;
|
||||
}
|
||||
|
||||
bb = emcf->busy_buf_ptrs;
|
||||
for (cl = hc->busy; cl; cl = cl->next) {
|
||||
*bb++ = cl->buf;
|
||||
}
|
||||
|
||||
bb = emcf->busy_buf_ptrs;
|
||||
for (i = hc->nbusy; i > 0; i--) {
|
||||
b = bb[i - 1];
|
||||
#else
|
||||
for (i = 0; i < hc->nbusy; i++) {
|
||||
b = hc->busy[i];
|
||||
#endif
|
||||
|
||||
if (first == NULL) {
|
||||
if (mr->request_line.data >= b->pos
|
||||
|| mr->request_line.data + mr->request_line.len
|
||||
+ line_break_len <= b->start)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
dd("found first at %d", (int) i);
|
||||
first = b;
|
||||
}
|
||||
|
||||
size += b->pos - b->start;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size++; /* plus the null terminator, as required by the later
|
||||
ngx_strstr() call */
|
||||
|
||||
v->data = ngx_palloc(r->pool, size);
|
||||
if (v->data == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
last = v->data;
|
||||
|
||||
b = c->buffer;
|
||||
found = 0;
|
||||
|
||||
if (first == b) {
|
||||
found = 1;
|
||||
pos = b->pos;
|
||||
|
||||
last = ngx_copy(v->data, mr->request_line.data,
|
||||
pos - mr->request_line.data);
|
||||
|
||||
if (b != mr->header_in) {
|
||||
/* skip truncated header entries (if any) */
|
||||
while (last > v->data && last[-1] != LF) {
|
||||
last--;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (p = v->data; p != last; p++) {
|
||||
if (*p == '\0') {
|
||||
i++;
|
||||
if (p + 1 != last && *(p + 1) == LF) {
|
||||
*p = CR;
|
||||
|
||||
} else if (i % 2 == 1) {
|
||||
*p = ':';
|
||||
|
||||
} else {
|
||||
*p = LF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hc->nbusy) {
|
||||
|
||||
#if nginx_version >= 1011011
|
||||
bb = emcf->busy_buf_ptrs;
|
||||
for (i = hc->nbusy; i > 0; i--) {
|
||||
b = bb[i - 1];
|
||||
#else
|
||||
for (i = 0; i < hc->nbusy; i++) {
|
||||
b = hc->busy[i];
|
||||
#endif
|
||||
|
||||
if (!found) {
|
||||
if (b != first) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dd("found first");
|
||||
found = 1;
|
||||
}
|
||||
|
||||
p = last;
|
||||
|
||||
pos = b->pos;
|
||||
|
||||
if (b == first) {
|
||||
dd("request line: %.*s", (int) mr->request_line.len,
|
||||
mr->request_line.data);
|
||||
|
||||
last = ngx_copy(last,
|
||||
mr->request_line.data,
|
||||
pos - mr->request_line.data);
|
||||
|
||||
} else {
|
||||
last = ngx_copy(last, b->start, pos - b->start);
|
||||
}
|
||||
|
||||
#if 1
|
||||
/* skip truncated header entries (if any) */
|
||||
while (last > p && last[-1] != LF) {
|
||||
last--;
|
||||
}
|
||||
#endif
|
||||
|
||||
j = 0;
|
||||
for (; p != last; p++) {
|
||||
if (*p == '\0') {
|
||||
j++;
|
||||
if (p + 1 == last) {
|
||||
/* XXX this should not happen */
|
||||
dd("found string end!!");
|
||||
|
||||
} else if (*(p + 1) == LF) {
|
||||
*p = CR;
|
||||
|
||||
} else if (j % 2 == 1) {
|
||||
*p = ':';
|
||||
|
||||
} else {
|
||||
*p = LF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (b == mr->header_in) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*last++ = '\0';
|
||||
|
||||
if (last - v->data > (ssize_t) size) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"buffer error when evaluating "
|
||||
"$echo_client__request_headers: \"%V\"",
|
||||
(ngx_int_t) (last - v->data - size));
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* strip the leading part (if any) of the request body in our header.
|
||||
* the first part of the request body could slip in because nginx core's
|
||||
* ngx_http_request_body_length_filter and etc can move r->header_in->pos
|
||||
* in case that some of the body data has been preread into r->header_in.
|
||||
*/
|
||||
|
||||
if ((p = (u_char *) ngx_strstr(v->data, CRLF CRLF)) != NULL) {
|
||||
last = p + sizeof(CRLF CRLF) - 1;
|
||||
|
||||
} else if ((p = (u_char *) ngx_strstr(v->data, CRLF "\n")) != NULL) {
|
||||
last = p + sizeof(CRLF "\n") - 1;
|
||||
|
||||
} else if ((p = (u_char *) ngx_strstr(v->data, "\n" CRLF)) != NULL) {
|
||||
last = p + sizeof("\n" CRLF) - 1;
|
||||
|
||||
} else {
|
||||
for (p = last - 1; p - v->data >= 2; p--) {
|
||||
if (p[0] == LF && p[-1] == CR) {
|
||||
p[-1] = LF;
|
||||
last = p + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p[0] == LF && p[-1] == LF) {
|
||||
last = p + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v->len = last - v->data;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_cacheable_request_uri_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
if (r->uri.len) {
|
||||
v->len = r->uri.len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 0;
|
||||
v->not_found = 0;
|
||||
v->data = r->uri.data;
|
||||
|
||||
} else {
|
||||
v->not_found = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_request_uri_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
if (r->uri.len) {
|
||||
v->len = r->uri.len;
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 1;
|
||||
v->not_found = 0;
|
||||
v->data = r->uri.data;
|
||||
|
||||
} else {
|
||||
v->not_found = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_echo_response_status_variable(ngx_http_request_t *r,
|
||||
ngx_http_variable_value_t *v, uintptr_t data)
|
||||
{
|
||||
u_char *p;
|
||||
|
||||
if (r->headers_out.status) {
|
||||
dd("headers out status: %d", (int) r->headers_out.status);
|
||||
|
||||
p = ngx_palloc(r->pool, NGX_INT_T_LEN);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
v->len = ngx_sprintf(p, "%ui", r->headers_out.status) - p;
|
||||
v->data = p;
|
||||
|
||||
v->valid = 1;
|
||||
v->no_cacheable = 1;
|
||||
v->not_found = 0;
|
||||
|
||||
} else {
|
||||
v->not_found = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
#if nginx_version >= 1011011
|
||||
void
|
||||
ngx_http_echo_request_headers_cleanup(void *data)
|
||||
{
|
||||
ngx_http_echo_main_conf_t *emcf;
|
||||
|
||||
emcf = (ngx_http_echo_main_conf_t *) data;
|
||||
|
||||
if (emcf->busy_buf_ptrs) {
|
||||
ngx_free(emcf->busy_buf_ptrs);
|
||||
emcf->busy_buf_ptrs = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue