add two moudles
This commit is contained in:
40
README.md
40
README.md
@@ -63,6 +63,25 @@ BSD 2-Clause License.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## ngx_headers_more
|
||||||
|
|
||||||
|
ngx_headers_more - Set and clear input and output headers...more than "add"!
|
||||||
|
|
||||||
|
This module is not distributed with the Nginx source.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./configure \
|
||||||
|
--add-dynamic-module=/path/to/ngx_headers_more
|
||||||
|
```
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
BSD 2-Clause License.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## ngx_http_flv_module
|
## ngx_http_flv_module
|
||||||
|
|
||||||
HTTP-FLV / RTMP / HLS streaming server module for Nginx.
|
HTTP-FLV / RTMP / HLS streaming server module for Nginx.
|
||||||
@@ -177,4 +196,25 @@ when compiled with --with-debug, this module will produce high number of log mes
|
|||||||
|
|
||||||
### License
|
### License
|
||||||
|
|
||||||
|
BSD 2-Clause License.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ngx_zstd
|
||||||
|
|
||||||
|
zstd-nginx-module - Nginx module for the [Zstandard compression](https://facebook.github.io/zstd/).
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./configure \
|
||||||
|
--add-module=/path/to/ngx_zstd
|
||||||
|
```
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
u should add as static module
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
BSD 2-Clause License.
|
BSD 2-Clause License.
|
||||||
1
ngx_headers_more/.gitattributes
vendored
Normal file
1
ngx_headers_more/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.t linguist-language=Text
|
||||||
54
ngx_headers_more/.gitignore
vendored
Normal file
54
ngx_headers_more/.gitignore
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
reindex
|
||||||
|
.libs
|
||||||
|
*.swp
|
||||||
|
*.slo
|
||||||
|
*.la
|
||||||
|
*.swo
|
||||||
|
*.lo
|
||||||
|
*~
|
||||||
|
*.o
|
||||||
|
print.txt
|
||||||
|
.rsync
|
||||||
|
*.tar.gz
|
||||||
|
dist
|
||||||
|
build[78]
|
||||||
|
build
|
||||||
|
tags
|
||||||
|
update-readme
|
||||||
|
*.tmp
|
||||||
|
test/Makefile
|
||||||
|
test/blib
|
||||||
|
test.sh
|
||||||
|
t.sh
|
||||||
|
t/t.sh
|
||||||
|
test/t/servroot/
|
||||||
|
releng
|
||||||
|
reset
|
||||||
|
*.t_
|
||||||
|
genmobi.sh
|
||||||
|
*.mobi
|
||||||
|
misc/chunked
|
||||||
|
src/headers.c
|
||||||
|
src/headers.h
|
||||||
|
src/module.c
|
||||||
|
src/module.h
|
||||||
|
src/util.c
|
||||||
|
src/util.h
|
||||||
|
go
|
||||||
|
ctags
|
||||||
|
src/in.c
|
||||||
|
src/in.h
|
||||||
|
src/out.c
|
||||||
|
src/out.h
|
||||||
|
build[89]
|
||||||
|
build1[0-9]
|
||||||
|
buildroot/
|
||||||
|
work/
|
||||||
|
all
|
||||||
|
t/servroot
|
||||||
|
analyze
|
||||||
|
cov
|
||||||
|
nginx
|
||||||
|
*.plist
|
||||||
|
a.patch
|
||||||
|
Makefile
|
||||||
65
ngx_headers_more/.travis.yml
Normal file
65
ngx_headers_more/.travis.yml
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
sudo: required
|
||||||
|
dist: focal
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- "master"
|
||||||
|
|
||||||
|
os: linux
|
||||||
|
|
||||||
|
language: c
|
||||||
|
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- axel
|
||||||
|
- cpanminus
|
||||||
|
|
||||||
|
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
|
||||||
|
- PCRE_PREFIX=/usr/local/openresty/pcre2
|
||||||
|
- PCRE_LIB=$PCRE_PREFIX/lib
|
||||||
|
- PCRE_INC=$PCRE_PREFIX/include
|
||||||
|
matrix:
|
||||||
|
- NGINX_VERSION=1.29.8
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get update -y
|
||||||
|
- sudo apt-get install -y ca-certificates
|
||||||
|
- sudo cpanm --notest Test::Nginx IPC::Run Test2::Util > build.log 2>&1 || (cat build.log && exit 1)
|
||||||
|
- sudo cpanm -v --notest Test::Nginx > build.log 2>&1 || (cat build.log && exit 1)
|
||||||
|
- wget -O - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
|
||||||
|
- echo "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends openresty-pcre2 openresty-openssl3 openresty-pcre2-dev openresty-openssl3-dev
|
||||||
|
|
||||||
|
install:
|
||||||
|
- git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module
|
||||||
|
- git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module
|
||||||
|
- 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 ../eval-nginx-module
|
||||||
|
- git clone https://github.com/openresty/openresty.git ../openresty
|
||||||
|
- git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx
|
||||||
|
- git clone https://github.com/openresty/nginx-devel-utils.git
|
||||||
|
- git clone -b v2.1-agentzh https://github.com/openresty/luajit2.git luajit2
|
||||||
|
|
||||||
|
before_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 ..
|
||||||
|
|
||||||
|
script:
|
||||||
|
- export PATH=$PWD/work/nginx/sbin:$PWD/nginx-devel-utils:$PATH
|
||||||
|
- export NGX_BUILD_CC=$CC
|
||||||
|
- sh util/build.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1)
|
||||||
|
- prove -I. -r t
|
||||||
|
|
||||||
20
ngx_headers_more/LICENSE
Normal file
20
ngx_headers_more/LICENSE
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
This module is licensed under the terms of the BSD license.
|
||||||
|
|
||||||
|
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.
|
||||||
541
ngx_headers_more/README.markdown
Normal file
541
ngx_headers_more/README.markdown
Normal file
@@ -0,0 +1,541 @@
|
|||||||
|
Name
|
||||||
|
====
|
||||||
|
|
||||||
|
**ngx_headers_more** - Set and clear input and output headers...more than "add"!
|
||||||
|
|
||||||
|
*This module is not distributed with the Nginx source.* See [the installation instructions](#installation).
|
||||||
|
|
||||||
|
Table of Contents
|
||||||
|
=================
|
||||||
|
|
||||||
|
* [Name](#name)
|
||||||
|
* [Version](#version)
|
||||||
|
* [Synopsis](#synopsis)
|
||||||
|
* [Description](#description)
|
||||||
|
* [Directives](#directives)
|
||||||
|
* [more_set_headers](#more_set_headers)
|
||||||
|
* [more_clear_headers](#more_clear_headers)
|
||||||
|
* [more_set_input_headers](#more_set_input_headers)
|
||||||
|
* [more_clear_input_headers](#more_clear_input_headers)
|
||||||
|
* [Limitations](#limitations)
|
||||||
|
* [Installation](#installation)
|
||||||
|
* [Compatibility](#compatibility)
|
||||||
|
* [Community](#community)
|
||||||
|
* [English Mailing List](#english-mailing-list)
|
||||||
|
* [Chinese Mailing List](#chinese-mailing-list)
|
||||||
|
* [Bugs and Patches](#bugs-and-patches)
|
||||||
|
* [Source Repository](#source-repository)
|
||||||
|
* [Changes](#changes)
|
||||||
|
* [Test Suite](#test-suite)
|
||||||
|
* [TODO](#todo)
|
||||||
|
* [Getting involved](#getting-involved)
|
||||||
|
* [Authors](#authors)
|
||||||
|
* [Copyright & License](#copyright--license)
|
||||||
|
* [See Also](#see-also)
|
||||||
|
|
||||||
|
Version
|
||||||
|
=======
|
||||||
|
|
||||||
|
This document describes headers-more-nginx-module [v0.34](https://github.com/openresty/headers-more-nginx-module/tags) released on 17 July 2022.
|
||||||
|
|
||||||
|
Synopsis
|
||||||
|
========
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
# set the Server output header
|
||||||
|
more_set_headers 'Server: my-server';
|
||||||
|
|
||||||
|
# set and clear output headers
|
||||||
|
location /bar {
|
||||||
|
more_set_headers 'X-MyHeader: blah' 'X-MyHeader2: foo';
|
||||||
|
more_set_headers -t 'text/plain text/css' 'Content-Type: text/foo';
|
||||||
|
more_set_headers -s '400 404 500 503' -s 413 'Foo: Bar';
|
||||||
|
more_clear_headers 'Content-Type';
|
||||||
|
|
||||||
|
# your proxy_pass/memcached_pass/or any other config goes here...
|
||||||
|
}
|
||||||
|
|
||||||
|
# set output headers
|
||||||
|
location /type {
|
||||||
|
more_set_headers 'Content-Type: text/plain';
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
|
||||||
|
# set input headers
|
||||||
|
location /foo {
|
||||||
|
set $my_host 'my dog';
|
||||||
|
more_set_input_headers 'Host: $my_host';
|
||||||
|
more_set_input_headers -t 'text/plain' 'X-Foo: bah';
|
||||||
|
|
||||||
|
# now $host and $http_host have their new values...
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
|
||||||
|
# replace input header X-Foo *only* if it already exists
|
||||||
|
more_set_input_headers -r 'X-Foo: howdy';
|
||||||
|
```
|
||||||
|
|
||||||
|
Description
|
||||||
|
===========
|
||||||
|
|
||||||
|
This module allows you to add, set, or clear any output
|
||||||
|
or input header that you specify.
|
||||||
|
|
||||||
|
This is an enhanced version of the standard
|
||||||
|
[headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module because it provides more utilities like
|
||||||
|
resetting or clearing "builtin headers" like `Content-Type`,
|
||||||
|
`Content-Length`, and `Server`.
|
||||||
|
|
||||||
|
It also allows you to specify an optional HTTP status code
|
||||||
|
criteria using the `-s` option and an optional content
|
||||||
|
type criteria using the `-t` option while modifying the
|
||||||
|
output headers with the [more_set_headers](#more_set_headers) and
|
||||||
|
[more_clear_headers](#more_clear_headers) directives. For example,
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
more_set_headers -s 404 -t 'text/html' 'X-Foo: Bar';
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also specify multiple MIME types to filter out in a single `-t` option.
|
||||||
|
For example,
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
more_set_headers -t 'text/html text/plain' 'X-Foo: Bar';
|
||||||
|
```
|
||||||
|
|
||||||
|
Never use other parameters like `charset=utf-8` in the `-t` option values; they will not
|
||||||
|
work as you would expect.
|
||||||
|
|
||||||
|
Input headers can be modified as well. For example
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location /foo {
|
||||||
|
more_set_input_headers 'Host: foo' 'User-Agent: faked';
|
||||||
|
# now $host, $http_host, $user_agent, and
|
||||||
|
# $http_user_agent all have their new values.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The option `-t` is also available in the
|
||||||
|
[more_set_input_headers](#more_set_input_headers) and
|
||||||
|
[more_clear_input_headers](#more_clear_input_headers) directives (for request header filtering) while the `-s` option
|
||||||
|
is not allowed.
|
||||||
|
|
||||||
|
Unlike the standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module, this module's directives will by
|
||||||
|
default apply to all the status codes, including `4xx` and `5xx`.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Directives
|
||||||
|
==========
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
more_set_headers
|
||||||
|
----------------
|
||||||
|
**syntax:** *more_set_headers [-t <content-type list>]... [-s <status-code list>]... [-a] <new-header>...*
|
||||||
|
|
||||||
|
**default:** *no*
|
||||||
|
|
||||||
|
**context:** *http, server, location, location if*
|
||||||
|
|
||||||
|
**phase:** *output-header-filter*
|
||||||
|
|
||||||
|
Replaces (if any) or adds (if not any) the specified output headers when the response status code matches the codes specified by the `-s` option *AND* the response content type matches the types specified by the `-t` option.
|
||||||
|
|
||||||
|
If the "-a" option is specified, the specified output headers can be appended directly without clearing the old fields. The behavior of builtin headers such as "Content-Type", "Content-Length", "Server", etc. cannot be changed.
|
||||||
|
|
||||||
|
If either `-s` or `-t` is not specified or has an empty list value, then no match is required. Therefore, the following directive set the `Server` output header to the custom value for *any* status code and *any* content type:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_set_headers "Server: my_server";
|
||||||
|
```
|
||||||
|
|
||||||
|
Existing response headers with the same name are always overridden. If you want to add headers incrementally, use the standard [add_header](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header) directive instead.
|
||||||
|
|
||||||
|
A single directive can set/add multiple output headers. For example
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_set_headers 'Foo: bar' 'Baz: bah';
|
||||||
|
```
|
||||||
|
|
||||||
|
Multiple occurrences of the options are allowed in a single directive. Their values will be merged together. For instance
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_set_headers -s 404 -s '500 503' 'Foo: bar';
|
||||||
|
```
|
||||||
|
|
||||||
|
is equivalent to
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_set_headers -s '404 500 503' 'Foo: bar';
|
||||||
|
```
|
||||||
|
|
||||||
|
The new header should be the one of the forms:
|
||||||
|
|
||||||
|
1. `Name: Value`
|
||||||
|
1. `Name: `
|
||||||
|
1. `Name`
|
||||||
|
|
||||||
|
The last two effectively clear the value of the header `Name`.
|
||||||
|
|
||||||
|
Nginx variables are allowed in header values. For example:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
set $my_var "dog";
|
||||||
|
more_set_headers "Server: $my_var";
|
||||||
|
```
|
||||||
|
|
||||||
|
But variables won't work in header keys due to performance considerations.
|
||||||
|
|
||||||
|
Multiple set/clear header directives are allowed in a single location, and they're executed sequentially.
|
||||||
|
|
||||||
|
Directives inherited from an upper level scope (say, http block or server blocks) are executed before the directives in the location block.
|
||||||
|
|
||||||
|
Note that although `more_set_headers` is allowed in *location* if blocks, it is *not* allowed in the *server* if blocks, as in
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
? # This is NOT allowed!
|
||||||
|
? server {
|
||||||
|
? if ($args ~ 'download') {
|
||||||
|
? more_set_headers 'Foo: Bar';
|
||||||
|
? }
|
||||||
|
? ...
|
||||||
|
? }
|
||||||
|
```
|
||||||
|
|
||||||
|
Behind the scene, use of this directive and its friend [more_clear_headers](#more_clear_headers) will (lazily) register an ouput header filter that modifies `r->headers_out` the way you specify.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
more_clear_headers
|
||||||
|
------------------
|
||||||
|
**syntax:** *more_clear_headers [-t <content-type list>]... [-s <status-code list>]... <new-header>...*
|
||||||
|
|
||||||
|
**default:** *no*
|
||||||
|
|
||||||
|
**context:** *http, server, location, location if*
|
||||||
|
|
||||||
|
**phase:** *output-header-filter*
|
||||||
|
|
||||||
|
Clears the specified output headers.
|
||||||
|
|
||||||
|
In fact,
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_clear_headers -s 404 -t 'text/plain' Foo Baz;
|
||||||
|
```
|
||||||
|
|
||||||
|
is exactly equivalent to
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_set_headers -s 404 -t 'text/plain' "Foo: " "Baz: ";
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_set_headers -s 404 -t 'text/plain' Foo Baz;
|
||||||
|
```
|
||||||
|
|
||||||
|
See [more_set_headers](#more_set_headers) for more details.
|
||||||
|
|
||||||
|
The wildcard character, `*`, can also be used at the end of the header name to specify a pattern. For example, the following directive
|
||||||
|
effectively clears *any* output headers starting by "`X-Hidden-`":
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_clear_headers 'X-Hidden-*';
|
||||||
|
```
|
||||||
|
|
||||||
|
The `*` wildcard support was first introduced in [v0.09](#v009).
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
more_set_input_headers
|
||||||
|
----------------------
|
||||||
|
**syntax:** *more_set_input_headers [-r] [-t <content-type list>]... <new-header>...*
|
||||||
|
|
||||||
|
**default:** *no*
|
||||||
|
|
||||||
|
**context:** *http, server, location, location if*
|
||||||
|
|
||||||
|
**phase:** *rewrite tail*
|
||||||
|
|
||||||
|
Very much like [more_set_headers](#more_set_headers) except that it operates on input headers (or request headers) and it only supports the `-t` option.
|
||||||
|
|
||||||
|
Note that using the `-t` option in this directive means filtering by the `Content-Type` *request* header, rather than the response header.
|
||||||
|
|
||||||
|
Behind the scene, use of this directive and its friend [more_clear_input_headers](#more_clear_input_headers) will (lazily)
|
||||||
|
register a `rewrite phase` handler that modifies `r->headers_in` the way you specify. Note that it always run at the *end* of
|
||||||
|
the `rewrite` phase so that it runs *after* the standard [rewrite module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html)
|
||||||
|
and works in subrequests as well.
|
||||||
|
|
||||||
|
If the `-r` option is specified, then the headers will be replaced to the new values *only if* they already exist.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
more_clear_input_headers
|
||||||
|
------------------------
|
||||||
|
**syntax:** *more_clear_input_headers [-t <content-type list>]... <new-header>...*
|
||||||
|
|
||||||
|
**default:** *no*
|
||||||
|
|
||||||
|
**context:** *http, server, location, location if*
|
||||||
|
|
||||||
|
**phase:** *rewrite tail*
|
||||||
|
|
||||||
|
Clears the specified input headers.
|
||||||
|
|
||||||
|
In fact,
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_clear_input_headers -t 'text/plain' Foo Baz;
|
||||||
|
```
|
||||||
|
|
||||||
|
is exactly equivalent to
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_set_input_headers -t 'text/plain' "Foo: " "Baz: ";
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_set_input_headers -t 'text/plain' Foo Baz
|
||||||
|
```
|
||||||
|
|
||||||
|
To remove request headers "Foo" and "Baz" for all incoming requests regardless of the content type, we can write
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_clear_input_headers "Foo" "Baz";
|
||||||
|
```
|
||||||
|
|
||||||
|
See [more_set_input_headers](#more_set_input_headers) for more details.
|
||||||
|
|
||||||
|
The wildcard character, `*`, can also be used at the end of the header name to specify a pattern. For example, the following directive
|
||||||
|
effectively clears *any* input headers starting by "`X-Hidden-`":
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
more_clear_input_headers 'X-Hidden-*';
|
||||||
|
```
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Limitations
|
||||||
|
===========
|
||||||
|
|
||||||
|
* Unlike the standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module, this module does not automatically take care of the constraint among the `Expires`, `Cache-Control`, and `Last-Modified` headers. You have to get them right yourself or use the [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module together with this module.
|
||||||
|
* You cannot remove the `Connection` response header using this module because the `Connection` response header is generated by the standard `ngx_http_header_filter_module` in the Nginx core, whose output header filter runs always *after* the filter of this module. The only way to actually remove the `Connection` header is to patch the Nginx core, that is, editing the C function `ngx_http_header_filter` in the `src/http/ngx_http_header_filter_module.c` file.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
Grab the nginx source code from [nginx.org](http://nginx.org/), for example,
|
||||||
|
the version 1.17.8 (see [nginx compatibility](#compatibility)), and then build the source with this module:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
wget 'http://nginx.org/download/nginx-1.17.8.tar.gz'
|
||||||
|
tar -xzvf nginx-1.17.8.tar.gz
|
||||||
|
cd nginx-1.17.8/
|
||||||
|
|
||||||
|
# Here we assume you would install you nginx under /opt/nginx/.
|
||||||
|
./configure --prefix=/opt/nginx \
|
||||||
|
--add-module=/path/to/headers-more-nginx-module
|
||||||
|
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
|
Download the latest version of the release tarball of this module from [headers-more-nginx-module file list](https://github.com/openresty/headers-more-nginx-module/tags).
|
||||||
|
|
||||||
|
Starting from NGINX 1.9.11, you can also compile this module as a dynamic module, by using the `--add-dynamic-module=PATH` option instead of `--add-module=PATH` on the
|
||||||
|
`./configure` command line above. And then you can explicitly load the module in your `nginx.conf` via the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module)
|
||||||
|
directive, for example,
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
load_module /path/to/modules/ngx_http_headers_more_filter_module.so;
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, this module is included and enabled by default in the [OpenResty bundle](http://openresty.org).
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Compatibility
|
||||||
|
=============
|
||||||
|
|
||||||
|
The following versions of Nginx should work with this module:
|
||||||
|
|
||||||
|
* **1.29.x** (last tested: 1.29.2)
|
||||||
|
* **1.27.x** (last tested: 1.27.1)
|
||||||
|
* **1.25.x** (last tested: 1.25.3)
|
||||||
|
* **1.21.x** (last tested: 1.21.4)
|
||||||
|
* **1.19.x** (last tested: 1.19.9)
|
||||||
|
* **1.17.x** (last tested: 1.17.8)
|
||||||
|
* **1.16.x**
|
||||||
|
* **1.15.x** (last tested: 1.15.8)
|
||||||
|
* **1.14.x**
|
||||||
|
* **1.13.x** (last tested: 1.13.6)
|
||||||
|
* **1.12.x**
|
||||||
|
* **1.11.x** (last tested: 1.11.2)
|
||||||
|
* **1.10.x**
|
||||||
|
* **1.9.x** (last tested: 1.9.15)
|
||||||
|
* **1.8.x**
|
||||||
|
* **1.7.x** (last tested: 1.7.10)
|
||||||
|
* **1.6.x** (last tested: 1.6.2)
|
||||||
|
* **1.5.x** (last tested: 1.5.8)
|
||||||
|
* **1.4.x** (last tested: 1.4.4)
|
||||||
|
* **1.3.x** (last tested: 1.3.7)
|
||||||
|
* **1.2.x** (last tested: 1.2.9)
|
||||||
|
* **1.1.x** (last tested: 1.1.5)
|
||||||
|
* **1.0.x** (last tested: 1.0.11)
|
||||||
|
* **0.9.x** (last tested: 0.9.4)
|
||||||
|
* **0.8.x** (last tested: 0.8.54)
|
||||||
|
* **0.7.x >= 0.7.44** (last tested: 0.7.68)
|
||||||
|
|
||||||
|
Earlier versions of Nginx like 0.6.x and 0.5.x will *not* work.
|
||||||
|
|
||||||
|
If you find that any particular version of Nginx above 0.7.44 does not work with this module, please consider [reporting a bug](#report-bugs).
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Community
|
||||||
|
=========
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
English Mailing List
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The [openresty-en](https://groups.google.com/group/openresty-en) mailing list is for English speakers.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Chinese Mailing List
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The [openresty](https://groups.google.com/group/openresty) mailing list is for Chinese speakers.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Bugs and Patches
|
||||||
|
================
|
||||||
|
|
||||||
|
Please submit bug reports, wishlists, or patches by
|
||||||
|
|
||||||
|
1. creating a ticket on the [GitHub Issue Tracker](https://github.com/chaoslawful/lua-nginx-module/issues),
|
||||||
|
1. or posting to the [OpenResty community](#community).
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Source Repository
|
||||||
|
=================
|
||||||
|
|
||||||
|
Available on github at [openresty/headers-more-nginx-module](https://github.com/openresty/headers-more-nginx-module).
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Changes
|
||||||
|
=======
|
||||||
|
|
||||||
|
The changes of every release of this module can be obtained from the OpenResty bundle's change logs:
|
||||||
|
|
||||||
|
<http://openresty.org/#Changes>
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Test Suite
|
||||||
|
==========
|
||||||
|
|
||||||
|
This module comes with a Perl-driven test suite. The [test cases](https://github.com/openresty/headers-more-nginx-module/tree/master/t/) are
|
||||||
|
[declarative](https://github.com/openresty/headers-more-nginx-module/blob/master/t/sanity.t) too. Thanks to the [Test::Nginx](http://search.cpan.org/perldoc?Test::Nginx) module in the Perl world.
|
||||||
|
|
||||||
|
To run it on your side:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
$ PATH=/path/to/your/nginx-with-headers-more-module:$PATH prove -r t
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the test suite with valgrind's memcheck, use the following commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
$ export PATH=/path/to/your/nginx-with-headers-more-module:$PATH
|
||||||
|
$ TEST_NGINX_USE_VALGRIND=1 prove -r t
|
||||||
|
```
|
||||||
|
|
||||||
|
You need to terminate any Nginx processes before running the test suite if you have changed the Nginx server binary.
|
||||||
|
|
||||||
|
Because a single nginx server (by default, `localhost:1984`) is used across all the test scripts (`.t` files), it's meaningless to run the test suite in parallel by specifying `-jN` when invoking the `prove` utility.
|
||||||
|
|
||||||
|
Some parts of the test suite requires modules [proxy](http://nginx.org/en/docs/http/ngx_http_proxy_module.html), [rewrite](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html), and [echo](https://github.com/openresty/echo-nginx-module) to be enabled as well when building Nginx.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
TODO
|
||||||
|
====
|
||||||
|
|
||||||
|
* Support variables in new headers' keys.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Getting involved
|
||||||
|
================
|
||||||
|
|
||||||
|
You'll be very welcomed to submit patches to the [author](#author) or just ask for a commit bit to the [source repository](#source-repository) on GitHub.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Authors
|
||||||
|
=======
|
||||||
|
|
||||||
|
* Yichun "agentzh" Zhang (章亦春) *<agentzh@gmail.com>*, OpenResty Inc.
|
||||||
|
* Bernd Dorn ( <http://www.lovelysystems.com/> )
|
||||||
|
|
||||||
|
This wiki page is also maintained by the author himself, and everybody is encouraged to improve this page as well.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
Copyright & License
|
||||||
|
===================
|
||||||
|
|
||||||
|
The code base is borrowed directly from the standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module in Nginx 0.8.24. This part of code is copyrighted by Igor Sysoev.
|
||||||
|
|
||||||
|
Copyright (c) 2009-2025, Yichun "agentzh" Zhang (章亦春) <agentzh@gmail.com>, OpenResty Inc.
|
||||||
|
|
||||||
|
Copyright (c) 2010-2013, Bernd Dorn.
|
||||||
|
|
||||||
|
The license text is available in the [LICENSE](LICENSE) file located in the root directory of the project.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
|
See Also
|
||||||
|
========
|
||||||
|
|
||||||
|
* The original thread on the Nginx mailing list that inspires this module's development: ["A question about add_header replication"](http://forum.nginx.org/read.php?2,11206,11738).
|
||||||
|
* The orginal announcement thread on the Nginx mailing list: ["The "headers_more" module: Set and clear output headers...more than 'add'!"](http://forum.nginx.org/read.php?2,23460).
|
||||||
|
* The original [blog post](http://agentzh.blogspot.com/2009/11/headers-more-module-scripting-input-and.html) about this module's initial development.
|
||||||
|
* The [echo module](https://github.com/openresty/echo-nginx-module) for Nginx module's automated testing.
|
||||||
|
* The standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module.
|
||||||
|
|
||||||
|
[Back to TOC](#table-of-contents)
|
||||||
|
|
||||||
32
ngx_headers_more/config
Normal file
32
ngx_headers_more/config
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
ngx_addon_name=ngx_http_headers_more_filter_module
|
||||||
|
|
||||||
|
HEADERS_MORE_SRCS=" \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_filter_module.c \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_headers_out.c \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_headers_in.c \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_util.c \
|
||||||
|
"
|
||||||
|
|
||||||
|
HEADERS_MORE_DEPS=" \
|
||||||
|
$ngx_addon_dir/src/ddebug.h \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_filter_module.h \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_headers_in.h \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_headers_out.h \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_headers_in.h \
|
||||||
|
$ngx_addon_dir/src/ngx_http_headers_more_util.h \
|
||||||
|
"
|
||||||
|
|
||||||
|
if test -n "$ngx_module_link"; then
|
||||||
|
ngx_module_type=HTTP_AUX_FILTER
|
||||||
|
ngx_module_name=$ngx_addon_name
|
||||||
|
ngx_module_incs=
|
||||||
|
ngx_module_deps="$HEADERS_MORE_DEPS"
|
||||||
|
ngx_module_srcs="$HEADERS_MORE_SRCS"
|
||||||
|
ngx_module_libs=
|
||||||
|
|
||||||
|
. auto/module
|
||||||
|
else
|
||||||
|
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
|
||||||
|
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $HEADERS_MORE_SRCS"
|
||||||
|
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $HEADERS_MORE_DEPS"
|
||||||
|
fi
|
||||||
124
ngx_headers_more/src/ddebug.h
Normal file
124
ngx_headers_more/src/ddebug.h
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#ifndef DDEBUG_H
|
||||||
|
#define DDEBUG_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_core.h>
|
||||||
|
#include <ngx_http.h>
|
||||||
|
#include <nginx.h>
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DDEBUG) && (DDEBUG)
|
||||||
|
|
||||||
|
# if (NGX_HAVE_VARIADIC_MACROS)
|
||||||
|
|
||||||
|
# define dd(...) fprintf(stderr, "headers-more *** %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__)
|
||||||
|
|
||||||
|
# if defined(nginx_version) && nginx_version >= 8011
|
||||||
|
# define dd_main_req_count r->main->count
|
||||||
|
# else
|
||||||
|
# define dd_main_req_count 0
|
||||||
|
# endif
|
||||||
|
|
||||||
|
static ngx_inline void
|
||||||
|
dd_enter_helper(ngx_http_request_t *r, const char *func)
|
||||||
|
{
|
||||||
|
ngx_http_posted_request_t *pr;
|
||||||
|
|
||||||
|
fprintf(stderr, "headers-more *** 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,
|
||||||
|
(int) dd_main_req_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 */
|
||||||
|
|
||||||
348
ngx_headers_more/src/ngx_http_headers_more_filter_module.c
Normal file
348
ngx_headers_more/src/ngx_http_headers_more_filter_module.c
Normal file
@@ -0,0 +1,348 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Yichun Zhang (agentzh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DDEBUG
|
||||||
|
#define DDEBUG 0
|
||||||
|
#endif
|
||||||
|
#include "ddebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "ngx_http_headers_more_filter_module.h"
|
||||||
|
#include "ngx_http_headers_more_headers_out.h"
|
||||||
|
#include "ngx_http_headers_more_headers_in.h"
|
||||||
|
#include "ngx_http_headers_more_util.h"
|
||||||
|
#include <ngx_config.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* config handlers */
|
||||||
|
|
||||||
|
static void *ngx_http_headers_more_create_loc_conf(ngx_conf_t *cf);
|
||||||
|
static char *ngx_http_headers_more_merge_loc_conf(ngx_conf_t *cf,
|
||||||
|
void *parent, void *child);
|
||||||
|
static void *ngx_http_headers_more_create_main_conf(ngx_conf_t *cf);
|
||||||
|
static ngx_int_t ngx_http_headers_more_post_config(ngx_conf_t *cf);
|
||||||
|
|
||||||
|
/* post-read-phase handler */
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_headers_more_handler(ngx_http_request_t *r);
|
||||||
|
|
||||||
|
/* filter handlers */
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_headers_more_filter_init(ngx_conf_t *cf);
|
||||||
|
|
||||||
|
ngx_uint_t ngx_http_headers_more_location_hash = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_command_t ngx_http_headers_more_filter_commands[] = {
|
||||||
|
|
||||||
|
{ ngx_string("more_set_headers"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|
||||||
|
|NGX_CONF_1MORE,
|
||||||
|
ngx_http_headers_more_set_headers,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL},
|
||||||
|
|
||||||
|
{ ngx_string("more_clear_headers"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|
||||||
|
|NGX_CONF_1MORE,
|
||||||
|
ngx_http_headers_more_clear_headers,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL},
|
||||||
|
|
||||||
|
{ ngx_string("more_set_input_headers"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|
||||||
|
|NGX_CONF_1MORE,
|
||||||
|
ngx_http_headers_more_set_input_headers,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL},
|
||||||
|
|
||||||
|
{ ngx_string("more_clear_input_headers"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|
||||||
|
|NGX_CONF_1MORE,
|
||||||
|
ngx_http_headers_more_clear_input_headers,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL},
|
||||||
|
|
||||||
|
ngx_null_command
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_module_t ngx_http_headers_more_filter_module_ctx = {
|
||||||
|
NULL, /* preconfiguration */
|
||||||
|
ngx_http_headers_more_post_config, /* postconfiguration */
|
||||||
|
|
||||||
|
ngx_http_headers_more_create_main_conf, /* create main configuration */
|
||||||
|
NULL, /* init main configuration */
|
||||||
|
|
||||||
|
NULL, /* create server configuration */
|
||||||
|
NULL, /* merge server configuration */
|
||||||
|
|
||||||
|
ngx_http_headers_more_create_loc_conf, /* create location configuration */
|
||||||
|
ngx_http_headers_more_merge_loc_conf /* merge location configuration */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_module_t ngx_http_headers_more_filter_module = {
|
||||||
|
NGX_MODULE_V1,
|
||||||
|
&ngx_http_headers_more_filter_module_ctx, /* module context */
|
||||||
|
ngx_http_headers_more_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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
|
||||||
|
|
||||||
|
|
||||||
|
static volatile ngx_cycle_t *ngx_http_headers_more_prev_cycle = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_headers_more_filter(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_http_headers_more_loc_conf_t *conf;
|
||||||
|
ngx_http_headers_more_cmd_t *cmd;
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"headers more header filter, uri \"%V\"", &r->uri);
|
||||||
|
|
||||||
|
conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_more_filter_module);
|
||||||
|
|
||||||
|
if (conf->cmds) {
|
||||||
|
cmd = conf->cmds->elts;
|
||||||
|
for (i = 0; i < conf->cmds->nelts; i++) {
|
||||||
|
if (cmd[i].is_input) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_http_headers_more_exec_cmd(r, &cmd[i]);
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_next_header_filter(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_headers_more_filter_init(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_next_header_filter = ngx_http_top_header_filter;
|
||||||
|
ngx_http_top_header_filter = ngx_http_headers_more_filter;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
ngx_http_headers_more_create_loc_conf(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_headers_more_loc_conf_t *conf;
|
||||||
|
|
||||||
|
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_headers_more_loc_conf_t));
|
||||||
|
if (conf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set by ngx_pcalloc():
|
||||||
|
*
|
||||||
|
* conf->cmds = NULL;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_headers_more_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
|
{
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_uint_t orig_len;
|
||||||
|
ngx_http_headers_more_cmd_t *prev_cmd, *cmd;
|
||||||
|
ngx_http_headers_more_loc_conf_t *prev = parent;
|
||||||
|
ngx_http_headers_more_loc_conf_t *conf = child;
|
||||||
|
|
||||||
|
if (conf->cmds == NULL || conf->cmds->nelts == 0) {
|
||||||
|
conf->cmds = prev->cmds;
|
||||||
|
|
||||||
|
} else if (prev->cmds && prev->cmds->nelts) {
|
||||||
|
orig_len = conf->cmds->nelts;
|
||||||
|
|
||||||
|
(void) ngx_array_push_n(conf->cmds, prev->cmds->nelts);
|
||||||
|
|
||||||
|
cmd = conf->cmds->elts;
|
||||||
|
|
||||||
|
for (i = 0; i < orig_len; i++) {
|
||||||
|
cmd[conf->cmds->nelts - 1 - i] = cmd[orig_len - 1 - i];
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_cmd = prev->cmds->elts;
|
||||||
|
|
||||||
|
for (i = 0; i < prev->cmds->nelts; i++) {
|
||||||
|
cmd[i] = prev_cmd[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_headers_more_post_config(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
int multi_http_blocks;
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_http_handler_pt *h;
|
||||||
|
ngx_http_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
|
ngx_http_headers_more_main_conf_t *hmcf;
|
||||||
|
|
||||||
|
ngx_http_headers_more_location_hash =
|
||||||
|
ngx_http_headers_more_hash_literal("location");
|
||||||
|
|
||||||
|
hmcf = ngx_http_conf_get_module_main_conf(cf,
|
||||||
|
ngx_http_headers_more_filter_module);
|
||||||
|
|
||||||
|
if (ngx_http_headers_more_prev_cycle != ngx_cycle) {
|
||||||
|
ngx_http_headers_more_prev_cycle = ngx_cycle;
|
||||||
|
multi_http_blocks = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
multi_http_blocks = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multi_http_blocks || hmcf->requires_filter) {
|
||||||
|
rc = ngx_http_headers_more_filter_init(cf);
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hmcf->requires_handler) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
|
||||||
|
|
||||||
|
h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = ngx_http_headers_more_handler;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_headers_more_handler(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_http_headers_more_loc_conf_t *conf;
|
||||||
|
ngx_http_headers_more_main_conf_t *hmcf;
|
||||||
|
ngx_http_headers_more_cmd_t *cmd;
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
"headers more rewrite handler, uri \"%V\"", &r->uri);
|
||||||
|
|
||||||
|
hmcf = ngx_http_get_module_main_conf(r,
|
||||||
|
ngx_http_headers_more_filter_module);
|
||||||
|
|
||||||
|
if (!hmcf->postponed_to_phase_end) {
|
||||||
|
ngx_http_core_main_conf_t *cmcf;
|
||||||
|
ngx_http_phase_handler_t tmp;
|
||||||
|
ngx_http_phase_handler_t *ph;
|
||||||
|
ngx_http_phase_handler_t *cur_ph;
|
||||||
|
ngx_http_phase_handler_t *last_ph;
|
||||||
|
|
||||||
|
hmcf->postponed_to_phase_end = 1;
|
||||||
|
|
||||||
|
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
ph = cmcf->phase_engine.handlers;
|
||||||
|
cur_ph = &ph[r->phase_handler];
|
||||||
|
last_ph = &ph[cur_ph->next - 1];
|
||||||
|
|
||||||
|
if (cur_ph < last_ph) {
|
||||||
|
dd("swaping the contents of cur_ph and last_ph...");
|
||||||
|
|
||||||
|
tmp = *cur_ph;
|
||||||
|
|
||||||
|
memmove(cur_ph, cur_ph + 1,
|
||||||
|
(last_ph - cur_ph) * sizeof (ngx_http_phase_handler_t));
|
||||||
|
|
||||||
|
*last_ph = tmp;
|
||||||
|
|
||||||
|
r->phase_handler--; /* redo the current ph */
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("running phase handler...");
|
||||||
|
|
||||||
|
conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_more_filter_module);
|
||||||
|
|
||||||
|
if (conf->cmds) {
|
||||||
|
if (r->http_version < NGX_HTTP_VERSION_10) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = conf->cmds->elts;
|
||||||
|
for (i = 0; i < conf->cmds->nelts; i++) {
|
||||||
|
if (!cmd[i].is_input) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_http_headers_more_exec_input_cmd(r, &cmd[i]);
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
ngx_http_headers_more_create_main_conf(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_headers_more_main_conf_t *hmcf;
|
||||||
|
|
||||||
|
hmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_headers_more_main_conf_t));
|
||||||
|
if (hmcf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set by ngx_pcalloc:
|
||||||
|
* hmcf->postponed_to_phase_end = 0;
|
||||||
|
* hmcf->requires_filter = 0;
|
||||||
|
* hmcf->requires_handler = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return hmcf;
|
||||||
|
}
|
||||||
81
ngx_headers_more/src/ngx_http_headers_more_filter_module.h
Normal file
81
ngx_headers_more/src/ngx_http_headers_more_filter_module.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) Yichun Zhang (agentzh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NGX_HTTP_HEADERS_MORE_FILTER_MODULE_H
|
||||||
|
#define NGX_HTTP_HEADERS_MORE_FILTER_MODULE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_core.h>
|
||||||
|
#include <ngx_http.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ngx_http_headers_more_opcode_set,
|
||||||
|
ngx_http_headers_more_opcode_clear
|
||||||
|
} ngx_http_headers_more_opcode_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_array_t *types; /* of ngx_str_t */
|
||||||
|
ngx_array_t *statuses; /* of ngx_uint_t */
|
||||||
|
ngx_array_t *headers; /* of ngx_http_header_val_t */
|
||||||
|
ngx_flag_t is_input;
|
||||||
|
} ngx_http_headers_more_cmd_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_array_t *cmds; /* of ngx_http_headers_more_cmd_t */
|
||||||
|
} ngx_http_headers_more_loc_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_int_t postponed_to_phase_end;
|
||||||
|
ngx_int_t requires_filter;
|
||||||
|
ngx_int_t requires_handler;
|
||||||
|
} ngx_http_headers_more_main_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ngx_http_headers_more_header_val_s
|
||||||
|
ngx_http_headers_more_header_val_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef ngx_int_t (*ngx_http_headers_more_set_header_pt)(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_str_t name;
|
||||||
|
ngx_uint_t offset;
|
||||||
|
ngx_http_headers_more_set_header_pt handler;
|
||||||
|
} ngx_http_headers_more_set_header_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct ngx_http_headers_more_header_val_s {
|
||||||
|
ngx_http_complex_value_t value;
|
||||||
|
ngx_uint_t hash;
|
||||||
|
ngx_str_t key;
|
||||||
|
ngx_http_headers_more_set_header_pt handler;
|
||||||
|
ngx_uint_t offset;
|
||||||
|
unsigned replace:1;
|
||||||
|
unsigned wildcard:1;
|
||||||
|
unsigned append:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern ngx_module_t ngx_http_headers_more_filter_module;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ngx_str_set
|
||||||
|
#define ngx_str_set(str, text) \
|
||||||
|
(str)->len = sizeof(text) - 1; (str)->data = (u_char *) text
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define ngx_http_headers_more_assert(a) assert(a)
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* NGX_HTTP_HEADERS_MORE_FILTER_MODULE_H */
|
||||||
959
ngx_headers_more/src/ngx_http_headers_more_headers_in.c
Normal file
959
ngx_headers_more/src/ngx_http_headers_more_headers_in.c
Normal file
@@ -0,0 +1,959 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Yichun Zhang (agentzh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DDEBUG
|
||||||
|
#define DDEBUG 0
|
||||||
|
#endif
|
||||||
|
#include "ddebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "ngx_http_headers_more_headers_in.h"
|
||||||
|
#include "ngx_http_headers_more_util.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
static char *ngx_http_headers_more_parse_directive(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *ngx_cmd, void *conf,
|
||||||
|
ngx_http_headers_more_opcode_t opcode);
|
||||||
|
static int ngx_http_headers_more_check_type(ngx_http_request_t *r,
|
||||||
|
ngx_array_t *types);
|
||||||
|
static ngx_int_t ngx_http_set_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
|
||||||
|
ngx_table_elt_t **output_header);
|
||||||
|
static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_user_agent_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_clear_content_length_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_host_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_connection_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_headers_more_validate_host(ngx_str_t *host,
|
||||||
|
ngx_pool_t *pool, ngx_uint_t alloc);
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_headers_more_set_header_t ngx_http_headers_more_set_handlers[]
|
||||||
|
= {
|
||||||
|
|
||||||
|
{ ngx_string("Host"),
|
||||||
|
offsetof(ngx_http_headers_in_t, host),
|
||||||
|
ngx_http_set_host_header },
|
||||||
|
|
||||||
|
{ ngx_string("Connection"),
|
||||||
|
offsetof(ngx_http_headers_in_t, connection),
|
||||||
|
ngx_http_set_connection_header },
|
||||||
|
|
||||||
|
{ ngx_string("If-Modified-Since"),
|
||||||
|
offsetof(ngx_http_headers_in_t, if_modified_since),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
#if defined(nginx_version) && nginx_version >= 9002
|
||||||
|
{ ngx_string("If-Unmodified-Since"),
|
||||||
|
offsetof(ngx_http_headers_in_t, if_unmodified_since),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(nginx_version) && nginx_version >= 1003003
|
||||||
|
{ ngx_string("If-Match"),
|
||||||
|
offsetof(ngx_http_headers_in_t, if_match),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("If-None-Match"),
|
||||||
|
offsetof(ngx_http_headers_in_t, if_none_match),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ ngx_string("User-Agent"),
|
||||||
|
offsetof(ngx_http_headers_in_t, user_agent),
|
||||||
|
ngx_http_set_user_agent_header },
|
||||||
|
|
||||||
|
{ ngx_string("Referer"),
|
||||||
|
offsetof(ngx_http_headers_in_t, referer),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Content-Length"),
|
||||||
|
offsetof(ngx_http_headers_in_t, content_length),
|
||||||
|
ngx_http_set_content_length_header },
|
||||||
|
|
||||||
|
{ ngx_string("Content-Type"),
|
||||||
|
offsetof(ngx_http_headers_in_t, content_type),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Range"),
|
||||||
|
offsetof(ngx_http_headers_in_t, range),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("If-Range"),
|
||||||
|
offsetof(ngx_http_headers_in_t, if_range),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Transfer-Encoding"),
|
||||||
|
offsetof(ngx_http_headers_in_t, transfer_encoding),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Expect"),
|
||||||
|
offsetof(ngx_http_headers_in_t, expect),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
#if defined(nginx_version) && nginx_version >= 1003013
|
||||||
|
{ ngx_string("Upgrade"),
|
||||||
|
offsetof(ngx_http_headers_in_t, upgrade),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HTTP_GZIP)
|
||||||
|
{ ngx_string("Accept-Encoding"),
|
||||||
|
offsetof(ngx_http_headers_in_t, accept_encoding),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ ngx_string("Authorization"),
|
||||||
|
offsetof(ngx_http_headers_in_t, authorization),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Keep-Alive"),
|
||||||
|
offsetof(ngx_http_headers_in_t, keep_alive),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
#if (NGX_HTTP_X_FORWARDED_FOR)
|
||||||
|
{ ngx_string("X-Forwarded-For"),
|
||||||
|
offsetof(ngx_http_headers_in_t, x_forwarded_for),
|
||||||
|
ngx_http_set_builtin_multi_header },
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HTTP_REALIP)
|
||||||
|
{ ngx_string("X-Real-IP"),
|
||||||
|
offsetof(ngx_http_headers_in_t, x_real_ip),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HTTP_DAV)
|
||||||
|
{ ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(nginx_version) && nginx_version >= 1023000
|
||||||
|
{ ngx_string("Cookie"),
|
||||||
|
offsetof(ngx_http_headers_in_t, cookie),
|
||||||
|
ngx_http_set_builtin_multi_header },
|
||||||
|
#else
|
||||||
|
{ ngx_string("Cookie"),
|
||||||
|
offsetof(ngx_http_headers_in_t, cookies),
|
||||||
|
ngx_http_set_builtin_multi_header },
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ ngx_null_string, 0, ngx_http_set_header }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_headers_more_exec_input_cmd(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_cmd_t *cmd)
|
||||||
|
{
|
||||||
|
ngx_str_t value;
|
||||||
|
ngx_http_headers_more_header_val_t *h;
|
||||||
|
ngx_uint_t i;
|
||||||
|
|
||||||
|
if (!cmd->headers) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->types && !ngx_http_headers_more_check_type(r, cmd->types)) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
h = cmd->headers->elts;
|
||||||
|
for (i = 0; i < cmd->headers->nelts; i++) {
|
||||||
|
|
||||||
|
if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.len) {
|
||||||
|
value.len--; /* remove the trailing '\0' added by
|
||||||
|
ngx_http_headers_more_parse_header */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h[i].handler(r, &h[i], &value) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
return ngx_http_set_header_helper(r, hv, value, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_header_helper(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
|
||||||
|
ngx_table_elt_t **output_header)
|
||||||
|
{
|
||||||
|
ngx_table_elt_t *h, *matched;
|
||||||
|
ngx_list_part_t *part;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_uint_t rc;
|
||||||
|
|
||||||
|
dd_enter();
|
||||||
|
|
||||||
|
matched = NULL;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
|
||||||
|
part = &r->headers_in.headers.part;
|
||||||
|
h = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
dd("i: %d, part: %p", (int) i, part);
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
h = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hv->wildcard
|
||||||
|
&& h[i].key.len == hv->key.len
|
||||||
|
&& ngx_strncasecmp(h[i].key.data, hv->key.data,
|
||||||
|
h[i].key.len) == 0)
|
||||||
|
{
|
||||||
|
goto matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hv->wildcard
|
||||||
|
&& value->len == 0
|
||||||
|
&& h[i].key.len >= hv->key.len - 1
|
||||||
|
&& ngx_strncasecmp(h[i].key.data, hv->key.data,
|
||||||
|
hv->key.len - 1) == 0)
|
||||||
|
{
|
||||||
|
goto matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not matched */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
matched:
|
||||||
|
|
||||||
|
if (value->len == 0 || (matched && matched != &h[i])) {
|
||||||
|
h[i].hash = 0;
|
||||||
|
|
||||||
|
rc = ngx_http_headers_more_rm_header_helper(
|
||||||
|
&r->headers_in.headers, part, i);
|
||||||
|
|
||||||
|
ngx_http_headers_more_assert(
|
||||||
|
!(r->headers_in.headers.part.next == NULL
|
||||||
|
&& r->headers_in.headers.last
|
||||||
|
!= &r->headers_in.headers.part));
|
||||||
|
|
||||||
|
if (rc == NGX_OK) {
|
||||||
|
if (output_header) {
|
||||||
|
*output_header = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
h[i].value = *value;
|
||||||
|
|
||||||
|
if (output_header) {
|
||||||
|
*output_header = &h[i];
|
||||||
|
dd("setting existing builtin input header");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched == NULL) {
|
||||||
|
matched = &h[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value->len == 0 || hv->replace) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->headers_in.headers.last == NULL) {
|
||||||
|
/* must be 400 bad request */
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
h = ngx_list_push(&r->headers_in.headers);
|
||||||
|
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("created new header for %.*s", (int) hv->key.len, hv->key.data);
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
h->hash = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
h->hash = hv->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->key = hv->key;
|
||||||
|
h->value = *value;
|
||||||
|
#if defined(nginx_version) && nginx_version >= 1023000
|
||||||
|
h->next = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
|
||||||
|
if (h->lowcase_key == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
|
||||||
|
|
||||||
|
if (output_header) {
|
||||||
|
*output_header = h;
|
||||||
|
|
||||||
|
while (r != r->main) {
|
||||||
|
r->parent->headers_in = r->headers_in;
|
||||||
|
r = r->parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_builtin_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
ngx_table_elt_t *h, **old;
|
||||||
|
|
||||||
|
dd("entered set_builtin_header (input)");
|
||||||
|
|
||||||
|
if (hv->offset) {
|
||||||
|
old = (ngx_table_elt_t **) ((char *) &r->headers_in + hv->offset);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
old = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("old builtin ptr ptr: %p", old);
|
||||||
|
if (old) {
|
||||||
|
dd("old builtin ptr: %p", *old);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old == NULL || *old == NULL) {
|
||||||
|
dd("set normal header");
|
||||||
|
return ngx_http_set_header_helper(r, hv, value, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
h = *old;
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
h->hash = 0;
|
||||||
|
h->value = *value;
|
||||||
|
|
||||||
|
return ngx_http_set_header_helper(r, hv, value, old);
|
||||||
|
}
|
||||||
|
|
||||||
|
h->hash = hv->hash;
|
||||||
|
h->value = *value;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_host_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
ngx_str_t host;
|
||||||
|
|
||||||
|
if (value->len) {
|
||||||
|
host= *value;
|
||||||
|
|
||||||
|
if (ngx_http_headers_more_validate_host(&host, r->pool, 0) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->headers_in.server = host;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
r->headers_in.server = *value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_content_length_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
off_t len;
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
return ngx_http_clear_content_length_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ngx_atosz(value->data, value->len);
|
||||||
|
if (len == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("reset headers_in.content_length_n to %d", (int) len);
|
||||||
|
|
||||||
|
r->headers_in.content_length_n = len;
|
||||||
|
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_clear_content_length_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
r->headers_in.content_length_n = -1;
|
||||||
|
|
||||||
|
return ngx_http_clear_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_clear_builtin_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
value->len = 0;
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
ngx_http_headers_more_set_input_headers(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
|
||||||
|
ngx_http_headers_more_opcode_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
ngx_http_headers_more_clear_input_headers(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
|
||||||
|
ngx_http_headers_more_opcode_clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
ngx_http_headers_more_check_type(ngx_http_request_t *r, ngx_array_t *types)
|
||||||
|
{
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_str_t *t;
|
||||||
|
ngx_str_t actual_type;
|
||||||
|
|
||||||
|
if (r->headers_in.content_type == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_type = r->headers_in.content_type->value;
|
||||||
|
if (actual_type.len == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("headers_in->content_type: %.*s",
|
||||||
|
(int) actual_type.len,
|
||||||
|
actual_type.data);
|
||||||
|
|
||||||
|
t = types->elts;
|
||||||
|
for (i = 0; i < types->nelts; i++) {
|
||||||
|
dd("...comparing with type [%.*s]", (int) t[i].len, t[i].data);
|
||||||
|
|
||||||
|
if (actual_type.len == t[i].len
|
||||||
|
&& ngx_strncmp(actual_type.data, t[i].data, t[i].len) == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
|
||||||
|
void *conf, ngx_http_headers_more_opcode_t opcode)
|
||||||
|
{
|
||||||
|
ngx_http_headers_more_loc_conf_t *hlcf = conf;
|
||||||
|
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_http_headers_more_cmd_t *cmd;
|
||||||
|
ngx_str_t *arg;
|
||||||
|
ngx_flag_t ignore_next_arg;
|
||||||
|
ngx_str_t *cmd_name;
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_flag_t replace = 0;
|
||||||
|
ngx_http_headers_more_header_val_t *h;
|
||||||
|
|
||||||
|
ngx_http_headers_more_main_conf_t *hmcf;
|
||||||
|
|
||||||
|
if (hlcf->cmds == NULL) {
|
||||||
|
hlcf->cmds = ngx_array_create(cf->pool, 1,
|
||||||
|
sizeof(ngx_http_headers_more_cmd_t));
|
||||||
|
|
||||||
|
if (hlcf->cmds == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = ngx_array_push(hlcf->cmds);
|
||||||
|
|
||||||
|
if (cmd == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->headers = ngx_array_create(cf->pool, 1,
|
||||||
|
sizeof(ngx_http_headers_more_header_val_t));
|
||||||
|
|
||||||
|
if (cmd->headers == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
|
||||||
|
if (cmd->types == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->statuses = NULL;
|
||||||
|
|
||||||
|
arg = cf->args->elts;
|
||||||
|
|
||||||
|
cmd_name = &arg[0];
|
||||||
|
|
||||||
|
ignore_next_arg = 0;
|
||||||
|
|
||||||
|
for (i = 1; i < cf->args->nelts; i++) {
|
||||||
|
if (ignore_next_arg) {
|
||||||
|
ignore_next_arg = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[i].len == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[i].data[0] != '-') {
|
||||||
|
rc = ngx_http_headers_more_parse_header(cf, cmd_name,
|
||||||
|
&arg[i], cmd->headers,
|
||||||
|
opcode,
|
||||||
|
ngx_http_headers_more_set_handlers);
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[i].len == 2) {
|
||||||
|
if (arg[i].data[1] == 't') {
|
||||||
|
if (i == cf->args->nelts - 1) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: option -t takes an argument.",
|
||||||
|
cmd_name);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_http_headers_more_parse_types(cf->log, cmd_name,
|
||||||
|
&arg[i + 1],
|
||||||
|
cmd->types);
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignore_next_arg = 1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[i].data[1] == 'r') {
|
||||||
|
dd("Found replace flag");
|
||||||
|
replace = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: invalid option name: \"%V\"", cmd_name, &arg[i]);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("Found %d types, and %d headers",
|
||||||
|
(int) cmd->types->nelts,
|
||||||
|
(int) cmd->headers->nelts);
|
||||||
|
|
||||||
|
if (cmd->headers->nelts == 0) {
|
||||||
|
ngx_pfree(cf->pool, cmd->headers);
|
||||||
|
cmd->headers = NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
h = cmd->headers->elts;
|
||||||
|
for (i = 0; i < cmd->headers->nelts; i++) {
|
||||||
|
h[i].replace = replace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->types->nelts == 0) {
|
||||||
|
ngx_pfree(cf->pool, cmd->types);
|
||||||
|
cmd->types = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->is_input = 1;
|
||||||
|
|
||||||
|
hmcf = ngx_http_conf_get_module_main_conf(cf,
|
||||||
|
ngx_http_headers_more_filter_module);
|
||||||
|
|
||||||
|
hmcf->requires_handler = 1;
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* borrowed the code from ngx_http_request.c:ngx_http_process_user_agent */
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_user_agent_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
u_char *user_agent, *msie;
|
||||||
|
|
||||||
|
/* clear existing settings */
|
||||||
|
|
||||||
|
r->headers_in.msie = 0;
|
||||||
|
r->headers_in.msie6 = 0;
|
||||||
|
r->headers_in.opera = 0;
|
||||||
|
r->headers_in.gecko = 0;
|
||||||
|
r->headers_in.chrome = 0;
|
||||||
|
r->headers_in.safari = 0;
|
||||||
|
r->headers_in.konqueror = 0;
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check some widespread browsers */
|
||||||
|
|
||||||
|
user_agent = value->data;
|
||||||
|
|
||||||
|
msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
|
||||||
|
|
||||||
|
if (msie && msie + 7 < user_agent + value->len) {
|
||||||
|
|
||||||
|
r->headers_in.msie = 1;
|
||||||
|
|
||||||
|
if (msie[6] == '.') {
|
||||||
|
|
||||||
|
switch (msie[5]) {
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
r->headers_in.msie6 = 1;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
|
||||||
|
r->headers_in.msie6 = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
|
||||||
|
r->headers_in.opera = 1;
|
||||||
|
r->headers_in.msie = 0;
|
||||||
|
r->headers_in.msie6 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r->headers_in.msie && !r->headers_in.opera) {
|
||||||
|
|
||||||
|
if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
|
||||||
|
r->headers_in.gecko = 1;
|
||||||
|
|
||||||
|
} else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
|
||||||
|
r->headers_in.chrome = 1;
|
||||||
|
|
||||||
|
} else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
|
||||||
|
&& ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
|
||||||
|
{
|
||||||
|
r->headers_in.safari = 1;
|
||||||
|
|
||||||
|
} else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
|
||||||
|
r->headers_in.konqueror = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_connection_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
r->headers_in.connection_type = 0;
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_strcasestrn(value->data, "close", 5 - 1)) {
|
||||||
|
r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
|
||||||
|
r->headers_in.keep_alive_n = -1;
|
||||||
|
r->keepalive = 0;
|
||||||
|
|
||||||
|
} else if (ngx_strcasestrn(value->data, "keep-alive", 10 - 1)) {
|
||||||
|
r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
#if defined(nginx_version) && nginx_version >= 1023000
|
||||||
|
ngx_table_elt_t **headers, **ph, *h;
|
||||||
|
#if (DDEBUG)
|
||||||
|
int nelts;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (r->headers_out.status == 400 || r->headers_in.headers.last == NULL) {
|
||||||
|
/* must be a 400 Bad Request */
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = (ngx_table_elt_t **) ((char *) &r->headers_in + hv->offset);
|
||||||
|
|
||||||
|
if (*headers) {
|
||||||
|
#if (DDEBUG)
|
||||||
|
nelts = 0;
|
||||||
|
for (h = *headers; h; h = h->next) {
|
||||||
|
nelts++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("clear multi-value headers: %d", nelts);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*headers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_http_set_header_helper(r, hv, value, &h) == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("new multi-value header: %p", h);
|
||||||
|
|
||||||
|
if (*headers) {
|
||||||
|
for (ph = headers; *ph; ph = &(*ph)->next) { /* void */ }
|
||||||
|
*ph = h;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
*headers = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->next = NULL;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
#else
|
||||||
|
ngx_array_t *headers;
|
||||||
|
ngx_table_elt_t **v, *h;
|
||||||
|
|
||||||
|
if (r->headers_out.status == 400 || r->headers_in.headers.last == NULL) {
|
||||||
|
/* must be a 400 Bad Request */
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = (ngx_array_t *) ((char *) &r->headers_in + hv->offset);
|
||||||
|
|
||||||
|
if (headers->nelts > 0) {
|
||||||
|
ngx_array_destroy(headers);
|
||||||
|
|
||||||
|
if (ngx_array_init(headers, r->pool, 2,
|
||||||
|
sizeof(ngx_table_elt_t *))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("clear multi-value headers: %d", (int) headers->nelts);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (headers->nalloc == 0) {
|
||||||
|
if (ngx_array_init(headers, r->pool, 2,
|
||||||
|
sizeof(ngx_table_elt_t *))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
h = NULL;
|
||||||
|
if (ngx_http_set_header_helper(r, hv, value, &h) == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("new cookie header: %p", h);
|
||||||
|
|
||||||
|
v = ngx_array_push(headers);
|
||||||
|
if (v == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*v = h;
|
||||||
|
return NGX_OK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_headers_more_validate_host(ngx_str_t *host, ngx_pool_t *pool,
|
||||||
|
ngx_uint_t alloc)
|
||||||
|
{
|
||||||
|
u_char *h, ch;
|
||||||
|
size_t i, dot_pos, host_len;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
sw_usual = 0,
|
||||||
|
sw_literal,
|
||||||
|
sw_rest
|
||||||
|
} state;
|
||||||
|
|
||||||
|
dot_pos = host->len;
|
||||||
|
host_len = host->len;
|
||||||
|
|
||||||
|
h = host->data;
|
||||||
|
|
||||||
|
state = sw_usual;
|
||||||
|
|
||||||
|
for (i = 0; i < host->len; i++) {
|
||||||
|
ch = h[i];
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
if (dot_pos == i - 1) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
dot_pos = i;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ':':
|
||||||
|
if (state == sw_usual) {
|
||||||
|
host_len = i;
|
||||||
|
state = sw_rest;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
if (i == 0) {
|
||||||
|
state = sw_literal;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ']':
|
||||||
|
if (state == sw_literal) {
|
||||||
|
host_len = i + 1;
|
||||||
|
state = sw_rest;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\0':
|
||||||
|
return NGX_DECLINED;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
if (ngx_path_separator(ch)) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch >= 'A' && ch <= 'Z') {
|
||||||
|
alloc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dot_pos == host_len - 1) {
|
||||||
|
host_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host_len == 0) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alloc) {
|
||||||
|
host->data = ngx_pnalloc(pool, host_len);
|
||||||
|
if (host->data == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_strlow(host->data, h, host_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
host->len = host_len;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
26
ngx_headers_more/src/ngx_http_headers_more_headers_in.h
Normal file
26
ngx_headers_more/src/ngx_http_headers_more_headers_in.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) Yichun Zhang (agentzh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NGX_HTTP_HEADERS_MORE_INPUT_HEADERS_H
|
||||||
|
#define NGX_HTTP_HEADERS_MORE_INPUT_HEADERS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "ngx_http_headers_more_filter_module.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* output header setters and clearers */
|
||||||
|
|
||||||
|
ngx_int_t ngx_http_headers_more_exec_input_cmd(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_cmd_t *cmd);
|
||||||
|
|
||||||
|
char *ngx_http_headers_more_set_input_headers(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd, void *conf);
|
||||||
|
|
||||||
|
char *ngx_http_headers_more_clear_input_headers(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd, void *conf);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* NGX_HTTP_HEADERS_MORE_INPUT_HEADERS_H */
|
||||||
817
ngx_headers_more/src/ngx_http_headers_more_headers_out.c
Normal file
817
ngx_headers_more/src/ngx_http_headers_more_headers_out.c
Normal file
@@ -0,0 +1,817 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Yichun Zhang (agentzh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DDEBUG
|
||||||
|
#define DDEBUG 0
|
||||||
|
#endif
|
||||||
|
#include "ddebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "ngx_http_headers_more_headers_out.h"
|
||||||
|
#include "ngx_http_headers_more_util.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
|
||||||
|
void *conf, ngx_http_headers_more_opcode_t opcode);
|
||||||
|
static ngx_flag_t ngx_http_headers_more_check_type(ngx_http_request_t *r,
|
||||||
|
ngx_array_t *types);
|
||||||
|
static ngx_flag_t ngx_http_headers_more_check_status(ngx_http_request_t *r,
|
||||||
|
ngx_array_t *statuses);
|
||||||
|
static ngx_int_t ngx_http_set_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
|
||||||
|
ngx_table_elt_t **output_header, ngx_flag_t no_create);
|
||||||
|
static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_accept_ranges_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_content_type_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_clear_content_length_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
static ngx_int_t ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_headers_more_set_header_t ngx_http_headers_more_set_handlers[]
|
||||||
|
= {
|
||||||
|
|
||||||
|
{ ngx_string("Server"),
|
||||||
|
offsetof(ngx_http_headers_out_t, server),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Date"),
|
||||||
|
offsetof(ngx_http_headers_out_t, date),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Content-Encoding"),
|
||||||
|
offsetof(ngx_http_headers_out_t, content_encoding),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Location"),
|
||||||
|
offsetof(ngx_http_headers_out_t, location),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Refresh"),
|
||||||
|
offsetof(ngx_http_headers_out_t, refresh),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Last-Modified"),
|
||||||
|
offsetof(ngx_http_headers_out_t, last_modified),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Content-Range"),
|
||||||
|
offsetof(ngx_http_headers_out_t, content_range),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Accept-Ranges"),
|
||||||
|
offsetof(ngx_http_headers_out_t, accept_ranges),
|
||||||
|
ngx_http_set_accept_ranges_header },
|
||||||
|
|
||||||
|
{ ngx_string("WWW-Authenticate"),
|
||||||
|
offsetof(ngx_http_headers_out_t, www_authenticate),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Expires"),
|
||||||
|
offsetof(ngx_http_headers_out_t, expires),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("E-Tag"),
|
||||||
|
offsetof(ngx_http_headers_out_t, etag),
|
||||||
|
ngx_http_set_builtin_header },
|
||||||
|
|
||||||
|
{ ngx_string("Content-Length"),
|
||||||
|
offsetof(ngx_http_headers_out_t, content_length),
|
||||||
|
ngx_http_set_content_length_header },
|
||||||
|
|
||||||
|
{ ngx_string("Content-Type"),
|
||||||
|
0,
|
||||||
|
ngx_http_set_content_type_header },
|
||||||
|
|
||||||
|
{ ngx_string("Cache-Control"),
|
||||||
|
offsetof(ngx_http_headers_out_t, cache_control),
|
||||||
|
ngx_http_set_builtin_multi_header },
|
||||||
|
|
||||||
|
{ ngx_null_string, 0, ngx_http_set_header }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_headers_more_exec_cmd(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_cmd_t *cmd)
|
||||||
|
{
|
||||||
|
ngx_str_t value;
|
||||||
|
ngx_http_headers_more_header_val_t *h;
|
||||||
|
ngx_uint_t i;
|
||||||
|
|
||||||
|
if (!cmd->headers) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->types && !ngx_http_headers_more_check_type(r, cmd->types)) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->statuses
|
||||||
|
&& !ngx_http_headers_more_check_status(r, cmd->statuses))
|
||||||
|
{
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
h = cmd->headers->elts;
|
||||||
|
for (i = 0; i < cmd->headers->nelts; i++) {
|
||||||
|
|
||||||
|
if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.len) {
|
||||||
|
value.len--; /* remove the trailing '\0' added by
|
||||||
|
ngx_http_headers_more_parse_header */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h[i].handler(r, &h[i], &value) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
return ngx_http_set_header_helper(r, hv, value, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_header_helper(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
|
||||||
|
ngx_table_elt_t **output_header, ngx_flag_t no_create)
|
||||||
|
{
|
||||||
|
ngx_table_elt_t *h;
|
||||||
|
ngx_list_part_t *part;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_flag_t matched = 0;
|
||||||
|
|
||||||
|
dd_enter();
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (r->headers_out.location
|
||||||
|
&& r->headers_out.location->value.len
|
||||||
|
&& r->headers_out.location->value.data[0] == '/')
|
||||||
|
{
|
||||||
|
/* XXX ngx_http_core_find_config_phase, for example,
|
||||||
|
* may not initialize the "key" and "hash" fields
|
||||||
|
* for a nasty optimization purpose, and
|
||||||
|
* we have to work-around it here */
|
||||||
|
|
||||||
|
r->headers_out.location->hash = ngx_http_headers_more_location_hash;
|
||||||
|
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (hv->append) {
|
||||||
|
goto append;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = &r->headers_out.headers.part;
|
||||||
|
h = part->elts;
|
||||||
|
|
||||||
|
for (i = 0; /* void */; i++) {
|
||||||
|
|
||||||
|
if (i >= part->nelts) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
h = part->elts;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h[i].hash == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hv->wildcard
|
||||||
|
&& h[i].key.len == hv->key.len
|
||||||
|
&& ngx_strncasecmp(h[i].key.data, hv->key.data,
|
||||||
|
h[i].key.len) == 0)
|
||||||
|
{
|
||||||
|
goto matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hv->wildcard
|
||||||
|
&& h[i].key.len >= hv->key.len - 1
|
||||||
|
&& ngx_strncasecmp(h[i].key.data, hv->key.data,
|
||||||
|
hv->key.len - 1) == 0)
|
||||||
|
{
|
||||||
|
goto matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not matched */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
matched:
|
||||||
|
|
||||||
|
if (value->len == 0 || matched) {
|
||||||
|
dd("clearing normal header for %.*s", (int) hv->key.len,
|
||||||
|
hv->key.data);
|
||||||
|
|
||||||
|
h[i].value.len = 0;
|
||||||
|
h[i].hash = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
h[i].value = *value;
|
||||||
|
h[i].hash = hv->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output_header) {
|
||||||
|
*output_header = &h[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
matched = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matched){
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hv->wildcard || no_create) && value->len == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX we still need to create header slot even if the value
|
||||||
|
* is empty because some builtin headers like Last-Modified
|
||||||
|
* relies on this to get cleared */
|
||||||
|
|
||||||
|
append:
|
||||||
|
|
||||||
|
h = ngx_list_push(&r->headers_out.headers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
h->hash = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
h->hash = hv->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->key = hv->key;
|
||||||
|
h->value = *value;
|
||||||
|
#if defined(nginx_version) && nginx_version >= 1023000
|
||||||
|
h->next = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
|
||||||
|
if (h->lowcase_key == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
|
||||||
|
|
||||||
|
if (output_header) {
|
||||||
|
*output_header = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_builtin_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
ngx_table_elt_t *h, **old;
|
||||||
|
|
||||||
|
dd_enter();
|
||||||
|
|
||||||
|
if (hv->offset) {
|
||||||
|
old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
old = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old == NULL || *old == NULL) {
|
||||||
|
return ngx_http_set_header_helper(r, hv, value, old, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
h = *old;
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
dd("clearing the builtin header");
|
||||||
|
|
||||||
|
h->hash = 0;
|
||||||
|
h->value = *value;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->hash = hv->hash;
|
||||||
|
h->key = hv->key;
|
||||||
|
h->value = *value;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
#if defined(nginx_version) && nginx_version >= 1023000
|
||||||
|
ngx_table_elt_t **headers, *h, *ho, **ph;
|
||||||
|
|
||||||
|
headers = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
|
||||||
|
|
||||||
|
if (*headers) {
|
||||||
|
for (h = (*headers)->next; h; h = h->next) {
|
||||||
|
h->hash = 0;
|
||||||
|
h->value.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h = *headers;
|
||||||
|
|
||||||
|
h->value = *value;
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
h->hash = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
h->hash = hv->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ph = headers; *ph; ph = &(*ph)->next) { /* void */ }
|
||||||
|
|
||||||
|
ho = ngx_list_push(&r->headers_out.headers);
|
||||||
|
if (ho == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ho->value = *value;
|
||||||
|
ho->hash = hv->hash;
|
||||||
|
ngx_str_set(&ho->key, "Cache-Control");
|
||||||
|
ho->next = NULL;
|
||||||
|
*ph = ho;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
#else
|
||||||
|
ngx_array_t *pa;
|
||||||
|
ngx_table_elt_t *ho, **ph;
|
||||||
|
ngx_uint_t i;
|
||||||
|
|
||||||
|
pa = (ngx_array_t *) ((char *) &r->headers_out + hv->offset);
|
||||||
|
|
||||||
|
if (pa->elts == NULL) {
|
||||||
|
if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* override old values (if any) */
|
||||||
|
|
||||||
|
if (pa->nelts > 0) {
|
||||||
|
ph = pa->elts;
|
||||||
|
for (i = 1; i < pa->nelts; i++) {
|
||||||
|
ph[i]->hash = 0;
|
||||||
|
ph[i]->value.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ph[0]->value = *value;
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
ph[0]->hash = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ph[0]->hash = hv->hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ph = ngx_array_push(pa);
|
||||||
|
if (ph == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ho = ngx_list_push(&r->headers_out.headers);
|
||||||
|
if (ho == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ho->value = *value;
|
||||||
|
ho->hash = hv->hash;
|
||||||
|
ngx_str_set(&ho->key, "Cache-Control");
|
||||||
|
*ph = ho;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_content_type_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
u_char *p, *last, *end;
|
||||||
|
|
||||||
|
r->headers_out.content_type_len = value->len;
|
||||||
|
r->headers_out.content_type = *value;
|
||||||
|
r->headers_out.content_type_hash = hv->hash;
|
||||||
|
r->headers_out.content_type_lowcase = NULL;
|
||||||
|
|
||||||
|
p = value->data;
|
||||||
|
end = p + value->len;
|
||||||
|
|
||||||
|
for (; p != end; p++) {
|
||||||
|
|
||||||
|
if (*p != ';') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = p;
|
||||||
|
|
||||||
|
while (*++p == ' ') { /* void */ }
|
||||||
|
|
||||||
|
if (p == end) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_strncasecmp(p, (u_char *) "charset=", 8) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 8;
|
||||||
|
|
||||||
|
r->headers_out.content_type_len = last - value->data;
|
||||||
|
|
||||||
|
if (*p == '"') {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = end;
|
||||||
|
|
||||||
|
if (*(last - 1) == '"') {
|
||||||
|
last--;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->headers_out.charset.len = last - p;
|
||||||
|
r->headers_out.charset.data = p;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
value->len = 0;
|
||||||
|
|
||||||
|
return ngx_http_set_header_helper(r, hv, value, NULL, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_content_length_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
off_t len;
|
||||||
|
|
||||||
|
if (value->len == 0) {
|
||||||
|
return ngx_http_clear_content_length_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
len = ngx_atosz(value->data, value->len);
|
||||||
|
if (len == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->headers_out.content_length_n = len;
|
||||||
|
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_set_accept_ranges_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
if (value->len == 0) {
|
||||||
|
r->allow_ranges = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_clear_content_length_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
r->headers_out.content_length_n = -1;
|
||||||
|
|
||||||
|
return ngx_http_clear_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_clear_builtin_header(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
|
||||||
|
{
|
||||||
|
dd_enter();
|
||||||
|
|
||||||
|
value->len = 0;
|
||||||
|
|
||||||
|
return ngx_http_set_builtin_header(r, hv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
ngx_http_headers_more_set_headers(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
|
||||||
|
ngx_http_headers_more_opcode_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
ngx_http_headers_more_clear_headers(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
|
||||||
|
ngx_http_headers_more_opcode_clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_flag_t
|
||||||
|
ngx_http_headers_more_check_type(ngx_http_request_t *r, ngx_array_t *types)
|
||||||
|
{
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_str_t *t;
|
||||||
|
|
||||||
|
dd("headers_out->content_type: %.*s (len %d)",
|
||||||
|
(int) r->headers_out.content_type.len,
|
||||||
|
r->headers_out.content_type.data,
|
||||||
|
(int) r->headers_out.content_type.len);
|
||||||
|
|
||||||
|
t = types->elts;
|
||||||
|
|
||||||
|
for (i = 0; i < types->nelts; i++) {
|
||||||
|
dd("...comparing with type [%.*s]", (int) t[i].len, t[i].data);
|
||||||
|
|
||||||
|
if (r->headers_out.content_type_len == t[i].len
|
||||||
|
&& ngx_strncmp(r->headers_out.content_type.data,
|
||||||
|
t[i].data, t[i].len) == 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_flag_t
|
||||||
|
ngx_http_headers_more_check_status(ngx_http_request_t *r, ngx_array_t *statuses)
|
||||||
|
{
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_uint_t *status;
|
||||||
|
|
||||||
|
dd("headers_out.status = %d", (int) r->headers_out.status);
|
||||||
|
|
||||||
|
status = statuses->elts;
|
||||||
|
for (i = 0; i < statuses->nelts; i++) {
|
||||||
|
dd("...comparing with specified status %d", (int) status[i]);
|
||||||
|
|
||||||
|
if (r->headers_out.status == status[i]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
|
||||||
|
void *conf, ngx_http_headers_more_opcode_t opcode)
|
||||||
|
{
|
||||||
|
ngx_http_headers_more_loc_conf_t *hlcf = conf;
|
||||||
|
|
||||||
|
ngx_uint_t i, j;
|
||||||
|
ngx_http_headers_more_cmd_t *cmd;
|
||||||
|
ngx_str_t *arg;
|
||||||
|
ngx_flag_t ignore_next_arg;
|
||||||
|
ngx_str_t *cmd_name;
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_flag_t append = 0;
|
||||||
|
ngx_flag_t is_builtin_header = 0;
|
||||||
|
ngx_http_headers_more_header_val_t *h;
|
||||||
|
ngx_http_headers_more_set_header_t *handlers;
|
||||||
|
|
||||||
|
ngx_http_headers_more_main_conf_t *hmcf;
|
||||||
|
|
||||||
|
if (hlcf->cmds == NULL) {
|
||||||
|
hlcf->cmds = ngx_array_create(cf->pool, 1,
|
||||||
|
sizeof(ngx_http_headers_more_cmd_t));
|
||||||
|
|
||||||
|
if (hlcf->cmds == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = ngx_array_push(hlcf->cmds);
|
||||||
|
if (cmd == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->headers =
|
||||||
|
ngx_array_create(cf->pool, 1,
|
||||||
|
sizeof(ngx_http_headers_more_header_val_t));
|
||||||
|
if (cmd->headers == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
|
||||||
|
if (cmd->types == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->statuses = ngx_array_create(cf->pool, 1, sizeof(ngx_uint_t));
|
||||||
|
if (cmd->statuses == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = cf->args->elts;
|
||||||
|
|
||||||
|
cmd_name = &arg[0];
|
||||||
|
|
||||||
|
ignore_next_arg = 0;
|
||||||
|
|
||||||
|
for (i = 1; i < cf->args->nelts; i++) {
|
||||||
|
|
||||||
|
if (ignore_next_arg) {
|
||||||
|
ignore_next_arg = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[i].len == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[i].data[0] != '-') {
|
||||||
|
rc = ngx_http_headers_more_parse_header(cf, cmd_name,
|
||||||
|
&arg[i], cmd->headers,
|
||||||
|
opcode,
|
||||||
|
ngx_http_headers_more_set_handlers);
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg[i].len == 2) {
|
||||||
|
if (arg[i].data[1] == 't') {
|
||||||
|
if (i == cf->args->nelts - 1) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: option -t takes an argument.",
|
||||||
|
cmd_name);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_http_headers_more_parse_types(cf->log, cmd_name,
|
||||||
|
&arg[i + 1],
|
||||||
|
cmd->types);
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignore_next_arg = 1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else if (arg[i].data[1] == 's') {
|
||||||
|
|
||||||
|
if (i == cf->args->nelts - 1) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: option -s takes an argument.",
|
||||||
|
cmd_name);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_http_headers_more_parse_statuses(cf->log, cmd_name,
|
||||||
|
&arg[i + 1],
|
||||||
|
cmd->statuses);
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignore_next_arg = 1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else if (arg[i].data[1] == 'a') {
|
||||||
|
|
||||||
|
if (ngx_strncasecmp((u_char *) "more_set_headers",
|
||||||
|
cmd_name->data, cmd_name->len) != 0)
|
||||||
|
{
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: invalid option name: \"%V\"",
|
||||||
|
cmd_name, &arg[i]);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("Found append flag");
|
||||||
|
append = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: invalid option name: \"%V\"", cmd_name, &arg[i]);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd("Found %d statuses, %d types, and %d headers",
|
||||||
|
(int) cmd->statuses->nelts, (int) cmd->types->nelts,
|
||||||
|
(int) cmd->headers->nelts);
|
||||||
|
|
||||||
|
if (cmd->headers->nelts == 0) {
|
||||||
|
cmd->headers = NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
h = cmd->headers->elts;
|
||||||
|
for (i = 0; i < cmd->headers->nelts; i++) {
|
||||||
|
h[i].append = 0;
|
||||||
|
|
||||||
|
handlers = ngx_http_headers_more_set_handlers;
|
||||||
|
|
||||||
|
for (j = 0; handlers[j].name.len; j++) {
|
||||||
|
if (h[i].key.len == handlers[j].name.len
|
||||||
|
&& ngx_strncasecmp(h[i].key.data, handlers[j].name.data,
|
||||||
|
h[i].key.len) == 0)
|
||||||
|
{
|
||||||
|
is_builtin_header = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_builtin_header && append) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: can not append builtin headers \"%V\"",
|
||||||
|
cmd_name, &h[i].key);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_builtin_header) {
|
||||||
|
h[i].append = append;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->types->nelts == 0) {
|
||||||
|
cmd->types = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->statuses->nelts == 0) {
|
||||||
|
cmd->statuses = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->is_input = 0;
|
||||||
|
|
||||||
|
hmcf = ngx_http_conf_get_module_main_conf(cf,
|
||||||
|
ngx_http_headers_more_filter_module);
|
||||||
|
|
||||||
|
hmcf->requires_filter = 1;
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
26
ngx_headers_more/src/ngx_http_headers_more_headers_out.h
Normal file
26
ngx_headers_more/src/ngx_http_headers_more_headers_out.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) Yichun Zhang (agentzh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NGX_HTTP_HEADERS_MORE_OUTPUT_HEADERS_H
|
||||||
|
#define NGX_HTTP_HEADERS_MORE_OUTPUT_HEADERS_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "ngx_http_headers_more_filter_module.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* output header setters and clearers */
|
||||||
|
|
||||||
|
ngx_int_t ngx_http_headers_more_exec_cmd(ngx_http_request_t *r,
|
||||||
|
ngx_http_headers_more_cmd_t *cmd);
|
||||||
|
|
||||||
|
char *ngx_http_headers_more_set_headers(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd, void *conf);
|
||||||
|
|
||||||
|
char *ngx_http_headers_more_clear_headers(ngx_conf_t *cf,
|
||||||
|
ngx_command_t *cmd, void *conf);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* NGX_HTTP_HEADERS_MORE_OUTPUT_HEADERS_H */
|
||||||
382
ngx_headers_more/src/ngx_http_headers_more_util.c
Normal file
382
ngx_headers_more/src/ngx_http_headers_more_util.c
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Yichun Zhang (agentzh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DDEBUG
|
||||||
|
#define DDEBUG 0
|
||||||
|
#endif
|
||||||
|
#include "ddebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "ngx_http_headers_more_util.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_headers_more_parse_header(ngx_conf_t *cf, ngx_str_t *cmd_name,
|
||||||
|
ngx_str_t *raw_header, ngx_array_t *headers,
|
||||||
|
ngx_http_headers_more_opcode_t opcode,
|
||||||
|
ngx_http_headers_more_set_header_t *handlers)
|
||||||
|
{
|
||||||
|
ngx_http_headers_more_header_val_t *hv;
|
||||||
|
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_str_t key = ngx_null_string;
|
||||||
|
ngx_str_t value = ngx_null_string;
|
||||||
|
ngx_flag_t seen_end_of_key;
|
||||||
|
ngx_http_compile_complex_value_t ccv;
|
||||||
|
u_char *p;
|
||||||
|
|
||||||
|
hv = ngx_array_push(headers);
|
||||||
|
if (hv == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
seen_end_of_key = 0;
|
||||||
|
for (i = 0; i < raw_header->len; i++) {
|
||||||
|
if (key.len == 0) {
|
||||||
|
if (isspace(raw_header->data[i])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
key.data = raw_header->data;
|
||||||
|
key.len = 1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seen_end_of_key) {
|
||||||
|
if (raw_header->data[i] == ':'
|
||||||
|
|| isspace(raw_header->data[i]))
|
||||||
|
{
|
||||||
|
seen_end_of_key = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
key.len++;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.len == 0) {
|
||||||
|
if (raw_header->data[i] == ':'
|
||||||
|
|| isspace(raw_header->data[i]))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
value.data = &raw_header->data[i];
|
||||||
|
value.len = 1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
value.len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.len == 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: no key found in the header argument: %V",
|
||||||
|
cmd_name, raw_header);
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
hv->wildcard = (key.data[key.len - 1] == '*');
|
||||||
|
if (hv->wildcard && key.len<2){
|
||||||
|
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||||
|
"%V: wildcard key too short: %V",
|
||||||
|
cmd_name, raw_header);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
hv->hash = ngx_hash_key_lc(key.data, key.len);
|
||||||
|
hv->key = key;
|
||||||
|
|
||||||
|
hv->offset = 0;
|
||||||
|
|
||||||
|
for (i = 0; handlers[i].name.len; i++) {
|
||||||
|
if (hv->key.len != handlers[i].name.len
|
||||||
|
|| ngx_strncasecmp(hv->key.data, handlers[i].name.data,
|
||||||
|
handlers[i].name.len) != 0)
|
||||||
|
{
|
||||||
|
dd("hv key comparison: %s <> %s", handlers[i].name.data,
|
||||||
|
hv->key.data);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hv->offset = handlers[i].offset;
|
||||||
|
hv->handler = handlers[i].handler;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handlers[i].name.len == 0 && handlers[i].handler) {
|
||||||
|
hv->offset = handlers[i].offset;
|
||||||
|
hv->handler = handlers[i].handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcode == ngx_http_headers_more_opcode_clear) {
|
||||||
|
value.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.len == 0) {
|
||||||
|
ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t));
|
||||||
|
return NGX_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nginx request header value requires to be a null-terminated
|
||||||
|
* C string */
|
||||||
|
|
||||||
|
p = ngx_palloc(cf->pool, value.len + 1);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memcpy(p, value.data, value.len);
|
||||||
|
p[value.len] = '\0';
|
||||||
|
value.data = p;
|
||||||
|
value.len++; /* we should also compile the trailing '\0' */
|
||||||
|
|
||||||
|
/* compile the header value as a complex value */
|
||||||
|
|
||||||
|
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
|
||||||
|
|
||||||
|
ccv.cf = cf;
|
||||||
|
ccv.value = &value;
|
||||||
|
ccv.complex_value = &hv->value;
|
||||||
|
|
||||||
|
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_headers_more_parse_statuses(ngx_log_t *log, ngx_str_t *cmd_name,
|
||||||
|
ngx_str_t *value, ngx_array_t *statuses)
|
||||||
|
{
|
||||||
|
u_char *p, *last;
|
||||||
|
ngx_uint_t *s = NULL;
|
||||||
|
|
||||||
|
p = value->data;
|
||||||
|
last = p + value->len;
|
||||||
|
|
||||||
|
for (; p != last; p++) {
|
||||||
|
if (s == NULL) {
|
||||||
|
if (isspace(*p)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = ngx_array_push(statuses);
|
||||||
|
if (s == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p >= '0' && *p <= '9') {
|
||||||
|
*s = *p - '0';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, log, 0,
|
||||||
|
"%V: invalid digit \"%c\" found in "
|
||||||
|
"the status code list \"%V\"",
|
||||||
|
cmd_name, *p, value);
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isspace(*p)) {
|
||||||
|
dd("Parsed status %d", (int) *s);
|
||||||
|
|
||||||
|
s = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p >= '0' && *p <= '9') {
|
||||||
|
*s *= 10;
|
||||||
|
*s += *p - '0';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, log, 0,
|
||||||
|
"%V: invalid digit \"%c\" found in "
|
||||||
|
"the status code list \"%V\"",
|
||||||
|
cmd_name, *p, value);
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s) {
|
||||||
|
dd("Parsed status %d", (int) *s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_headers_more_parse_types(ngx_log_t *log, ngx_str_t *cmd_name,
|
||||||
|
ngx_str_t *value, ngx_array_t *types)
|
||||||
|
{
|
||||||
|
u_char *p, *last;
|
||||||
|
ngx_str_t *t = NULL;
|
||||||
|
|
||||||
|
p = value->data;
|
||||||
|
last = p + value->len;
|
||||||
|
|
||||||
|
for (; p != last; p++) {
|
||||||
|
if (t == NULL) {
|
||||||
|
if (isspace(*p) || *p == ';') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = ngx_array_push(types);
|
||||||
|
if (t == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->len = 1;
|
||||||
|
t->data = p;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isspace(*p) || *p == ';') {
|
||||||
|
t = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_http_headers_more_rm_header_helper(ngx_list_t *l, ngx_list_part_t *cur,
|
||||||
|
ngx_uint_t i)
|
||||||
|
{
|
||||||
|
ngx_table_elt_t *data;
|
||||||
|
ngx_list_part_t *new, *part;
|
||||||
|
|
||||||
|
dd("list rm item: part %p, i %d, nalloc %d", cur, (int) i,
|
||||||
|
(int) l->nalloc);
|
||||||
|
|
||||||
|
data = cur->elts;
|
||||||
|
|
||||||
|
dd("cur: nelts %d, nalloc %d", (int) cur->nelts,
|
||||||
|
(int) l->nalloc);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
cur->elts = (char *) cur->elts + l->size;
|
||||||
|
cur->nelts--;
|
||||||
|
|
||||||
|
if (cur == l->last) {
|
||||||
|
if (cur->nelts == 0) {
|
||||||
|
#if 1
|
||||||
|
part = &l->part;
|
||||||
|
|
||||||
|
if (part == cur) {
|
||||||
|
cur->elts = (char *) cur->elts - l->size;
|
||||||
|
/* do nothing */
|
||||||
|
|
||||||
|
} else {
|
||||||
|
while (part->next != cur) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
l->last = part;
|
||||||
|
part->next = NULL;
|
||||||
|
dd("part nelts: %d", (int) part->nelts);
|
||||||
|
l->nalloc = part->nelts;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else {
|
||||||
|
l->nalloc--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->nelts == 0) {
|
||||||
|
part = &l->part;
|
||||||
|
|
||||||
|
if (part == cur) {
|
||||||
|
ngx_http_headers_more_assert(cur->next != NULL);
|
||||||
|
|
||||||
|
dd("remove 'cur' from the list by rewriting 'cur': "
|
||||||
|
"l->last: %p, cur: %p, cur->next: %p, part: %p",
|
||||||
|
l->last, cur, cur->next, part);
|
||||||
|
|
||||||
|
if (l->last == cur->next) {
|
||||||
|
dd("last is cur->next");
|
||||||
|
l->part = *(cur->next);
|
||||||
|
l->last = part;
|
||||||
|
l->nalloc = part->nelts;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
l->part = *(cur->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dd("remove 'cur' from the list");
|
||||||
|
while (part->next != cur) {
|
||||||
|
if (part->next == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
part = part->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
part->next = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == cur->nelts - 1) {
|
||||||
|
cur->nelts--;
|
||||||
|
|
||||||
|
if (cur == l->last) {
|
||||||
|
l->nalloc = cur->nelts;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
new = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
|
||||||
|
if (new == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
new->elts = &data[i + 1];
|
||||||
|
new->nelts = cur->nelts - i - 1;
|
||||||
|
new->next = cur->next;
|
||||||
|
|
||||||
|
cur->nelts = i;
|
||||||
|
cur->next = new;
|
||||||
|
if (cur == l->last) {
|
||||||
|
l->last = new;
|
||||||
|
l->nalloc = new->nelts;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
52
ngx_headers_more/src/ngx_http_headers_more_util.h
Normal file
52
ngx_headers_more/src/ngx_http_headers_more_util.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) Yichun Zhang (agentzh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NGX_HTTP_HEADERS_MORE_UTIL_H
|
||||||
|
#define NGX_HTTP_HEADERS_MORE_UTIL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "ngx_http_headers_more_filter_module.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define ngx_http_headers_more_hash_literal(s) \
|
||||||
|
ngx_http_headers_more_hash_str((u_char *) s, sizeof(s) - 1)
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_inline ngx_uint_t
|
||||||
|
ngx_http_headers_more_hash_str(u_char *src, size_t n)
|
||||||
|
{
|
||||||
|
ngx_uint_t key;
|
||||||
|
|
||||||
|
key = 0;
|
||||||
|
|
||||||
|
while (n--) {
|
||||||
|
key = ngx_hash(key, *src);
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern ngx_uint_t ngx_http_headers_more_location_hash;
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t ngx_http_headers_more_parse_header(ngx_conf_t *cf,
|
||||||
|
ngx_str_t *cmd_name, ngx_str_t *raw_header, ngx_array_t *headers,
|
||||||
|
ngx_http_headers_more_opcode_t opcode,
|
||||||
|
ngx_http_headers_more_set_header_t *handlers);
|
||||||
|
|
||||||
|
ngx_int_t ngx_http_headers_more_parse_statuses(ngx_log_t *log,
|
||||||
|
ngx_str_t *cmd_name, ngx_str_t *value, ngx_array_t *statuses);
|
||||||
|
|
||||||
|
ngx_int_t ngx_http_headers_more_parse_types(ngx_log_t *log,
|
||||||
|
ngx_str_t *cmd_name, ngx_str_t *value, ngx_array_t *types);
|
||||||
|
|
||||||
|
ngx_int_t ngx_http_headers_more_rm_header_helper(ngx_list_t *l,
|
||||||
|
ngx_list_part_t *cur, ngx_uint_t i);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* NGX_HTTP_HEADERS_MORE_UTIL_H */
|
||||||
461
ngx_headers_more/t/bug.t
Normal file
461
ngx_headers_more/t/bug.t
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
# vi:filetype=
|
||||||
|
|
||||||
|
use Test::Nginx::Socket; # 'no_plan';
|
||||||
|
|
||||||
|
repeat_each(2);
|
||||||
|
|
||||||
|
plan tests => 62 * repeat_each();
|
||||||
|
|
||||||
|
no_diff;
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: set Server
|
||||||
|
--- config
|
||||||
|
#more_set_headers 'Last-Modified: x';
|
||||||
|
more_clear_headers 'Last-Modified';
|
||||||
|
--- request
|
||||||
|
GET /index.html
|
||||||
|
--- response_headers
|
||||||
|
! Last-Modified
|
||||||
|
--- response_body_like: It works!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: variables in the Ranges header
|
||||||
|
--- config
|
||||||
|
location /index.html {
|
||||||
|
set $rfrom 1;
|
||||||
|
set $rto 3;
|
||||||
|
more_set_input_headers 'Range: bytes=$rfrom - $rto';
|
||||||
|
#more_set_input_headers 'Range: bytes=1 - 3';
|
||||||
|
#echo $http_range;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /index.html
|
||||||
|
--- error_code: 206
|
||||||
|
--- response_body chomp
|
||||||
|
htm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: mime type overriding (inlined types)
|
||||||
|
--- config
|
||||||
|
more_clear_headers 'X-Powered-By' 'X-Runtime' 'ETag';
|
||||||
|
|
||||||
|
types {
|
||||||
|
text/html html htm shtml;
|
||||||
|
text/css css;
|
||||||
|
}
|
||||||
|
--- user_files
|
||||||
|
>>> a.css
|
||||||
|
hello
|
||||||
|
--- request
|
||||||
|
GET /a.css
|
||||||
|
--- error_code: 200
|
||||||
|
--- response_headers
|
||||||
|
Content-Type: text/css
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 4: mime type overriding (included types file)
|
||||||
|
--- config
|
||||||
|
more_clear_headers 'X-Powered-By' 'X-Runtime' 'ETag';
|
||||||
|
include mime.types;
|
||||||
|
--- user_files
|
||||||
|
>>> a.css
|
||||||
|
hello
|
||||||
|
>>> ../conf/mime.types
|
||||||
|
types {
|
||||||
|
text/html html htm shtml;
|
||||||
|
text/css css;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /a.css
|
||||||
|
--- error_code: 200
|
||||||
|
--- response_headers
|
||||||
|
Content-Type: text/css
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 5: empty variable as the header value
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
more_set_headers 'X-Foo: $arg_foo';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
! X-Foo
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 6: range bug
|
||||||
|
--- config
|
||||||
|
location /index.html {
|
||||||
|
more_clear_input_headers "Range*" ;
|
||||||
|
more_clear_input_headers "Content-Range*" ;
|
||||||
|
|
||||||
|
more_set_input_headers 'Range: bytes=1-5';
|
||||||
|
more_set_headers 'Content-Range: bytes 1-5/1000';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /index.html
|
||||||
|
--- more_headers
|
||||||
|
Range: bytes=1-3
|
||||||
|
--- raw_response_headers_like: Content-Range: bytes 1-5/1000$
|
||||||
|
--- response_body chop
|
||||||
|
html>
|
||||||
|
--- error_code: 206
|
||||||
|
--- SKIP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 7: Allow-Ranges
|
||||||
|
--- config
|
||||||
|
location /index.html {
|
||||||
|
more_clear_headers 'Accept-Ranges';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /index.html
|
||||||
|
--- response_headers
|
||||||
|
! Accept-Ranges
|
||||||
|
--- response_body_like: It works
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 8: clear hand-written Allow-Ranges headers
|
||||||
|
--- config
|
||||||
|
location /index.html {
|
||||||
|
more_set_headers 'Accept-Ranges: bytes';
|
||||||
|
more_clear_headers 'Accept-Ranges';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /index.html
|
||||||
|
--- response_headers
|
||||||
|
! Accept-Ranges
|
||||||
|
--- response_body_like: It works
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 9: clear first, then add
|
||||||
|
--- config
|
||||||
|
location /bug {
|
||||||
|
more_clear_headers 'Foo';
|
||||||
|
more_set_headers 'Foo: a';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bug
|
||||||
|
--- raw_response_headers_like eval
|
||||||
|
".*Foo: a.*"
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 10: first add, then clear, then add again
|
||||||
|
--- config
|
||||||
|
location /bug {
|
||||||
|
more_set_headers 'Foo: a';
|
||||||
|
more_clear_headers 'Foo';
|
||||||
|
more_set_headers 'Foo: b';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bug
|
||||||
|
--- raw_response_headers_like eval
|
||||||
|
".*Foo: b.*"
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 11: override charset
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
charset iso-8859-1;
|
||||||
|
default_type "text/html";
|
||||||
|
echo hiya;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /bug {
|
||||||
|
more_set_headers "Content-Type: text/html; charset=UTF-8";
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/foo;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bug
|
||||||
|
--- response_body
|
||||||
|
hiya
|
||||||
|
--- response_headers
|
||||||
|
Content-Type: text/html; charset=UTF-8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 12: set multi-value header to a single value
|
||||||
|
--- config
|
||||||
|
location /main {
|
||||||
|
set $footer '';
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/foo;
|
||||||
|
more_set_headers 'Foo: b';
|
||||||
|
header_filter_by_lua '
|
||||||
|
ngx.var.footer = ngx.header.Foo
|
||||||
|
';
|
||||||
|
echo_after_body $footer;
|
||||||
|
}
|
||||||
|
location /foo {
|
||||||
|
echo foo;
|
||||||
|
add_header Foo a;
|
||||||
|
add_header Foo c;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /main
|
||||||
|
--- response_headers
|
||||||
|
Foo: b
|
||||||
|
--- response_body
|
||||||
|
foo
|
||||||
|
b
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 13: set multi values to cache-control and override it with multiple values (to reproduce a bug)
|
||||||
|
--- config
|
||||||
|
location /lua {
|
||||||
|
content_by_lua '
|
||||||
|
ngx.header.cache_control = { "private", "no-store", "foo", "bar", "baz" }
|
||||||
|
ngx.send_headers()
|
||||||
|
ngx.say("Cache-Control: ", ngx.var.sent_http_cache_control)
|
||||||
|
';
|
||||||
|
more_clear_headers Cache-Control;
|
||||||
|
add_header Cache-Control "blah";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /lua
|
||||||
|
--- response_headers
|
||||||
|
Cache-Control: blah
|
||||||
|
--- response_body
|
||||||
|
Cache-Control: blah
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 14: set 20+ headers
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
more_clear_input_headers "Authorization";
|
||||||
|
echo $http_a1;
|
||||||
|
echo $http_authorization;
|
||||||
|
echo $http_a2;
|
||||||
|
echo $http_a3;
|
||||||
|
echo $http_a23;
|
||||||
|
echo $http_a24;
|
||||||
|
echo $http_a25;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
--- more_headers eval
|
||||||
|
my $i = 1;
|
||||||
|
my $s;
|
||||||
|
while ($i <= 25) {
|
||||||
|
$s .= "A$i: $i\n";
|
||||||
|
if ($i == 22) {
|
||||||
|
$s .= "Authorization: blah\n";
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
#warn $s;
|
||||||
|
$s
|
||||||
|
--- response_body
|
||||||
|
1
|
||||||
|
|
||||||
|
2
|
||||||
|
3
|
||||||
|
23
|
||||||
|
24
|
||||||
|
25
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 15: github #20: segfault caused by the nasty optimization in the nginx core (set)
|
||||||
|
--- config
|
||||||
|
location = /t/ {
|
||||||
|
more_set_headers "Foo: 1";
|
||||||
|
proxy_pass http://127.0.0.1:$server_port;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- more_headers
|
||||||
|
Foo: bar
|
||||||
|
Bah: baz
|
||||||
|
--- response_body_like: 301 Moved Permanently
|
||||||
|
--- error_code: 301
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 16: github #20: segfault caused by the nasty optimization in the nginx core (clear)
|
||||||
|
--- config
|
||||||
|
location = /t/ {
|
||||||
|
more_clear_headers Foo;
|
||||||
|
proxy_pass http://127.0.0.1:$server_port;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- more_headers
|
||||||
|
Foo: bar
|
||||||
|
Bah: baz
|
||||||
|
--- response_body_like: 301 Moved Permanently
|
||||||
|
--- error_code: 301
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 17: Content-Type response headers with a charset param (correct -t values)
|
||||||
|
--- config
|
||||||
|
location = /t {
|
||||||
|
more_set_headers -t 'text/html' 'X-Foo: Bar';
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/fake;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /fake {
|
||||||
|
default_type text/html;
|
||||||
|
charset utf-8;
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- response_headers
|
||||||
|
X-Foo: Bar
|
||||||
|
--- response_body
|
||||||
|
ok
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 18: Content-Type response headers with a charset param (WRONG -t values)
|
||||||
|
--- config
|
||||||
|
location = /t {
|
||||||
|
more_set_headers -t 'text/html; charset=utf-8' 'X-Foo: Bar';
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/fake;
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /fake {
|
||||||
|
default_type text/html;
|
||||||
|
charset utf-8;
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- response_headers
|
||||||
|
X-Foo: Bar
|
||||||
|
--- response_body
|
||||||
|
ok
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 19: for bad requests (bad request method letter case)
|
||||||
|
--- config
|
||||||
|
error_page 400 = /err;
|
||||||
|
|
||||||
|
location = /err {
|
||||||
|
more_set_input_headers "Foo: bar";
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- raw_request
|
||||||
|
GeT / HTTP/1.1
|
||||||
|
--- response_body
|
||||||
|
ok
|
||||||
|
--- no_check_leak
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 20: for bad requests (bad request method names)
|
||||||
|
--- config
|
||||||
|
error_page 400 = /err;
|
||||||
|
|
||||||
|
location = /err {
|
||||||
|
more_set_input_headers "Foo: bar";
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- raw_request
|
||||||
|
GET x HTTP/1.1
|
||||||
|
--- response_body
|
||||||
|
ok
|
||||||
|
--- no_check_leak
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 21: override Cache-Control header sent by proxy module
|
||||||
|
--- config
|
||||||
|
location = /back {
|
||||||
|
content_by_lua_block {
|
||||||
|
ngx.header['Cache-Control'] = 'max-age=0, no-cache'
|
||||||
|
ngx.send_headers()
|
||||||
|
ngx.say("Cache-Control: ", ngx.var.sent_http_cache_control)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /t {
|
||||||
|
more_set_headers "Cache-Control: max-age=1800";
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/back;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- response_headers
|
||||||
|
Cache-Control: max-age=1800
|
||||||
|
--- response_body
|
||||||
|
Cache-Control: max-age=0, no-cache
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 22: 401 from upstream without WWW-Authenticate header
|
||||||
|
--- config
|
||||||
|
location = /back {
|
||||||
|
content_by_lua_block {
|
||||||
|
ngx.exit(401)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /t {
|
||||||
|
more_set_headers -s "401" 'WWW-Authenticate: Bearer realm="https://my.org/auth"';
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/back;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- error_code: 401
|
||||||
|
--- response_headers
|
||||||
|
WWW-Authenticate: Bearer realm="https://my.org/auth"
|
||||||
|
--- response_body eval
|
||||||
|
qr/401 Authorization Required/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 23: 401 from upstream with WWW-Authenticate header
|
||||||
|
--- config
|
||||||
|
location = /back {
|
||||||
|
more_set_headers -s "401" 'WWW-Authenticate: Bearer realm="https://my.org/auth1"';
|
||||||
|
content_by_lua_block {
|
||||||
|
ngx.exit(401)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /t {
|
||||||
|
more_set_headers -s "401" 'WWW-Authenticate: Bearer realm="https://my.org/auth"';
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/back;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- error_code: 401
|
||||||
|
--- response_headers
|
||||||
|
WWW-Authenticate: Bearer realm="https://my.org/auth"
|
||||||
|
--- response_body eval
|
||||||
|
qr/401 Authorization Required/
|
||||||
338
ngx_headers_more/t/builtin.t
Normal file
338
ngx_headers_more/t/builtin.t
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
# vi:filetype=
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket; # 'no_plan';
|
||||||
|
|
||||||
|
plan tests => 60;
|
||||||
|
|
||||||
|
no_diff;
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: set Server
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
more_set_headers 'Server: Foo';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
Server: Foo
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: clear Server
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
more_clear_headers 'Server: ';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
! Server
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: set Content-Type
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
default_type 'text/plan';
|
||||||
|
more_set_headers 'Content-Type: text/css';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
Content-Type: text/css
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 4: set Content-Type
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
default_type 'text/plan';
|
||||||
|
more_set_headers 'Content-Type: text/css';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
Content-Type: text/css
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 5: clear Content-Type
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_clear_headers 'Content-Type: ';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
! Content-Type
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 6: clear Content-Type (colon not required)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Content-Type: Hello';
|
||||||
|
more_clear_headers 'Content-Type';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
! Content-Type
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 7: clear Content-Type (value ignored)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Content-Type: Hello';
|
||||||
|
more_clear_headers 'Content-Type: blah';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
! Content-Type
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 8: clear Content-Type (case insensitive)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Content-Type: Hello';
|
||||||
|
more_clear_headers 'content-type: blah';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
! Content-Type
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 9: clear Content-Type using set empty
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Content-Type: Hello';
|
||||||
|
more_set_headers 'content-type:';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
! Content-Type
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 10: clear Content-Type using setting key only
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Content-Type: Hello';
|
||||||
|
more_set_headers 'content-type';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
! Content-Type
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 11: set content-length
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
more_set_headers 'Content-Length: 2';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 2
|
||||||
|
--- response_body chop
|
||||||
|
he
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 12: set content-length multiple times
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
more_set_headers 'Content-Length: 2';
|
||||||
|
more_set_headers 'Content-Length: 4';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 4
|
||||||
|
--- response_body chop
|
||||||
|
hell
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 13: clear content-length
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
more_set_headers 'Content-Length: 4';
|
||||||
|
more_set_headers 'Content-Length:';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
! Content-Length
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 14: clear content-length (another way)
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
more_set_headers 'Content-Length: 4';
|
||||||
|
more_clear_headers 'Content-Length';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
! Content-Length
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 15: clear content-type
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Content-Type:';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
! Content-Type
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 16: clear content-type (the other way)
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_clear_headers 'Content-Type:';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
! Content-Type
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 17: set Charset
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Charset: gbk';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
Charset: gbk
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 18: clear Charset
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Charset: gbk';
|
||||||
|
more_clear_headers 'Charset';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
! Charset
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 19: clear Charset (the other way: using set)
|
||||||
|
--- config
|
||||||
|
location /len {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Charset: gbk';
|
||||||
|
more_set_headers 'Charset: ';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
! Charset
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 20: set Vary
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
more_set_headers 'Vary: gbk';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
location /len {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers 'Vary: hello';
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/foo;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /len
|
||||||
|
--- response_headers
|
||||||
|
Vary: hello
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
36
ngx_headers_more/t/eval.t
Normal file
36
ngx_headers_more/t/eval.t
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# vi:filetype=
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket; # 'no_plan';
|
||||||
|
|
||||||
|
repeat_each(3);
|
||||||
|
|
||||||
|
plan tests => repeat_each() * 2 * blocks();
|
||||||
|
|
||||||
|
#no_long_string();
|
||||||
|
#no_diff;
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: set request header at client side
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
eval_subrequest_in_memory off;
|
||||||
|
eval_override_content_type text/plain;
|
||||||
|
eval $res {
|
||||||
|
echo -n 1;
|
||||||
|
}
|
||||||
|
#echo "[$res]";
|
||||||
|
if ($res = '1') {
|
||||||
|
more_set_input_headers 'Foo: Bar';
|
||||||
|
echo "OK";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
echo "NOT OK";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_body
|
||||||
|
OK
|
||||||
137
ngx_headers_more/t/input-conn.t
Normal file
137
ngx_headers_more/t/input-conn.t
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
# vim:set ft= ts=4 sw=4 et fdm=marker:
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket;
|
||||||
|
|
||||||
|
#worker_connections(1014);
|
||||||
|
#master_process_enabled(1);
|
||||||
|
#log_level('warn');
|
||||||
|
|
||||||
|
repeat_each(2);
|
||||||
|
|
||||||
|
plan tests => repeat_each() * (4 * blocks());
|
||||||
|
|
||||||
|
#no_diff();
|
||||||
|
no_long_string();
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: clear the Connection req header
|
||||||
|
--- config
|
||||||
|
location /req-header {
|
||||||
|
more_clear_input_headers Connection;
|
||||||
|
echo "connection: $http_connection";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /req-header
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: conn type: %d\n", $r->headers_in->connection_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: conn type: 1
|
||||||
|
content: conn type: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
connection:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: set custom Connection req header (close)
|
||||||
|
--- config
|
||||||
|
location /req-header {
|
||||||
|
more_set_input_headers "Connection: CLOSE";
|
||||||
|
echo "connection: $http_connection";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /req-header
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: conn type: %d\n", $r->headers_in->connection_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: conn type: 1
|
||||||
|
content: conn type: 1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
connection: CLOSE
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: set custom Connection req header (keep-alive)
|
||||||
|
--- config
|
||||||
|
location /req-header {
|
||||||
|
more_set_input_headers "Connection: keep-alive";
|
||||||
|
echo "connection: $http_connection";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /req-header
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: conn type: %d\n", $r->headers_in->connection_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: conn type: 1
|
||||||
|
content: conn type: 2
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
connection: keep-alive
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 4: set custom Connection req header (bad)
|
||||||
|
--- config
|
||||||
|
location /req-header {
|
||||||
|
more_set_input_headers "Connection: bad";
|
||||||
|
echo "connection: $http_connection";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /req-header
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: conn type: %d\n", $r->headers_in->connection_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: conn type: %d\n", $r->headers_in->connection_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: conn type: 1
|
||||||
|
content: conn type: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
connection: bad
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
183
ngx_headers_more/t/input-cookie.t
Normal file
183
ngx_headers_more/t/input-cookie.t
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
# vim:set ft= ts=4 sw=4 et fdm=marker:
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket;
|
||||||
|
|
||||||
|
#worker_connections(1014);
|
||||||
|
#master_process_enabled(1);
|
||||||
|
#log_level('warn');
|
||||||
|
|
||||||
|
repeat_each(2);
|
||||||
|
|
||||||
|
plan tests => repeat_each() * (4 * blocks());
|
||||||
|
|
||||||
|
#no_diff();
|
||||||
|
no_long_string();
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: clear cookie (with existing cookies)
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers Cookie;
|
||||||
|
echo "Cookie foo: $cookie_foo";
|
||||||
|
echo "Cookie baz: $cookie_baz";
|
||||||
|
echo "Cookie: $http_cookie";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- more_headers
|
||||||
|
Cookie: foo=bar
|
||||||
|
Cookie: baz=blah
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: cookies: %d\n", $r->headers_in->cookies->nelts)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: cookies: %d\n", $r->headers_in->cookies->nelts)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: cookies: 2
|
||||||
|
content: cookies: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
Cookie foo:
|
||||||
|
Cookie baz:
|
||||||
|
Cookie:
|
||||||
|
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: clear cookie (without existing cookies)
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers Cookie;
|
||||||
|
echo "Cookie foo: $cookie_foo";
|
||||||
|
echo "Cookie baz: $cookie_baz";
|
||||||
|
echo "Cookie: $http_cookie";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: cookies: %d\n", $r->headers_in->cookies->nelts)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: cookies: %d\n", $r->headers_in->cookies->nelts)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: cookies: 0
|
||||||
|
content: cookies: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
Cookie foo:
|
||||||
|
Cookie baz:
|
||||||
|
Cookie:
|
||||||
|
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: set one custom cookie (with existing cookies)
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "Cookie: boo=123";
|
||||||
|
echo "Cookie foo: $cookie_foo";
|
||||||
|
echo "Cookie baz: $cookie_baz";
|
||||||
|
echo "Cookie boo: $cookie_boo";
|
||||||
|
echo "Cookie: $http_cookie";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
--- more_headers
|
||||||
|
Cookie: foo=bar
|
||||||
|
Cookie: baz=blah
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: cookies: %d\n", $r->headers_in->cookies->nelts)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: cookies: %d\n", $r->headers_in->cookies->nelts)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: cookies: 2
|
||||||
|
content: cookies: 1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
Cookie foo:
|
||||||
|
Cookie baz:
|
||||||
|
Cookie boo: 123
|
||||||
|
Cookie: boo=123
|
||||||
|
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 4: set one custom cookie (without existing cookies)
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "Cookie: boo=123";
|
||||||
|
echo "Cookie foo: $cookie_foo";
|
||||||
|
echo "Cookie baz: $cookie_baz";
|
||||||
|
echo "Cookie boo: $cookie_boo";
|
||||||
|
echo "Cookie: $http_cookie";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: cookies: %d\n", $r->headers_in->cookies->nelts)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: cookies: %d\n", $r->headers_in->cookies->nelts)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: cookies: 0
|
||||||
|
content: cookies: 1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
Cookie foo:
|
||||||
|
Cookie baz:
|
||||||
|
Cookie boo: 123
|
||||||
|
Cookie: boo=123
|
||||||
|
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 5: for bad requests causing segfaults when setting & getting multi-value headers
|
||||||
|
--- config
|
||||||
|
error_page 400 = /err;
|
||||||
|
|
||||||
|
location = /err {
|
||||||
|
more_set_input_headers "Cookie: foo=bar";
|
||||||
|
echo -n $cookie_foo;
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- raw_request
|
||||||
|
GeT / HTTP/1.1
|
||||||
|
--- response_body
|
||||||
|
ok
|
||||||
|
--- no_error_log
|
||||||
|
[warn]
|
||||||
|
[error]
|
||||||
|
--- no_check_leak
|
||||||
628
ngx_headers_more/t/input-ua.t
Normal file
628
ngx_headers_more/t/input-ua.t
Normal file
@@ -0,0 +1,628 @@
|
|||||||
|
# vim:set ft= ts=4 sw=4 et fdm=marker:
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket;
|
||||||
|
|
||||||
|
#worker_connections(1014);
|
||||||
|
#master_process_enabled(1);
|
||||||
|
#log_level('warn');
|
||||||
|
|
||||||
|
repeat_each(2);
|
||||||
|
|
||||||
|
plan tests => repeat_each() * (4 * blocks());
|
||||||
|
|
||||||
|
#no_diff();
|
||||||
|
no_long_string();
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: clear Opera user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Opera/9.80 (Macintosh; Intel Mac OS X 10.7.4; U; en) Presto/2.10.229 Version/11.62
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: opera: %d\n", $r->headers_in->opera)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: opera: %d\n", $r->headers_in->opera)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: opera: 1
|
||||||
|
content: opera: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: clear MSIE 4 user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0)
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=1 msie6=1
|
||||||
|
content: msie=0 msie6=0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: set custom MSIE 4 user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0)";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=0 msie6=0
|
||||||
|
content: msie=1 msie6=1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 5.0)
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 4: clear MSIE 5 user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; MSIECrawler)
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=1 msie6=1
|
||||||
|
content: msie=0 msie6=0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 5: set custom MSIE 5 user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; MSIECrawler)";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=0 msie6=0
|
||||||
|
content: msie=1 msie6=1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 95; MSIECrawler)
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 6: clear MSIE 6 (without SV1) user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Google Wireless Transcoder;)
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=1 msie6=1
|
||||||
|
content: msie=0 msie6=0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 7: set custom MSIE 6 (without SV1) user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Google Wireless Transcoder;)";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=0 msie6=0
|
||||||
|
content: msie=1 msie6=1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Google Wireless Transcoder;)
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 8: clear MSIE 6 (with SV1) user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=1 msie6=0
|
||||||
|
content: msie=0 msie6=0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 9: set custom MSIE 6 (with SV1) user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=0 msie6=0
|
||||||
|
content: msie=1 msie6=0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.1)
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 10: set custom MSIE 7 user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; winfx; .NET CLR 1.1.4322; .NET CLR 2.0.50727; Zune 2.0)";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: msie=%d msie6=%d\n",
|
||||||
|
$r->headers_in->msie,
|
||||||
|
$r->headers_in->msie6)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: msie=0 msie6=0
|
||||||
|
content: msie=1 msie6=0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; winfx; .NET CLR 1.1.4322; .NET CLR 2.0.50727; Zune 2.0)
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 11: clear Gecko user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: gecko: %d\n", $r->headers_in->gecko)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: gecko: %d\n", $r->headers_in->gecko)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: gecko: 1
|
||||||
|
content: gecko: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 12: set custom Gecko user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: gecko: %d\n", $r->headers_in->gecko)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: gecko: %d\n", $r->headers_in->gecko)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: gecko: 0
|
||||||
|
content: gecko: 1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/5.0 (Android; Mobile; rv:13.0) Gecko/13.0 Firefox/13.0
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 13: clear Chrome user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.151 Safari/535.19
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: chrome: %d\n", $r->headers_in->chrome)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: chrome: %d\n", $r->headers_in->chrome)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: chrome: 1
|
||||||
|
content: chrome: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 14: set custom Chrome user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.151 Safari/535.19";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: chrome: %d\n", $r->headers_in->chrome)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: chrome: %d\n", $r->headers_in->chrome)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: chrome: 0
|
||||||
|
content: chrome: 1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.151 Safari/535.19
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 15: clear Safari (Mac OS X) user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: safari: %d\n", $r->headers_in->safari)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: safari: %d\n", $r->headers_in->safari)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: safari: 1
|
||||||
|
content: safari: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 16: set custom Safari user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: safari: %d\n", $r->headers_in->safari)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: safari: %d\n", $r->headers_in->safari)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: safari: 0
|
||||||
|
content: safari: 1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/125.2 (KHTML, like Gecko) Safari/125.8
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 17: clear Konqueror user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_clear_input_headers User-Agent;
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu)
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: konqueror: %d\n", $r->headers_in->konqueror)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: konqueror: %d\n", $r->headers_in->konqueror)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: konqueror: 1
|
||||||
|
content: konqueror: 0
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent:
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 18: set custom Konqueror user-agent
|
||||||
|
--- config
|
||||||
|
location /t {
|
||||||
|
more_set_input_headers "User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu)";
|
||||||
|
echo "User-Agent: $http_user_agent";
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /t
|
||||||
|
|
||||||
|
--- stap
|
||||||
|
F(ngx_http_headers_more_exec_input_cmd) {
|
||||||
|
printf("rewrite: konqueror: %d\n", $r->headers_in->konqueror)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
F(ngx_http_core_content_phase) {
|
||||||
|
printf("content: konqueror: %d\n", $r->headers_in->konqueror)
|
||||||
|
}
|
||||||
|
|
||||||
|
--- stap_out
|
||||||
|
rewrite: konqueror: 0
|
||||||
|
content: konqueror: 1
|
||||||
|
|
||||||
|
--- response_body
|
||||||
|
User-Agent: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.10 (like Gecko) (Kubuntu)
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
1384
ngx_headers_more/t/input.t
Normal file
1384
ngx_headers_more/t/input.t
Normal file
File diff suppressed because it is too large
Load Diff
25
ngx_headers_more/t/phase.t
Normal file
25
ngx_headers_more/t/phase.t
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# vi:filetype=perl
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket;
|
||||||
|
|
||||||
|
plan tests => 3;
|
||||||
|
|
||||||
|
no_diff;
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: simple set (1 arg)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
deny all;
|
||||||
|
more_set_headers 'X-Foo: Blah';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
X-Foo: Blah
|
||||||
|
--- response_body_like: 403 Forbidden
|
||||||
|
--- error_code: 403
|
||||||
628
ngx_headers_more/t/sanity.t
Normal file
628
ngx_headers_more/t/sanity.t
Normal file
@@ -0,0 +1,628 @@
|
|||||||
|
# vi:filetype=
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket;
|
||||||
|
|
||||||
|
repeat_each(2);
|
||||||
|
|
||||||
|
plan tests => repeat_each() * 123;
|
||||||
|
|
||||||
|
#master_on();
|
||||||
|
#workers(2);
|
||||||
|
log_level("warn");
|
||||||
|
no_diff;
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: simple set (1 arg)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
more_set_headers 'X-Foo: Blah';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
X-Foo: Blah
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: simple set (2 args)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
more_set_headers 'X-Foo: Blah' 'X-Bar: hi';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
X-Foo: Blah
|
||||||
|
X-Bar: hi
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: two sets in a single location
|
||||||
|
--- config
|
||||||
|
location /two {
|
||||||
|
echo hi;
|
||||||
|
more_set_headers 'X-Foo: Blah'
|
||||||
|
more_set_headers 'X-Bar: hi';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /two
|
||||||
|
--- response_headers
|
||||||
|
X-Foo: Blah
|
||||||
|
X-Bar: hi
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 4: two sets in a single location (for 404 too)
|
||||||
|
--- config
|
||||||
|
location /two {
|
||||||
|
more_set_headers 'X-Foo: Blah'
|
||||||
|
more_set_headers 'X-Bar: hi';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /two
|
||||||
|
--- response_headers
|
||||||
|
X-Foo: Blah
|
||||||
|
X-Bar: hi
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 5: set a header then clears it (500)
|
||||||
|
--- config
|
||||||
|
location /two {
|
||||||
|
more_set_headers 'X-Foo: Blah';
|
||||||
|
more_set_headers 'X-Foo:';
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /two
|
||||||
|
--- response_headers
|
||||||
|
! X-Foo
|
||||||
|
! X-Bar
|
||||||
|
--- response_body_like: 500 Internal Server Error
|
||||||
|
--- error_code: 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 6: set a header only when 500 (matched)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s 500 'X-Mine: Hiya';
|
||||||
|
more_set_headers -s 404 'X-Yours: Blah';
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-Mine: Hiya
|
||||||
|
! X-Yours
|
||||||
|
--- response_body_like: 500 Internal Server Error
|
||||||
|
--- error_code: 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 7: set a header only when 500 (not matched with 200)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s 500 'X-Mine: Hiya';
|
||||||
|
more_set_headers -s 404 'X-Yours: Blah';
|
||||||
|
echo hello;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-Mine
|
||||||
|
! X-Yours
|
||||||
|
--- response_body
|
||||||
|
hello
|
||||||
|
--- error_code: 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 8: set a header only when 500 (not matched with 404)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s 500 'X-Mine: Hiya';
|
||||||
|
more_set_headers -s 404 'X-Yours: Blah';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-Mine
|
||||||
|
X-Yours: Blah
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 9: more conditions
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s '503 404' 'X-Mine: Hiya';
|
||||||
|
more_set_headers -s ' 404 413 ' 'X-Yours: Blah';
|
||||||
|
return 503;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-Mine: Hiya
|
||||||
|
! X-Yours
|
||||||
|
--- response_body_like: 503 Service
|
||||||
|
--- error_code: 503
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 10: more conditions
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s '503 404' 'X-Mine: Hiya';
|
||||||
|
more_set_headers -s ' 404 413 ' 'X-Yours: Blah';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-Mine: Hiya
|
||||||
|
X-Yours: Blah
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 11: more conditions
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s '503 404' 'X-Mine: Hiya';
|
||||||
|
more_set_headers -s ' 404 413 ' 'X-Yours: Blah';
|
||||||
|
return 413;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-Mine
|
||||||
|
X-Yours: Blah
|
||||||
|
--- response_body_like: 413 Request Entity Too Large
|
||||||
|
--- error_code: 413
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 12: simple -t
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/css';
|
||||||
|
more_set_headers -t 'text/css' 'X-CSS: yes';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-CSS: yes
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 13: simple -t (not matched)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers -t 'text/css' 'X-CSS: yes';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-CSS
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 14: multiple -t (not matched)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers -t 'text/javascript' -t 'text/css' 'X-CSS: yes';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-CSS
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 15: multiple -t (matched)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers -t 'text/javascript' -t 'text/plain' 'X-CSS: yes';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-CSS: yes
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 16: multiple -t (matched)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/javascript';
|
||||||
|
more_set_headers -t 'text/javascript' -t 'text/plain' 'X-CSS: yes';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-CSS: yes
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 17: multiple -t (matched) with extra spaces
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/javascript';
|
||||||
|
more_set_headers -t ' text/javascript ' -t 'text/plain' 'X-CSS: yes';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-CSS: yes
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 18: multiple -t merged
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/javascript';
|
||||||
|
more_set_headers -t ' text/javascript text/plain' 'X-CSS: yes';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-CSS: yes
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 19: multiple -t merged (2)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/plain';
|
||||||
|
more_set_headers -t ' text/javascript text/plain' 'X-CSS: yes';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-CSS: yes
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 20: multiple -s option in a directive (not matched)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s 404 -s 500 'X-status: howdy';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-status
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 21: multiple -s option in a directive (matched 404)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s 404 -s 500 'X-status: howdy';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-status: howdy
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 22: multiple -s option in a directive (matched 500)
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
more_set_headers -s 404 -s 500 'X-status: howdy';
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-status: howdy
|
||||||
|
--- response_body_like: 500 Internal Server Error
|
||||||
|
--- error_code: 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 23: -s mixed with -t
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/html';
|
||||||
|
more_set_headers -s 404 -s 200 -t 'text/html' 'X-status: howdy2';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-status: howdy2
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 24: -s mixed with -t
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/html';
|
||||||
|
more_set_headers -s 404 -s 200 -t 'text/plain' 'X-status: howdy2';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-status
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 25: -s mixed with -t
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/html';
|
||||||
|
more_set_headers -s 404 -s 200 -t 'text/html' 'X-status: howdy2';
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-status: howdy2
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
--- error_code: 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 26: -s mixed with -t
|
||||||
|
--- config
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/html';
|
||||||
|
more_set_headers -s 500 -s 200 -t 'text/html' 'X-status: howdy2';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-status
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 27: merge from the upper level
|
||||||
|
--- config
|
||||||
|
more_set_headers -s 404 -t 'text/html' 'X-status2: howdy3';
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/html';
|
||||||
|
more_set_headers -s 500 -s 200 -t 'text/html' 'X-status: howdy2';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-status2: howdy3
|
||||||
|
! X-status
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 28: merge from the upper level
|
||||||
|
--- config
|
||||||
|
more_set_headers -s 404 -t 'text/html' 'X-status2: howdy3';
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/html';
|
||||||
|
more_set_headers -s 500 -s 200 -t 'text/html' 'X-status: howdy2';
|
||||||
|
echo yeah;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
! X-status2
|
||||||
|
X-status: howdy2
|
||||||
|
--- response_body
|
||||||
|
yeah
|
||||||
|
--- error_code: 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 29: override settings by inheritance
|
||||||
|
--- config
|
||||||
|
more_set_headers -s 404 -t 'text/html' 'X-status: yeah';
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/html';
|
||||||
|
more_set_headers -s 404 -t 'text/html' 'X-status: nope';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-status: nope
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 30: append settings by inheritance
|
||||||
|
--- config
|
||||||
|
more_set_headers -s 404 -t 'text/html' 'X-status: yeah';
|
||||||
|
location /bad {
|
||||||
|
default_type 'text/html';
|
||||||
|
more_set_headers -s 404 -t 'text/html' 'X-status2: nope';
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /bad
|
||||||
|
--- response_headers
|
||||||
|
X-status: yeah
|
||||||
|
X-status2: nope
|
||||||
|
--- response_body_like: 404 Not Found
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 31: clear headers with wildcard
|
||||||
|
--- config
|
||||||
|
location = /backend {
|
||||||
|
add_header X-Hidden-One "i am hidden";
|
||||||
|
add_header X-Hidden-Two "me 2";
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
location /hello {
|
||||||
|
more_clear_headers 'X-Hidden-*';
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/backend;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /hello
|
||||||
|
--- response_headers
|
||||||
|
! X-Hidden-One
|
||||||
|
! X-Hidden-Two
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 32: clear duplicate headers
|
||||||
|
--- config
|
||||||
|
location = /backend {
|
||||||
|
add_header pragma no-cache;
|
||||||
|
add_header pragma no-cache;
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
location /hello {
|
||||||
|
more_clear_headers 'pragma';
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/backend;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /hello
|
||||||
|
--- response_headers
|
||||||
|
!pragma
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 33: HTTP 0.9 (set)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
more_set_headers 'X-Foo: howdy';
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- raw_request eval
|
||||||
|
"GET /foo\r\n"
|
||||||
|
--- response_headers
|
||||||
|
! X-Foo
|
||||||
|
--- response_body
|
||||||
|
ok
|
||||||
|
--- http09
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 34: use the -a option to append the cookie field
|
||||||
|
--- config
|
||||||
|
location /cookie {
|
||||||
|
more_set_headers -a 'Set-Cookie: name=lynch';
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /cookie
|
||||||
|
--- response_headers
|
||||||
|
Set-Cookie: name=lynch
|
||||||
|
--- response_body
|
||||||
|
ok
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 35: the original Set-Cookie fields will not be overwritten, when using the -a option
|
||||||
|
--- config
|
||||||
|
location /cookie {
|
||||||
|
more_set_headers 'Set-Cookie: name=lynch';
|
||||||
|
more_set_headers -a 'Set-Cookie: born=1981';
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /cookie
|
||||||
|
--- raw_response_headers_like eval
|
||||||
|
"Set-Cookie: name=lynch\r\nSet-Cookie: born=1981\r\n"
|
||||||
|
--- response_body
|
||||||
|
ok
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 36: The behavior of builtin headers can not be changed
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
more_set_headers -a "Server: myServer";
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- must_die
|
||||||
|
--- error_log chomp
|
||||||
|
can not append builtin headers
|
||||||
|
--- suppress_stderr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 37: can not use -a option with more_clear_headers
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
more_clear_headers -a 'Content-Type';
|
||||||
|
echo ok;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- must_die
|
||||||
|
--- error_log chomp
|
||||||
|
invalid option name: "-a"
|
||||||
|
--- suppress_stderr
|
||||||
68
ngx_headers_more/t/subrequest.t
Normal file
68
ngx_headers_more/t/subrequest.t
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# vi:filetype=
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket; # 'no_plan';
|
||||||
|
|
||||||
|
plan tests => blocks() * 3;
|
||||||
|
|
||||||
|
no_diff;
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: vars in input header directives
|
||||||
|
--- config
|
||||||
|
location /main {
|
||||||
|
echo_location /foo;
|
||||||
|
echo "main: $http_user_agent";
|
||||||
|
}
|
||||||
|
location /foo {
|
||||||
|
set $val 'dog';
|
||||||
|
|
||||||
|
more_set_input_headers 'User-Agent: $val';
|
||||||
|
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/proxy;
|
||||||
|
}
|
||||||
|
location /proxy {
|
||||||
|
echo "sub: $http_user_agent";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /main
|
||||||
|
--- more_headers
|
||||||
|
User-Agent: my-sock
|
||||||
|
--- response_body
|
||||||
|
sub: dog
|
||||||
|
main: dog
|
||||||
|
--- response_headers
|
||||||
|
! Host
|
||||||
|
--- skip_nginx: 3: < 0.7.46
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: vars in input header directives
|
||||||
|
--- config
|
||||||
|
location /main {
|
||||||
|
#more_set_input_headers 'User-Agent: cat';
|
||||||
|
echo_location /foo;
|
||||||
|
echo "main: $http_user_agent";
|
||||||
|
}
|
||||||
|
location /foo {
|
||||||
|
set $val 'dog';
|
||||||
|
|
||||||
|
more_set_input_headers 'User-Agent: $val';
|
||||||
|
|
||||||
|
proxy_pass http://127.0.0.1:$server_port/proxy;
|
||||||
|
#echo $http_user_agent;
|
||||||
|
}
|
||||||
|
location /proxy {
|
||||||
|
echo "sub: $http_user_agent";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /main
|
||||||
|
--- response_body
|
||||||
|
sub: dog
|
||||||
|
main: dog
|
||||||
|
--- response_headers
|
||||||
|
! Host
|
||||||
|
--- skip_nginx: 3: < 0.7.46
|
||||||
174
ngx_headers_more/t/unused.t
Normal file
174
ngx_headers_more/t/unused.t
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
# vi:filetype=
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket;
|
||||||
|
|
||||||
|
repeat_each(2);
|
||||||
|
|
||||||
|
plan tests => repeat_each() * (blocks() * 4 + 2);
|
||||||
|
|
||||||
|
#master_on();
|
||||||
|
#workers(2);
|
||||||
|
log_level("warn");
|
||||||
|
no_diff;
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: used output filter
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
more_set_headers "Foo: bar";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
Foo: bar
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
--- error_log
|
||||||
|
headers more header filter
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
--- log_level: debug
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: unused output filter (none)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
--- no_error_log
|
||||||
|
headers more header filter
|
||||||
|
[error]
|
||||||
|
--- log_level: debug
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: unused output filter (with more_set_input_headers only)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
more_set_input_headers "Foo: bar";
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
--- no_error_log
|
||||||
|
headers more header filter
|
||||||
|
[error]
|
||||||
|
--- log_level: debug
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 4: used rewrite handler
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
more_set_input_headers "Foo: bar";
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
--- error_log
|
||||||
|
headers more rewrite handler
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
--- log_level: debug
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 5: unused rewrite handler (none)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
#more_set_input_headers "Foo: bar";
|
||||||
|
echo hi;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
--- no_error_log
|
||||||
|
headers more rewrite handler
|
||||||
|
[error]
|
||||||
|
--- log_level: debug
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 6: unused rewrite handler (with output header filters)
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
#more_set_input_headers "Foo: bar";
|
||||||
|
echo hi;
|
||||||
|
more_set_headers "Foo: bar";
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
Foo: bar
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
--- no_error_log
|
||||||
|
headers more rewrite handler
|
||||||
|
[error]
|
||||||
|
--- log_level: debug
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 7: multiple http {} blocks (filter)
|
||||||
|
This test case won't run with nginx 1.9.3+ since duplicate http {} blocks
|
||||||
|
have been prohibited since then.
|
||||||
|
--- SKIP
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
more_set_headers 'Foo: bar';
|
||||||
|
}
|
||||||
|
--- post_main_config
|
||||||
|
http {
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
--- response_headers
|
||||||
|
Foo: bar
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
--- error_log
|
||||||
|
headers more header filter
|
||||||
|
--- log_level: debug
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 8: multiple http {} blocks (handler)
|
||||||
|
This test case won't run with nginx 1.9.3+ since duplicate http {} blocks
|
||||||
|
have been prohibited since then.
|
||||||
|
--- SKIP
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
more_set_input_headers 'Foo: bar';
|
||||||
|
echo $http_foo;
|
||||||
|
}
|
||||||
|
--- post_main_config
|
||||||
|
http {
|
||||||
|
}
|
||||||
|
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_body
|
||||||
|
bar
|
||||||
|
--- no_error_log
|
||||||
|
headers more header handler
|
||||||
|
[error]
|
||||||
|
--- log_level: debug
|
||||||
58
ngx_headers_more/t/vars.t
Normal file
58
ngx_headers_more/t/vars.t
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# vi:ft=
|
||||||
|
|
||||||
|
use lib 'lib';
|
||||||
|
use Test::Nginx::Socket; # 'no_plan';
|
||||||
|
|
||||||
|
plan tests => 9;
|
||||||
|
|
||||||
|
no_diff;
|
||||||
|
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
=== TEST 1: vars
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
set $val 'hello, world';
|
||||||
|
more_set_headers 'X-Foo: $val';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
X-Foo: hello, world
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: vars in both key and val
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
echo hi;
|
||||||
|
set $val 'hello, world';
|
||||||
|
more_set_headers '$val: $val';
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_headers
|
||||||
|
$val: hello, world
|
||||||
|
--- response_body
|
||||||
|
hi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: vars in input header directives
|
||||||
|
--- config
|
||||||
|
location /foo {
|
||||||
|
set $val 'dog';
|
||||||
|
more_set_input_headers 'Host: $val';
|
||||||
|
echo $host;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /foo
|
||||||
|
--- response_body
|
||||||
|
dog
|
||||||
|
--- response_headers
|
||||||
|
Host:
|
||||||
34
ngx_headers_more/util/build.sh
Normal file
34
ngx_headers_more/util/build.sh
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# this file is mostly meant to be used by the author himself.
|
||||||
|
|
||||||
|
root=`pwd`
|
||||||
|
version=$1
|
||||||
|
home=~
|
||||||
|
force=$2
|
||||||
|
|
||||||
|
#--with-cc=gcc46 \
|
||||||
|
|
||||||
|
ngx-build $force $version \
|
||||||
|
--with-ld-opt="-L$PCRE_LIB -Wl,-rpath,$PCRE_LIB" \
|
||||||
|
--with-cc-opt="-DNGX_LUA_USE_ASSERT -I$PCRE_INC" \
|
||||||
|
--without-mail_pop3_module \
|
||||||
|
--without-mail_imap_module \
|
||||||
|
--without-mail_smtp_module \
|
||||||
|
--without-http_upstream_ip_hash_module \
|
||||||
|
--without-http_empty_gif_module \
|
||||||
|
--without-http_memcached_module \
|
||||||
|
--without-http_referer_module \
|
||||||
|
--without-http_autoindex_module \
|
||||||
|
--without-http_auth_basic_module \
|
||||||
|
--without-http_userid_module \
|
||||||
|
--with-http_realip_module \
|
||||||
|
--with-http_dav_module \
|
||||||
|
--add-module=$root/../eval-nginx-module \
|
||||||
|
--add-module=$root/../lua-nginx-module \
|
||||||
|
--add-module=$root/../echo-nginx-module \
|
||||||
|
--add-module=$root $opts \
|
||||||
|
--with-debug
|
||||||
|
#--add-module=$root/../ndk-nginx-module \
|
||||||
|
#--without-http_ssi_module # we cannot disable ssi because echo_location_async depends on it (i dunno why?!)
|
||||||
|
|
||||||
135
ngx_headers_more/valgrind.suppress
Normal file
135
ngx_headers_more/valgrind.suppress
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
obj:*
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_calloc
|
||||||
|
fun:ngx_event_process_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_event_process_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
epoll_ctl(event)
|
||||||
|
fun:epoll_ctl
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:memcpy
|
||||||
|
fun:ngx_vslprintf
|
||||||
|
fun:ngx_log_error_core
|
||||||
|
fun:ngx_http_charset_header_filter
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nginx-core-process-init
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_event_process_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nginx-core-crc32-init
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_crc32_table_init
|
||||||
|
fun:main
|
||||||
|
}
|
||||||
|
{
|
||||||
|
palloc_large_for_init_request
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_palloc_large
|
||||||
|
fun:ngx_palloc
|
||||||
|
fun:ngx_pcalloc
|
||||||
|
fun:ngx_http_init_request
|
||||||
|
fun:ngx_epoll_process_events
|
||||||
|
fun:ngx_process_events_and_timers
|
||||||
|
}
|
||||||
|
{
|
||||||
|
palloc_large_for_create_temp_buf
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_palloc_large
|
||||||
|
fun:ngx_palloc
|
||||||
|
fun:ngx_create_temp_buf
|
||||||
|
fun:ngx_http_init_request
|
||||||
|
fun:ngx_epoll_process_events
|
||||||
|
fun:ngx_process_events_and_timers
|
||||||
|
}
|
||||||
|
{
|
||||||
|
accept_create_pool
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:memalign
|
||||||
|
fun:posix_memalign
|
||||||
|
fun:ngx_memalign
|
||||||
|
fun:ngx_create_pool
|
||||||
|
fun:ngx_event_accept
|
||||||
|
fun:ngx_epoll_process_events
|
||||||
|
fun:ngx_process_events_and_timers
|
||||||
|
}
|
||||||
|
{
|
||||||
|
create_pool_for_init_req
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:memalign
|
||||||
|
fun:posix_memalign
|
||||||
|
fun:ngx_memalign
|
||||||
|
fun:ngx_create_pool
|
||||||
|
fun:ngx_http_init_request
|
||||||
|
fun:ngx_epoll_process_events
|
||||||
|
fun:ngx_process_events_and_timers
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Addr8
|
||||||
|
fun:getenv
|
||||||
|
fun:gcov_exit
|
||||||
|
fun:exit
|
||||||
|
fun:ngx_master_process_exit
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:index
|
||||||
|
fun:expand_dynamic_string_token
|
||||||
|
fun:_dl_map_object
|
||||||
|
fun:map_doit
|
||||||
|
fun:_dl_catch_error
|
||||||
|
fun:do_preload
|
||||||
|
fun:dl_main
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: definite
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_set_environment
|
||||||
|
fun:ngx_single_process_cycle
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: definite
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_set_environment
|
||||||
|
fun:ngx_worker_process_init
|
||||||
|
fun:ngx_worker_process_cycle
|
||||||
|
}
|
||||||
1
ngx_zstd/.gitattributes
vendored
Normal file
1
ngx_zstd/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.t linguist-language=Text
|
||||||
54
ngx_zstd/.gitignore
vendored
Normal file
54
ngx_zstd/.gitignore
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
t/servroot/*
|
||||||
25
ngx_zstd/LICENSE
Normal file
25
ngx_zstd/LICENSE
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
BSD 2-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2018, Alex Zhang
|
||||||
|
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.
|
||||||
155
ngx_zstd/README.md
Normal file
155
ngx_zstd/README.md
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
# Name
|
||||||
|
zstd-nginx-module - Nginx module for the [Zstandard compression](https://facebook.github.io/zstd/).
|
||||||
|
|
||||||
|
# Table of Contents
|
||||||
|
|
||||||
|
* [Name](#name)
|
||||||
|
* [Status](#status)
|
||||||
|
* [Synopsis](#synopsis)
|
||||||
|
* [Installation](#installation)
|
||||||
|
* [Directives](#directives)
|
||||||
|
* [ngx_http_zstd_filter_module](#ngx_http_zstd_filter_module)
|
||||||
|
* [zstd_dict_file](#zstd_dict_file)
|
||||||
|
* [zstd](#zstd)
|
||||||
|
* [zstd_comp_level](#zstd_comp_level)
|
||||||
|
* [zstd_min_length](#zstd_min_length)
|
||||||
|
* [zstd_types](#zstd_types)
|
||||||
|
* [zstd_buffers](#zstd_buffers)
|
||||||
|
* [ngx_http_zstd_static_module](#ngx_http_zstd_static_module)
|
||||||
|
* [zstd_static](#zstd_static)
|
||||||
|
* [Variables](#variables)
|
||||||
|
* [ngx_http_zstd_filter_module](#ngx_http_zstd_filter_module)
|
||||||
|
* [$zstd_ratio](#$zstd_ratio)
|
||||||
|
* [Author](#author)
|
||||||
|
|
||||||
|
# Status
|
||||||
|
|
||||||
|
This Nginx module is currently considered experimental. Issues and PRs are welcome if you encounter any problems.
|
||||||
|
|
||||||
|
# Synopsis
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
|
||||||
|
# specify the dictionary
|
||||||
|
zstd_dict_file /path/to/dict;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 127.0.0.1:8080;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
# enable zstd compression
|
||||||
|
zstd on;
|
||||||
|
zstd_min_length 256; # no less than 256 bytes
|
||||||
|
zstd_comp_level 3; # set the level to 3
|
||||||
|
|
||||||
|
proxy_pass http://foo.com;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 127.0.0.1:8081;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
zstd_static on;
|
||||||
|
root html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
To use theses modules, configure your nginx branch with `--add-module=/path/to/zstd-nginx-module`. Several points should be taken care of.
|
||||||
|
|
||||||
|
* You can set environment variables `ZSTD_INC` and `ZSTD_LIB` to specify the path to `zstd.h` and the path to zstd shared library respectively.
|
||||||
|
* static library will be attempted prior to dynamic library, since this Nginx module uses some **advanced APIs** where static linking is recommended.
|
||||||
|
* System's zstd bundle will be linked if `ZSTD_INC` and `ZSTD_LIB` are not specified.
|
||||||
|
* Both `ngx_http_zstd_static_module` and `ngx_http_zstd_filter_module` will be configured.
|
||||||
|
|
||||||
|
# Directives
|
||||||
|
|
||||||
|
## ngx_http_zstd_filter_module
|
||||||
|
|
||||||
|
The `ngx_http_zstd_filter_module` module is a filter that compresses responses using the _"zstd"_ method. This often helps to reduce the size of transmitted data by half or even more.
|
||||||
|
|
||||||
|
### zstd_dict_file
|
||||||
|
|
||||||
|
**Syntax:** *zstd_dict_file /path/to/dict;*
|
||||||
|
**Default:** *-*
|
||||||
|
**Context:** *http*
|
||||||
|
|
||||||
|
Specifies the external dictionary.
|
||||||
|
|
||||||
|
**WARNING:** Be careful! The content-coding registration only specifies a means to signal the use of the zstd format, and does not additionally specify any mechanism for advertising/negotiating/synchronizing the use of a specific dictionary between client and server. Use the `zstd_dict_file` only if you can insure that both ends _(server and client)_ are capable of using the same dictionary (e.g. advertise with a HTTP header). See https://github.com/tokers/zstd-nginx-module/issues/2 for the details.
|
||||||
|
|
||||||
|
### zstd
|
||||||
|
|
||||||
|
**Syntax:** *zstd on | off;*
|
||||||
|
**Default:** *zstd off;*
|
||||||
|
**Context:** *http, server, location, if in location*
|
||||||
|
|
||||||
|
Enables or disables zstd compression for response.
|
||||||
|
|
||||||
|
### zstd_comp_level
|
||||||
|
|
||||||
|
**Syntax:** *zstd_comp_level level;*
|
||||||
|
**Default:** *zstd_comp_level 1;*
|
||||||
|
**Context:** *http, server, location*
|
||||||
|
|
||||||
|
Sets a zstd compression level of a response. Acceptable values are in the range from 1 to `ZSTD_maxCLevel()`.
|
||||||
|
|
||||||
|
### zstd_min_length
|
||||||
|
|
||||||
|
**Syntax:** *zstd_min_length length;*
|
||||||
|
**Default:** *zstd_min_length 20;*
|
||||||
|
**Context:** *http, server, location*
|
||||||
|
|
||||||
|
Sets the minimum length of a response that will be compressed by zstd. The length is determined only from the `Content-Length` response header field.
|
||||||
|
|
||||||
|
### zstd_types
|
||||||
|
|
||||||
|
**Syntax:** *zstd_types mime-type ...;*
|
||||||
|
**Default:** *zstd_types text/html;*
|
||||||
|
**Context:** *http, server, location*
|
||||||
|
|
||||||
|
Enables zstd of responses for the specified MIME types in addition to `text/html`. The special value `*` matches any MIME type.
|
||||||
|
|
||||||
|
### zstd_buffers
|
||||||
|
|
||||||
|
**Syntax:** *zstd_buffers number size;*
|
||||||
|
**Default:** *zstd_buffers 32 4k | 16 8k;*
|
||||||
|
**Context:** *http, server, location*
|
||||||
|
|
||||||
|
Sets the number and size of buffers used to compress a response. By default the buffer size is equal to one memory page. This is either 4K or 8K, depending on a platform.
|
||||||
|
|
||||||
|
## ngx_http_zstd_static_module
|
||||||
|
|
||||||
|
The `ngx_http_zstd_static_module` module allows sending precompressed files with the `.zst` filename extension instead of regular files.
|
||||||
|
|
||||||
|
### zstd_static
|
||||||
|
|
||||||
|
**Syntax:** *zstd_static on | off | always;*
|
||||||
|
**Default:** *zstd_static off;*
|
||||||
|
**Context:** *http, server, location*
|
||||||
|
|
||||||
|
Enables ("on") or disables ("off") checking the existence of precompressed files. The following directives are also taken into account: `gzip_vary`.
|
||||||
|
|
||||||
|
With the _"always"_ value, "zstd" file is used in all cases, without checking if the client supports it.
|
||||||
|
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
|
||||||
|
## ngx_http_zstd_filter_module
|
||||||
|
|
||||||
|
### $zstd_ratio
|
||||||
|
|
||||||
|
Achieved compression ratio, computed as the ratio between the original and compressed response sizes.
|
||||||
|
|
||||||
|
# Author
|
||||||
|
|
||||||
|
Alex Zhang (张超) zchao1995@gmail.com, UPYUN Inc.
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
This Nginx module is licensed under [BSD 2-Clause License](LICENSE).
|
||||||
11
ngx_zstd/config
Normal file
11
ngx_zstd/config
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Make sure the module knows it is a submodule.
|
||||||
|
ngx_addon_name=ngx_zstd
|
||||||
|
. $ngx_addon_dir/filter/config
|
||||||
|
|
||||||
|
# Make sure the module knows it is a submodule.
|
||||||
|
ngx_addon_name=ngx_zstd
|
||||||
|
. $ngx_addon_dir/static/config
|
||||||
|
|
||||||
|
# The final name for reporting.
|
||||||
|
ngx_addon_name=ngx_zstd
|
||||||
|
|
||||||
144
ngx_zstd/filter/config
Normal file
144
ngx_zstd/filter/config
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
ngx_feature_incs="#include <zstd.h>"
|
||||||
|
ngx_feature_test="(void) ZSTD_createCCtx();"
|
||||||
|
ngx_feature_libs=
|
||||||
|
ngx_feature_run=yes
|
||||||
|
|
||||||
|
ngx_zstd_opt_I=
|
||||||
|
ngx_zstd_opt_L=
|
||||||
|
|
||||||
|
if [ -n "$ZSTD_INC" -o -n "$ZSTD_LIB" ]; then
|
||||||
|
ngx_feature="ZStandard static library in $ZSTD_INC and $ZSTD_LIB"
|
||||||
|
ngx_feature_path=$ZSTD_INC
|
||||||
|
|
||||||
|
# we try the static shared library firstly
|
||||||
|
ngx_zstd_opt_I="-I$ZSTD_INC -DZSTD_STATIC_LINKING_ONLY"
|
||||||
|
ngx_zstd_opt_L="$ZSTD_LIB/libzstd.a"
|
||||||
|
SAVED_CC_TAST_FLAGS=$CC_TEST_FLAGS
|
||||||
|
CC_TEST_FLAGS="$ngx_zstd_opt_I $CC_TEST_FLAGS"
|
||||||
|
SAVED_NGX_TEST_LD_OPT=$NGX_TEST_LD_OPT
|
||||||
|
NGX_TEST_LD_OPT="$ngx_zstd_opt_L $NGX_TEST_LD_OPT"
|
||||||
|
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
# restore
|
||||||
|
CC_TEST_FLAGS=$SAVED_CC_TAST_FLAGS
|
||||||
|
NGX_TEST_LD_OPT=$SAVED_NGX_TEST_LD_OPT
|
||||||
|
|
||||||
|
if [ $ngx_found = no ]; then
|
||||||
|
# then try the dynamic shared library
|
||||||
|
ngx_feature="ZStandard dynamic library in $ZSTD_INC and $ZSTD_LIB"
|
||||||
|
ngx_zstd_opt_L="-L$ZSTD_LIB -lzstd -Wl,-rpath, $ZSTD_LIB"
|
||||||
|
|
||||||
|
SAVED_CC_TAST_FLAGS=$CC_TEST_FLAGS
|
||||||
|
CC_TEST_FLAGS="$ngx_zstd_opt_I $CC_TEST_FLAGS"
|
||||||
|
SAVED_NGX_TEST_LD_OPT=$NGX_TEST_LD_OPT
|
||||||
|
NGX_TEST_LD_OPT="$ngx_zstd_opt_L $NGX_TEST_LD_OPT"
|
||||||
|
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
# restore
|
||||||
|
CC_TEST_FLAGS=$SAVED_CC_TAST_FLAGS
|
||||||
|
NGX_TEST_LD_OPT=$SAVED_NGX_TEST_LD_OPT
|
||||||
|
|
||||||
|
if [ $ngx_found = no ]; then
|
||||||
|
cat << END
|
||||||
|
$0: error: ngx_http_zstd_filter_module requires the ZStandard library, please be sure that "\$ZSTD_INC" and "\$ZSTD_LIB" are set correctly.
|
||||||
|
END
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# auto-discovery
|
||||||
|
ngx_feature="ZStandard static library"
|
||||||
|
ngx_zstd_opt_I="-DZSTD_STATIC_LINKING_ONLY"
|
||||||
|
ngx_zstd_opt_L="-l:libzstd.a"
|
||||||
|
|
||||||
|
# still we consider the static library firstly
|
||||||
|
SAVED_CC_TAST_FLAGS=$CC_TEST_FLAGS
|
||||||
|
CC_TEST_FLAGS="$ngx_zstd_opt_I $CC_TEST_FLAGS"
|
||||||
|
SAVED_NGX_TEST_LD_OPT=$NGX_TEST_LD_OPT
|
||||||
|
NGX_TEST_LD_OPT="$ngx_zstd_opt_L $NGX_TEST_LD_OPT"
|
||||||
|
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
# restore
|
||||||
|
CC_TEST_FLAGS=$SAVED_CC_TAST_FLAGS
|
||||||
|
NGX_TEST_LD_OPT=$SAVED_NGX_TEST_LD_OPT
|
||||||
|
|
||||||
|
if [ $ngx_found = no ]; then
|
||||||
|
|
||||||
|
ngx_feature="ZStandard dynamic library"
|
||||||
|
ngx_zstd_opt_L="-lzstd"
|
||||||
|
SAVED_CC_TAST_FLAGS=$CC_TEST_FLAGS
|
||||||
|
CC_TEST_FLAGS="$ngx_zstd_opt_I $CC_TEST_FLAGS"
|
||||||
|
SAVED_NGX_TEST_LD_OPT=$NGX_TEST_LD_OPT
|
||||||
|
NGX_TEST_LD_OPT="$ngx_zstd_opt_L $NGX_TEST_LD_OPT"
|
||||||
|
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
if [ $ngx_found = no ]; then
|
||||||
|
cat << END
|
||||||
|
$0: error: ngx_http_zstd_filter_module requires the ZStandard library.
|
||||||
|
END
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# restore
|
||||||
|
CC_TEST_FLAGS=$SAVED_CC_TAST_FLAGS
|
||||||
|
NGX_TEST_LD_OPT=$SAVED_NGX_TEST_LD_OPT
|
||||||
|
|
||||||
|
cat << END
|
||||||
|
$0: warning: ngx_http_zstd_filter_module uses advanced ZStandard APIs (which are still considered experimental) while you are trying to link the dynamic shared library.
|
||||||
|
END
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO we need more tries for the different OS port.
|
||||||
|
fi
|
||||||
|
|
||||||
|
NGX_LD_OPT="$ngx_zstd_opt_L $NGX_LD_OPT"
|
||||||
|
|
||||||
|
HTTP_ZSTD_SRCS="$ngx_addon_dir/filter/ngx_http_zstd_filter_module.c"
|
||||||
|
|
||||||
|
ngx_addon_name=ngx_http_zstd_filter_module
|
||||||
|
ngx_module_type=HTTP_FILTER
|
||||||
|
ngx_module_name=ngx_http_zstd_filter_module
|
||||||
|
ngx_module_incs="$ngx_zstd_opt_I"
|
||||||
|
ngx_module_srcs=$HTTP_ZSTD_SRCS
|
||||||
|
ngx_module_libs=$NGX_LD_OPT
|
||||||
|
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
|
||||||
|
|
||||||
1035
ngx_zstd/filter/ngx_http_zstd_filter_module.c
Normal file
1035
ngx_zstd/filter/ngx_http_zstd_filter_module.c
Normal file
File diff suppressed because it is too large
Load Diff
111
ngx_zstd/static/config
Normal file
111
ngx_zstd/static/config
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
ngx_feature_incs="#include <zstd.h>"
|
||||||
|
ngx_feature_test="(void) ZSTD_createCCtx();"
|
||||||
|
ngx_feature_libs=
|
||||||
|
ngx_feature_run=yes
|
||||||
|
|
||||||
|
ngx_zstd_opt_I=
|
||||||
|
ngx_zstd_opt_L=
|
||||||
|
|
||||||
|
if [ -n "$ZSTD_INC" -o -n "$ZSTD_LIB" ]; then
|
||||||
|
ngx_feature="ZStandard static library in $ZSTD_INC and $ZSTD_LIB"
|
||||||
|
ngx_feature_path=$ZSTD_INC
|
||||||
|
|
||||||
|
# we try the static shared library firstly
|
||||||
|
ngx_zstd_opt_I="-I$ZSTD_INC -DZSTD_STATIC_LINKING_ONLY"
|
||||||
|
ngx_zstd_opt_L="$ZSTD_LIB/libzstd.a"
|
||||||
|
SAVED_CC_TAST_FLAGS=$CC_TEST_FLAGS
|
||||||
|
CC_TEST_FLAGS="$ngx_zstd_opt_I $CC_TEST_FLAGS"
|
||||||
|
SAVED_NGX_TEST_LD_OPT=$NGX_TEST_LD_OPT
|
||||||
|
NGX_TEST_LD_OPT="$ngx_zstd_opt_L $NGX_TEST_LD_OPT"
|
||||||
|
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
# restore
|
||||||
|
CC_TEST_FLAGS=$SAVED_CC_TAST_FLAGS
|
||||||
|
NGX_TEST_LD_OPT=$SAVED_NGX_TEST_LD_OPT
|
||||||
|
|
||||||
|
if [ $ngx_found = no ]; then
|
||||||
|
# then try the dynamic shared library
|
||||||
|
ngx_feature="ZStandard dynamic library in $ZSTD_INC and $ZSTD_LIB"
|
||||||
|
ngx_zstd_opt_L="-L$ZSTD_LIB -lzstd -Wl,-rpath, $ZSTD_LIB"
|
||||||
|
|
||||||
|
SAVED_CC_TAST_FLAGS=$CC_TEST_FLAGS
|
||||||
|
CC_TEST_FLAGS="$ngx_zstd_opt_I $CC_TEST_FLAGS"
|
||||||
|
SAVED_NGX_TEST_LD_OPT=$NGX_TEST_LD_OPT
|
||||||
|
NGX_TEST_LD_OPT="$ngx_zstd_opt_L $NGX_TEST_LD_OPT"
|
||||||
|
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
# restore
|
||||||
|
CC_TEST_FLAGS=$SAVED_CC_TAST_FLAGS
|
||||||
|
NGX_TEST_LD_OPT=$SAVED_NGX_TEST_LD_OPT
|
||||||
|
|
||||||
|
if [ $ngx_found = no ]; then
|
||||||
|
cat << END
|
||||||
|
$0: error: ngx_http_zstd_filter_module requires the ZStandard library, please be sure that "\$ZSTD_INC" and "\$ZSTD_LIB" are set correctly.
|
||||||
|
END
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# auto-discovery
|
||||||
|
ngx_feature="ZStandard static library"
|
||||||
|
ngx_zstd_opt_I="-DZSTD_STATIC_LINKING_ONLY"
|
||||||
|
ngx_zstd_opt_L="-l:libzstd.a"
|
||||||
|
|
||||||
|
# still we consider the static library firstly
|
||||||
|
SAVED_CC_TAST_FLAGS=$CC_TEST_FLAGS
|
||||||
|
CC_TEST_FLAGS="$ngx_zstd_opt_I $CC_TEST_FLAGS"
|
||||||
|
SAVED_NGX_TEST_LD_OPT=$NGX_TEST_LD_OPT
|
||||||
|
NGX_TEST_LD_OPT="$ngx_zstd_opt_L $NGX_TEST_LD_OPT"
|
||||||
|
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
# restore
|
||||||
|
CC_TEST_FLAGS=$SAVED_CC_TAST_FLAGS
|
||||||
|
NGX_TEST_LD_OPT=$SAVED_NGX_TEST_LD_OPT
|
||||||
|
|
||||||
|
if [ $ngx_found = no ]; then
|
||||||
|
|
||||||
|
ngx_feature="ZStandard dynamic library"
|
||||||
|
ngx_zstd_opt_L="-lzstd"
|
||||||
|
SAVED_CC_TAST_FLAGS=$CC_TEST_FLAGS
|
||||||
|
CC_TEST_FLAGS="$ngx_zstd_opt_I $CC_TEST_FLAGS"
|
||||||
|
SAVED_NGX_TEST_LD_OPT=$NGX_TEST_LD_OPT
|
||||||
|
NGX_TEST_LD_OPT="$ngx_zstd_opt_L $NGX_TEST_LD_OPT"
|
||||||
|
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
if [ $ngx_found = no ]; then
|
||||||
|
cat << END
|
||||||
|
$0: error: ngx_http_zstd_filter_module requires the ZStandard library.
|
||||||
|
END
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# restore
|
||||||
|
CC_TEST_FLAGS=$SAVED_CC_TAST_FLAGS
|
||||||
|
NGX_TEST_LD_OPT=$SAVED_NGX_TEST_LD_OPT
|
||||||
|
|
||||||
|
cat << END
|
||||||
|
$0: warning: ngx_http_zstd_filter_module uses advanced ZStandard APIs (which are still considered experimental) while you are trying to link the dynamic shared library.
|
||||||
|
END
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO we need more tries for the different OS port.
|
||||||
|
fi
|
||||||
|
|
||||||
|
CFLAGS="$ngx_zstd_opt_I $CFLAGS"
|
||||||
|
NGX_LD_OPT="$ngx_zstd_opt_L $NGX_LD_OPT"
|
||||||
|
|
||||||
|
# build the ngx_http_zstd_static_module
|
||||||
|
HTTP_ZSTD_SRCS="$ngx_addon_dir/static/ngx_http_zstd_static_module.c"
|
||||||
|
|
||||||
|
ngx_addon_name=ngx_http_zstd_static_module
|
||||||
|
ngx_module_type=HTTP
|
||||||
|
ngx_module_name=ngx_http_zstd_static_module
|
||||||
|
ngx_module_incs="$ngx_zstd_opt_I"
|
||||||
|
ngx_module_srcs=$HTTP_ZSTD_SRCS
|
||||||
|
|
||||||
|
. auto/module
|
||||||
383
ngx_zstd/static/ngx_http_zstd_static_module.c
Normal file
383
ngx_zstd/static/ngx_http_zstd_static_module.c
Normal file
@@ -0,0 +1,383 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Alex Zhang
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_core.h>
|
||||||
|
#include <ngx_http.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_HTTP_ZSTD_STATIC_OFF 0
|
||||||
|
#define NGX_HTTP_ZSTD_STATIC_ON 1
|
||||||
|
#define NGX_HTTP_ZSTD_STATIC_ALWAYS 2
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_uint_t enable;
|
||||||
|
} ngx_http_zstd_static_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_conf_enum_t ngx_http_zstd_static[] = {
|
||||||
|
{ ngx_string("off"), NGX_HTTP_ZSTD_STATIC_OFF },
|
||||||
|
{ ngx_string("on"), NGX_HTTP_ZSTD_STATIC_ON },
|
||||||
|
{ ngx_string("always"), NGX_HTTP_ZSTD_STATIC_ALWAYS },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_command_t ngx_http_zstd_static_commands[] = {
|
||||||
|
|
||||||
|
{ ngx_string("zstd_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(ngx_http_zstd_static_conf_t, enable),
|
||||||
|
&ngx_http_zstd_static },
|
||||||
|
|
||||||
|
ngx_null_command
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_zstd_static_handler(ngx_http_request_t *r);
|
||||||
|
static ngx_int_t ngx_http_zstd_accept_encoding(ngx_str_t *ae);
|
||||||
|
static ngx_int_t ngx_http_zstd_ok(ngx_http_request_t *r);
|
||||||
|
static void * ngx_http_zstd_static_create_loc_conf(ngx_conf_t *cf);
|
||||||
|
static char * ngx_http_zstd_static_merge_loc_conf(ngx_conf_t *cf, void *parent,
|
||||||
|
void *child);
|
||||||
|
static ngx_int_t ngx_http_zstd_static_init(ngx_conf_t *cf);
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_module_t ngx_http_zstd_static_module_ctx = {
|
||||||
|
NULL, /* preconfiguration */
|
||||||
|
ngx_http_zstd_static_init, /* postconfiguration */
|
||||||
|
|
||||||
|
NULL, /* create main configuration */
|
||||||
|
NULL, /* init main configuration */
|
||||||
|
|
||||||
|
NULL, /* create server configuration */
|
||||||
|
NULL, /* merge server configuration */
|
||||||
|
|
||||||
|
ngx_http_zstd_static_create_loc_conf, /* create location configuration */
|
||||||
|
ngx_http_zstd_static_merge_loc_conf, /* merge location configuration */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_module_t ngx_http_zstd_static_module = {
|
||||||
|
NGX_MODULE_V1,
|
||||||
|
&ngx_http_zstd_static_module_ctx, /* module context */
|
||||||
|
ngx_http_zstd_static_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 ngx_int_t
|
||||||
|
ngx_http_zstd_static_handler(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_uint_t level;
|
||||||
|
size_t root;
|
||||||
|
ngx_str_t path;
|
||||||
|
ngx_buf_t *b;
|
||||||
|
ngx_log_t *log;
|
||||||
|
ngx_table_elt_t *h;
|
||||||
|
ngx_chain_t out;
|
||||||
|
ngx_open_file_info_t of;
|
||||||
|
ngx_http_core_loc_conf_t *clcf;
|
||||||
|
ngx_http_zstd_static_conf_t *zscf;
|
||||||
|
|
||||||
|
if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r->uri.data[r->uri.len - 1] == '/') {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
zscf = ngx_http_get_module_loc_conf(r, ngx_http_zstd_static_module);
|
||||||
|
|
||||||
|
if (zscf->enable == NGX_HTTP_ZSTD_STATIC_OFF) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zscf->enable == NGX_HTTP_ZSTD_STATIC_ON) {
|
||||||
|
rc = ngx_http_zstd_ok(r);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
rc = NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||||
|
|
||||||
|
if (!clcf->gzip_vary && rc != NGX_OK) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
log = r->connection->log;
|
||||||
|
|
||||||
|
p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".zst") - 1);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p++ = '.';
|
||||||
|
*p++ = 'z';
|
||||||
|
*p++ = 's';
|
||||||
|
*p++ = 't';
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
path.len = p - path.data;
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
|
||||||
|
"http filename: \"%s\"", path.data);
|
||||||
|
|
||||||
|
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
|
||||||
|
|
||||||
|
of.read_ahead = clcf->read_ahead;
|
||||||
|
of.directio = clcf->directio;
|
||||||
|
of.valid = clcf->open_file_cache_valid;
|
||||||
|
of.min_uses = clcf->open_file_cache_min_uses;
|
||||||
|
of.errors = clcf->open_file_cache_errors;
|
||||||
|
of.events = clcf->open_file_cache_events;
|
||||||
|
|
||||||
|
if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
switch (of.err) {
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
|
||||||
|
case NGX_ENOENT:
|
||||||
|
case NGX_ENOTDIR:
|
||||||
|
case NGX_ENAMETOOLONG:
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
|
||||||
|
case NGX_EACCES:
|
||||||
|
#if (NGX_HAVE_OPENAT)
|
||||||
|
case NGX_EMLINK:
|
||||||
|
case NGX_ELOOP:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
level = NGX_LOG_ERR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
level = NGX_LOG_CRIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(level, log, of.err,
|
||||||
|
"%s \"%s\" failed", of.failed, path.data);
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zscf->enable == NGX_HTTP_ZSTD_STATIC_ON) {
|
||||||
|
r->gzip_vary = 1;
|
||||||
|
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
|
||||||
|
|
||||||
|
if (of.is_dir) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !(NGX_WIN32) /* the not regular files are probably Unix specific */
|
||||||
|
|
||||||
|
if (!of.is_file) {
|
||||||
|
ngx_log_error(NGX_LOG_CRIT, log, 0,
|
||||||
|
"\"%s\" is not a regular file", path.data);
|
||||||
|
|
||||||
|
return NGX_HTTP_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
r->root_tested = !r->error_page;
|
||||||
|
|
||||||
|
rc = ngx_http_discard_request_body(r);
|
||||||
|
if (rc != NGX_OK) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
log->action = "sending response to client";
|
||||||
|
|
||||||
|
r->headers_out.status = NGX_HTTP_OK;
|
||||||
|
r->headers_out.content_length_n = of.size;
|
||||||
|
r->headers_out.last_modified_time = of.mtime;
|
||||||
|
|
||||||
|
if (ngx_http_set_etag(r) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_http_set_content_type(r) != NGX_OK) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
h = ngx_list_push(&r->headers_out.headers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
h->hash = 1;
|
||||||
|
ngx_str_set(&h->key, "Content-Encoding");
|
||||||
|
ngx_str_set(&h->value, "zstd");
|
||||||
|
r->headers_out.content_encoding = h;
|
||||||
|
|
||||||
|
b = ngx_calloc_buf(r->pool);
|
||||||
|
if (b == NULL) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
|
||||||
|
if (b->file == NULL) {
|
||||||
|
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_http_send_header(r);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->file_pos = 0;
|
||||||
|
b->file_last = of.size;
|
||||||
|
|
||||||
|
b->in_file = b->file_last ? 1 : 0;
|
||||||
|
b->last_buf = (r == r->main) ? 1 : 0;
|
||||||
|
b->last_in_chain = 1;
|
||||||
|
|
||||||
|
b->file->fd = of.fd;
|
||||||
|
b->file->name = path;
|
||||||
|
b->file->log = log;
|
||||||
|
b->file->directio = of.is_directio;
|
||||||
|
|
||||||
|
out.buf = b;
|
||||||
|
out.next = NULL;
|
||||||
|
|
||||||
|
return ngx_http_output_filter(r, &out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_zstd_ok(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_table_elt_t *ae;
|
||||||
|
|
||||||
|
if (r != r->main) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ae = r->headers_in.accept_encoding;
|
||||||
|
if (ae == NULL) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ae->value.len < sizeof("zstd") - 1) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_memcmp(ae->value.data, "zstd", 4) != 0
|
||||||
|
&& ngx_http_zstd_accept_encoding(&ae->value) != NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
r->gzip_tested = 1;
|
||||||
|
r->gzip_ok = 0;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_zstd_accept_encoding(ngx_str_t *ae)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
|
||||||
|
p = ngx_strcasestrn(ae->data, "zstd", sizeof("zstd") - 1);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == ae->data || (*(p - 1) == ',' || *(p - 1) == ' ')) {
|
||||||
|
|
||||||
|
p += sizeof("zstd") - 1;
|
||||||
|
|
||||||
|
if (p == ae->data + ae->len || *p == ',' || *p == ' ' || *p == ';') {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
ngx_http_zstd_static_create_loc_conf(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_zstd_static_conf_t *conf;
|
||||||
|
|
||||||
|
conf = ngx_palloc(cf->pool, sizeof(ngx_http_zstd_static_conf_t));
|
||||||
|
if (conf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->enable = NGX_CONF_UNSET_UINT;
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_zstd_static_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
|
{
|
||||||
|
ngx_http_zstd_static_conf_t *prev = parent;
|
||||||
|
ngx_http_zstd_static_conf_t *conf = child;
|
||||||
|
|
||||||
|
ngx_conf_merge_uint_value(conf->enable, prev->enable,
|
||||||
|
NGX_HTTP_ZSTD_STATIC_OFF);
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_zstd_static_init(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_handler_pt *h;
|
||||||
|
ngx_http_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
|
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
|
||||||
|
|
||||||
|
h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = ngx_http_zstd_static_handler;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
8
ngx_zstd/t/00-filter.t
Normal file
8
ngx_zstd/t/00-filter.t
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use Test::Nginx::Socket::Lua;
|
||||||
|
|
||||||
|
no_long_string();
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
|
||||||
198
ngx_zstd/t/01-static.t
Normal file
198
ngx_zstd/t/01-static.t
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
use Test::Nginx::Socket;
|
||||||
|
use lib 'lib';
|
||||||
|
|
||||||
|
no_long_string();
|
||||||
|
log_level 'debug';
|
||||||
|
repeat_each(3);
|
||||||
|
plan tests => repeat_each() * ((blocks() - 3) * 5 + 3);
|
||||||
|
run_tests();
|
||||||
|
|
||||||
|
|
||||||
|
__DATA__
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 1: zstd_static off
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
zstd_static off;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 59738
|
||||||
|
ETag: "5be17d33-e95a"
|
||||||
|
!Content-Encoding
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 2: zstd_static off (with accept-encoding header)
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
zstd_static off;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
Accept-Encoding: gzip,zstd
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 59738
|
||||||
|
ETag: "5be17d33-e95a"
|
||||||
|
!Content-Encoding
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 3: zstd_static on
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
zstd_static on;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
--- more_headers
|
||||||
|
Accept-Encoding: gzip, zstd
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 20706
|
||||||
|
ETag: "5be17d33-50e2"
|
||||||
|
!Content-Encoding
|
||||||
|
Content-Encoding: zstd
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 4: zstd_static on (without accept-encoding header)
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
zstd_static on;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 59738
|
||||||
|
ETag: "5be17d33-e95a"
|
||||||
|
Content-Encoding: zstd
|
||||||
|
!Content-Encoding
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 5: zstd_static on (without zstd component in accept-encoding header)
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
zstd_static on;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
--- more_headers
|
||||||
|
Accept-Encoding: gzip, br
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 59738
|
||||||
|
ETag: "5be17d33-e95a"
|
||||||
|
!Content-Encoding
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 6: zstd_static always
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
zstd_static always;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
--- more_headers
|
||||||
|
Accept-Encoding: gzip, br
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 20706
|
||||||
|
ETag: "5be17d33-50e2"
|
||||||
|
Content-Encoding: zstd
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 6: zstd_static always (without accept-encoding header)
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
zstd_static always;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 20706
|
||||||
|
ETag: "5be17d33-50e2"
|
||||||
|
Content-Encoding: zstd
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 7: zstd_static always (without zstd component in accept-encoding header)
|
||||||
|
--- config
|
||||||
|
location /test {
|
||||||
|
zstd_static always;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test
|
||||||
|
--- more_headers
|
||||||
|
Accept-Encoding: gzip, br
|
||||||
|
--- response_headers
|
||||||
|
Content-Length: 20706
|
||||||
|
ETag: "5be17d33-50e2"
|
||||||
|
Content-Encoding: zstd
|
||||||
|
--- no_error_log
|
||||||
|
[error]
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 8: zstd_static always (file does not exist)
|
||||||
|
--- config
|
||||||
|
location /test2 {
|
||||||
|
zstd_static always;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test2
|
||||||
|
--- more_headers
|
||||||
|
Accept-Encoding: gzip, br
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 9: zstd_static on (file does not exist)
|
||||||
|
--- config
|
||||||
|
location /test2 {
|
||||||
|
zstd_static on;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test2
|
||||||
|
--- more_headers
|
||||||
|
Accept-Encoding: gzip, br
|
||||||
|
--- error_code: 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
=== TEST 10: zstd_static off (file does not exist)
|
||||||
|
--- config
|
||||||
|
location /test2 {
|
||||||
|
zstd_static off;
|
||||||
|
root ../../t/suite;
|
||||||
|
}
|
||||||
|
--- request
|
||||||
|
GET /test2
|
||||||
|
--- more_headers
|
||||||
|
Accept-Encoding: gzip, br
|
||||||
|
--- error_code: 404
|
||||||
2040
ngx_zstd/t/suite/test
Normal file
2040
ngx_zstd/t/suite/test
Normal file
File diff suppressed because it is too large
Load Diff
BIN
ngx_zstd/t/suite/test.zst
Normal file
BIN
ngx_zstd/t/suite/test.zst
Normal file
Binary file not shown.
218
ngx_zstd/valgrind.suppress
Normal file
218
ngx_zstd/valgrind.suppress
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Addr1
|
||||||
|
fun:ngx_init_cycle
|
||||||
|
fun:ngx_master_process_cycle
|
||||||
|
fun:main
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Addr4
|
||||||
|
fun:ngx_init_cycle
|
||||||
|
fun:ngx_master_process_cycle
|
||||||
|
fun:main
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:ngx_vslprintf
|
||||||
|
fun:ngx_snprintf
|
||||||
|
fun:ngx_sock_ntop
|
||||||
|
fun:ngx_event_accept
|
||||||
|
fun:ngx_epoll_process_events
|
||||||
|
fun:ngx_process_events_and_timers
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Addr1
|
||||||
|
fun:ngx_vslprintf
|
||||||
|
fun:ngx_snprintf
|
||||||
|
fun:ngx_sock_ntop
|
||||||
|
fun:ngx_event_accept
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
exp-sgcheck:SorG
|
||||||
|
fun:ngx_http_lua_ndk_set_var_get
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
exp-sgcheck:SorG
|
||||||
|
fun:ngx_http_variables_init_vars
|
||||||
|
fun:ngx_http_block
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
exp-sgcheck:SorG
|
||||||
|
fun:ngx_conf_parse
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
exp-sgcheck:SorG
|
||||||
|
fun:ngx_vslprintf
|
||||||
|
fun:ngx_log_error_core
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
epoll_ctl(event)
|
||||||
|
fun:epoll_ctl
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:ngx_conf_flush_files
|
||||||
|
fun:ngx_single_process_cycle
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:memcpy
|
||||||
|
fun:ngx_vslprintf
|
||||||
|
fun:ngx_log_error_core
|
||||||
|
fun:ngx_http_charset_header_filter
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
socketcall.setsockopt(optval)
|
||||||
|
fun:setsockopt
|
||||||
|
fun:drizzle_state_connect
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:ngx_conf_flush_files
|
||||||
|
fun:ngx_single_process_cycle
|
||||||
|
fun:main
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_event_process_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
sendmsg(mmsg[0].msg_hdr)
|
||||||
|
fun:sendmmsg
|
||||||
|
fun:__libc_res_nsend
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
sendmsg(msg.msg_iov[0])
|
||||||
|
fun:__sendmsg_nocancel
|
||||||
|
fun:ngx_write_channel
|
||||||
|
fun:ngx_pass_open_channel
|
||||||
|
fun:ngx_start_cache_manager_processes
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:ngx_init_cycle
|
||||||
|
fun:ngx_master_process_cycle
|
||||||
|
fun:main
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
fun:index
|
||||||
|
fun:expand_dynamic_string_token
|
||||||
|
fun:_dl_map_object
|
||||||
|
fun:map_doit
|
||||||
|
fun:_dl_catch_error
|
||||||
|
fun:do_preload
|
||||||
|
fun:dl_main
|
||||||
|
fun:_dl_sysdep_start
|
||||||
|
fun:_dl_start
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
sendmsg(mmsg[0].msg_hdr)
|
||||||
|
fun:sendmmsg
|
||||||
|
fun:__libc_res_nsend
|
||||||
|
fun:__libc_res_nquery
|
||||||
|
fun:__libc_res_nquerydomain
|
||||||
|
fun:__libc_res_nsearch
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: definite
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_set_environment
|
||||||
|
fun:ngx_single_process_cycle
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Cond
|
||||||
|
obj:*
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: definite
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_set_environment
|
||||||
|
fun:ngx_worker_process_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: definite
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_create_pool
|
||||||
|
fun:main
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
epoll_pwait(sigmask)
|
||||||
|
fun:epoll_pwait
|
||||||
|
fun:epoll_wait
|
||||||
|
fun:ngx_epoll_process_events
|
||||||
|
fun:ngx_process_events_and_timers
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
epoll_pwait(sigmask)
|
||||||
|
fun:epoll_pwait
|
||||||
|
fun:epoll_wait
|
||||||
|
fun:ngx_epoll_test_rdhup
|
||||||
|
fun:ngx_epoll_init
|
||||||
|
fun:ngx_event_process_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
epoll_pwait(sigmask)
|
||||||
|
fun:epoll_pwait
|
||||||
|
fun:ngx_epoll_process_events
|
||||||
|
fun:ngx_process_events_and_timers
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Param
|
||||||
|
epoll_pwait(sigmask)
|
||||||
|
fun:epoll_pwait
|
||||||
|
fun:ngx_epoll_test_rdhup
|
||||||
|
fun:ngx_epoll_init
|
||||||
|
fun:ngx_event_process_init
|
||||||
|
}
|
||||||
|
{
|
||||||
|
<insert_a_suppression_name_here>
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: possible
|
||||||
|
fun:malloc
|
||||||
|
fun:ngx_alloc
|
||||||
|
fun:ngx_crc32_table_init
|
||||||
|
fun:main
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user