debian/0000775000000000000000000000000012705460163007174 5ustar debian/rules0000775000000000000000000001374212705233614010262 0ustar #!/usr/bin/make -f export DH_VERBOSE=1 export DEB_BUILD_MAINT_OPTIONS=hardening=+all debian_cflags:=$(shell dpkg-buildflags --get CFLAGS) $(shell dpkg-buildflags --get CPPFLAGS) debian_ldflags:=$(shell dpkg-buildflags --get LDFLAGS) # export necessary perl hardenging flags # see: src/http/modules/perl/Makefile.PL DEBIAN_NGINX_PERL_LDFLAGS:= $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-pie dpkg-buildflags --get LDFLAGS) export DEBIAN_NGINX_PERL_LDFLAGS FLAVOURS := core full light extras MODULESDIR = $(CURDIR)/debian/modules BASEDIR = $(CURDIR) $(foreach flavour,$(FLAVOURS),$(eval BUILDDIR_$(flavour) = $(CURDIR)/debian/build-$(flavour))) DEB_BUILD_ARCH ?=$(shell dpkg-architecture -qDEB_BUILD_ARCH) ifeq ($(DEB_BUILD_ARCH),sparc) debian_cflags += -m32 -mcpu=ultrasparc endif ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) MAKEFLAGS += -j$(NUMJOBS) endif # configure flags common_configure_flags := \ --with-cc-opt="$(debian_cflags)" \ --with-ld-opt="$(debian_ldflags)" \ --prefix=/usr/share/nginx \ --conf-path=/etc/nginx/nginx.conf \ --http-log-path=/var/log/nginx/access.log \ --error-log-path=/var/log/nginx/error.log \ --lock-path=/var/lock/nginx.lock \ --pid-path=/run/nginx.pid \ --http-client-body-temp-path=/var/lib/nginx/body \ --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ --http-proxy-temp-path=/var/lib/nginx/proxy \ --http-scgi-temp-path=/var/lib/nginx/scgi \ --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \ --with-debug \ --with-pcre-jit \ --with-ipv6 \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-http_realip_module \ --with-http_auth_request_module core_configure_flags := \ $(common_configure_flags) \ --with-http_addition_module \ --with-http_dav_module \ --with-http_geoip_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_image_filter_module \ --with-http_v2_module \ --with-http_sub_module \ --with-http_xslt_module \ --with-stream \ --with-stream_ssl_module \ --with-mail \ --with-mail_ssl_module \ --with-threads light_configure_flags := \ $(common_configure_flags) \ --with-http_gzip_static_module \ --without-http_browser_module \ --without-http_geo_module \ --without-http_limit_req_module \ --without-http_limit_conn_module \ --without-http_memcached_module \ --without-http_referer_module \ --without-http_scgi_module \ --without-http_split_clients_module \ --without-http_ssi_module \ --without-http_userid_module \ --without-http_uwsgi_module \ --add-module=$(MODULESDIR)/nginx-echo full_configure_flags := \ $(common_configure_flags) \ --with-http_addition_module \ --with-http_dav_module \ --with-http_geoip_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_image_filter_module \ --with-http_v2_module \ --with-http_sub_module \ --with-http_xslt_module \ --with-stream \ --with-stream_ssl_module \ --with-mail \ --with-mail_ssl_module \ --with-threads \ --add-module=$(MODULESDIR)/nginx-auth-pam \ --add-module=$(MODULESDIR)/nginx-dav-ext-module \ --add-module=$(MODULESDIR)/nginx-echo \ --add-module=$(MODULESDIR)/nginx-upstream-fair \ --add-module=$(MODULESDIR)/ngx_http_substitutions_filter_module extras_configure_flags := \ $(common_configure_flags) \ --with-http_addition_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_geoip_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_image_filter_module \ --with-http_mp4_module \ --with-http_perl_module \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_v2_module \ --with-http_sub_module \ --with-http_xslt_module \ --with-mail \ --with-mail_ssl_module \ --with-stream \ --with-stream_ssl_module \ --with-threads \ --add-module=$(MODULESDIR)/headers-more-nginx-module \ --add-module=$(MODULESDIR)/nginx-auth-pam \ --add-module=$(MODULESDIR)/nginx-cache-purge \ --add-module=$(MODULESDIR)/nginx-dav-ext-module \ --add-module=$(MODULESDIR)/nginx-development-kit \ --add-module=$(MODULESDIR)/nginx-echo \ --add-module=$(MODULESDIR)/ngx-fancyindex \ --add-module=$(MODULESDIR)/nginx-http-push \ --add-module=$(MODULESDIR)/nginx-lua \ --add-module=$(MODULESDIR)/nginx-upload-progress \ --add-module=$(MODULESDIR)/nginx-upstream-fair \ --add-module=$(MODULESDIR)/ngx_http_substitutions_filter_module %: dh $@ --with systemd override_dh_auto_configure: $(foreach flavour,$(FLAVOURS),config.arch.$(flavour)) override_dh_auto_build: $(foreach flavour,$(FLAVOURS),build.arch.$(flavour)) override_dh_strip: $(foreach flavour,$(FLAVOURS),strip.arch.$(flavour)) override_dh_clean: $(foreach flavour,$(FLAVOURS),clean.$(flavour)) dh_clean override_dh_installinit: dh_installinit --no-restart-on-upgrade --no-start --name=nginx override_dh_systemd_enable: dh_systemd_enable --name=nginx override_dh_installlogrotate: dh_installlogrotate --package nginx-common --name=nginx build.arch.%: $(MAKE) -C $(BUILDDIR_$*) build strip.arch.%: dh_strip --package=nginx-$(*) --dbg-package=nginx-$(*)-dbg config.arch.%: dh_testdir mkdir -p $(BUILDDIR_$*) cp -Pa $(CURDIR)/auto $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/conf $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/configure $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/contrib $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/src $(BUILDDIR_$*)/ cp -Pa $(CURDIR)/man $(BUILDDIR_$*)/ cd $(BUILDDIR_$*) && ./configure $($*_configure_flags) clean.%: rm -rf $(BUILDDIR_$*) debian/compat0000664000000000000000000000000212705233614010371 0ustar 9 debian/ufw/0000775000000000000000000000000012705233614007774 5ustar debian/ufw/nginx0000664000000000000000000000056612705233614011051 0ustar [Nginx HTTP] title=Web Server (Nginx, HTTP) description=Small, but very powerful and efficient web server ports=80/tcp [Nginx HTTPS] title=Web Server (Nginx, HTTPS) description=Small, but very powerful and efficient web server ports=443/tcp [Nginx Full] title=Web Server (Nginx, HTTP + HTTPS) description=Small, but very powerful and efficient web server ports=80,443/tcp debian/nginx-common.postrm0000664000000000000000000000127112705233614013053 0ustar #!/bin/sh set -e # Handle naxsi removal dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi.rules 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi_core.rules 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf.1.4.1 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf 1.6.2-2~ -- "$@" case "$1" in purge) rm -rf /var/lib/nginx /var/log/nginx /etc/nginx ;; upgrade|remove|failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 debian/nginx-common.lintian-overrides0000664000000000000000000000014012705233614015157 0ustar # /var/www/html is the default document root nginx-common: dir-or-file-in-var-www var/www/html/ debian/nginx-common.preinst0000664000000000000000000000240512705233614013213 0ustar #!/bin/sh set -e # Handle naxsi removal dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi.rules 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi_core.rules 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf.1.4.1 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf 1.6.2-2~ -- "$@" case "$1" in install) # If we are doing a fresh install, then these files are no longer needed. # They were around for a very short time and are best simply removed. rm -f /etc/logrotate.d/nginx-full rm -f /etc/logrotate.d/nginx-light rm -f /etc/logrotate.d/nginx-extras rm -f /etc/logrotate.d/nginx-common ;; upgrade) # If this is an upgrade, then they might have the UFW profile in the wrong spot. if [ -d /etc/ufw/applications.d/nginx ]; then rm -f /etc/ufw/applications.d/nginx/ufw.profile rmdir /etc/ufw/applications.d/nginx fi rm -f /etc/logrotate.d/nginx-full rm -f /etc/logrotate.d/nginx-light rm -f /etc/logrotate.d/nginx-extras rm -f /etc/logrotate.d/nginx-common ;; abort-upgrade) ;; *) echo "preinst called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 debian/upstream/0000775000000000000000000000000012705233614011033 5ustar debian/upstream/signing-key.asc0000664000000000000000000000373112705233614013753 0ustar -----BEGIN PGP PUBLIC KEY BLOCK----- mQENBE7SKu8BCADQo6x4ZQfAcPlJMLmL8zBEBUS6GyKMMMDtrTh3Yaq481HB54oR 0cpKL05Ff9upjrIzLD5TJUCzYYM9GQOhguDUP8+ZU9JpSz3yO2TvH7WBbUZ8FADf hblmmUBLNgOWgLo3W+FYhl3mz1GFS2Fvid6Tfn02L8CBAj7jxbjL1Qj/OA/WmLLc m6BMTqI7IBlYW2vyIOIHasISGiAwZfp0ucMeXXvTtt14LGa8qXVcFnJTdwbf03AS ljhYrQnKnpl3VpDAoQt8C68YCwjaNJW59hKqWB+XeIJ9CW98+EOAxLAFszSyGanp rCqPd0numj9TIddjcRkTA/ZbmCWK+xjpVBGXABEBAAG0IU1heGltIERvdW5pbiA8 bWRvdW5pbkBtZG91bmluLnJ1PohGBBARAgAGBQJO01Y/AAoJEOzw6QssFyCDVyQA n3qwTZlcZgyyzWu9Cs8gJ0CXREaSAJ92QjGLT9DijTcbB+q9OS/nl16Z/IhGBBAR AgAGBQJO02JDAAoJEKk3YTmlJMU+P64AnjCKEXFelSVMtgefJk3+vpyt3QX1AKCH 9M3MbTWPeDUL+MpULlfdyfvjj4heBBARCAAGBQJRCTwgAAoJEFGFCWhsfl6CzF0B AJsQ3DJbtGcZ+0VIcM2a06RRQfBvIHqm1A/1WSYmObLGAP90lxWlNjSugvUUlqTk YEEgRTGozgixSyMWGJrNwqgMYokBOAQTAQIAIgUCTtIq7wIbAwYLCQgHAwIGFQgC CQoLBBYCAwECHgECF4AACgkQUgqZk6HAUvj+iwf/b4FS6zVzJ5T0v1vcQGD4ZzXe D5xMC4BJW414wVMU15rfX7aCdtoCYBNiApPxEd7SwiyxWRhRA9bikUq87JEgmnyV 0iYbHZvCvc1jOkx4WR7E45t1Mi29KBoPaFXA9X5adZkYcOQLDxa2Z8m6LGXnlF6N tJkxQ8APrjZsdrbDvo3HxU9muPcq49ydzhgwfLwpUs11LYkwB0An9WRPuv3jporZ /XgI6RfPMZ5NIx+FRRCjn6DnfHboY9rNF6NzrOReJRBhXCi6I+KkHHEnMoyg8XET 9lVkfHTOl81aIZqrAloX3/00TkYWyM2zO9oYpOg6eUFCX/Lw4MJZsTcT5EKVxLkB DQRO0irvAQgA0LjCc8S6oZzjiap2MjRNhRFA5BYjXZRZBdKF2VP74avt2/RELq8G W0n7JWmKn6vvrXabEGLyfkCngAhTq9tJ/K7LPx/bmlO5+jboO/1inH2BTtLiHjAX vicXZk3oaZt2Sotx5mMI3yzpFQRVqZXsi0LpUTPJEh3oS8IdYRjslQh1A7P5hfCZ wtzwb/hKm8upODe/ITUMuXeWfLuQj/uEU6wMzmfMHb+jlYMWtb+v98aJa2FODeKP mWCXLa7bliXp1SSeBOEfIgEAmjM6QGlDx5sZhr2Ss2xSPRdZ8DqD7oiRVzmstX1Y oxEzC0yXfaefC7SgM0nMnaTvYEOYJ9CH3wARAQABiQEfBBgBAgAJBQJO0irvAhsM AAoJEFIKmZOhwFL4844H/jo8icCcS6eOWvnen7lg0FcCo1fIm4wW3tEmkQdchSHE CJDq7pgTloN65pwB5tBoT47cyYNZA9eTfJVgRc74q5cexKOYrMC3KuAqWbwqXhkV s0nkWxnOIidTHSXvBZfDFA4Idwte94Thrzf8Pn8UESudTiqrWoCBXk2UyVsl03gJ blSJAeJGYPPeo+Yj6m63OWe2+/S2VTgmbPS/RObn0Aeg7yuff0n5+ytEt2KL51gO QE2uIxTCawHr12PsllPkbqPk/PagIttfEJqn9b0CrqPC3HREePb2aMJ/Ctw/76CO wn0mtXeIXLCTvBmznXfaMKllsqbsy2nCJ2P2uJjOntw= =ISka -----END PGP PUBLIC KEY BLOCK----- debian/nginx-common.postinst0000664000000000000000000000311212705233614013406 0ustar #!/bin/sh set -e # Handle naxsi removal dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi.rules 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi_core.rules 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf.1.4.1 1.6.2-2~ -- "$@" dpkg-maintscript-helper rm_conffile \ /etc/nginx/naxsi-ui.conf 1.6.2-2~ -- "$@" case "$1" in configure) logdir="/var/log/nginx" # Ensure secure permissions (CVE-2013-0337) # http://bugs.debian.org/701112 # # nginx uses 0755 for log files making them world readable, # we fix that by using 0750 for the log directory. # # Allow local admin to override: # e.g. dpkg-statoverride --add root adm 0755 /var/log/nginx if ! dpkg-statoverride --list "$logdir" >/dev/null; then chown www-data:adm $logdir chmod 0750 $logdir fi # If a symlink doesn't exist and can be created, then create it. if [ -z $2 ] && [ ! -e /etc/nginx/sites-enabled/default ] && [ -d /etc/nginx/sites-enabled ] && [ -d /etc/nginx/sites-available ]; then ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default fi # Create a default index page when not already present. if [ ! -e /var/www/html/index.nginx-debian.html ]; then cp /usr/share/nginx/html/index.html /var/www/html/index.nginx-debian.html fi ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 debian/nginx-extras.lintian-overrides0000664000000000000000000000007612705233614015205 0ustar nginx-extras: spelling-error-in-binary usr/sbin/nginx tEH the debian/nginx-common.nginx.service0000664000000000000000000000173212705233614014313 0ustar # Stop dance for nginx # ======================= # # ExecStop sends SIGSTOP (graceful stop) to the nginx process. # If, after 5s (--retry QUIT/5) nginx is still running, systemd takes control # and sends SIGTERM (fast shutdown) to the main process. # After another 5s (TimeoutStopSec=5), and if nginx is alive, systemd sends # SIGKILL to all the remaining processes in the process group (KillMode=mixed). # # nginx signals reference doc: # http://nginx.org/en/docs/control.html # [Unit] Description=A high performance web server and a reverse proxy server After=network.target [Service] Type=forking PIDFile=/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid TimeoutStopSec=5 KillMode=mixed [Install] WantedBy=multi-user.target debian/nginx-full.prerm0000664000000000000000000000050412705233614012324 0ustar #!/bin/sh set -e case "$1" in remove|remove-in-favour|deconfigure|deconfigure-in-favour) if [ -x /etc/init.d/nginx ]; then invoke-rc.d nginx stop || exit $? fi ;; upgrade|failed-upgrade) ;; *) echo "prerm called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 debian/nginx-light.lintian-overrides0000664000000000000000000000007512705233614015005 0ustar nginx-light: spelling-error-in-binary usr/sbin/nginx tEH the debian/nginx-extras.manpages0000664000000000000000000000004112705233614013332 0ustar debian/build-extras/objs/nginx.8 debian/apport/0000775000000000000000000000000012705233614010500 5ustar debian/apport/source_nginx.py0000664000000000000000000000125412705233614013557 0ustar ''' apport package hook for nginx packages Copyright (c) 2015, Thomas Ward ''' import apport.hookutils import os import subprocess def add_info(report, ui): if (report['Package'].split()[0] != 'nginx-common' and report['ProblemType'] == 'Package' and os.path.isdir('/run/systemd/system')): report['Journalctl_Nginx.txt'] = apport.hookutils.command_output( ['journalctl', '-xe', '--unit=nginx.service']) report['SystemctlStatusFull_Nginx.txt'] = subprocess.Popen( ['systemctl', '-l', 'status', 'nginx.service'], stdout=subprocess.PIPE).communicate()[0] debian/nginx-light.manpages0000664000000000000000000000004012705233614013132 0ustar debian/build-light/objs/nginx.8 debian/ngx-conf/0000775000000000000000000000000012705233614010712 5ustar debian/ngx-conf/ngx-conf0000775000000000000000000002765112705233614012372 0ustar #!/usr/bin/env python ## # copyright (c) 2015 Michael Lustfield # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the sale, # use or other dealings in this Software without prior written authorization. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. ## import argparse try: import configparser as ConfigParser except: import ConfigParser import glob import os import subprocess # Read configuration values config_opts = ConfigParser.SafeConfigParser({ 'base_dir': '/etc/nginx/', 'conf_dir': 'conf.d/', 'sites_en': 'sites-enabled/', 'sites_dis': 'sites-available/', 'conf_ext': '.conf', 'verbose': 'no', 'reload': 'no', 'force': 'no'}) config_opts.read('/etc/nginx/ngx.cfg') config_opts.read('/etc/ngx.cfg') config_opts.read('ngx.cfg') # Variable that we'll use a lot. sites_en = config_opts.get('DEFAULT', 'base_dir') + config_opts.get('DEFAULT', 'sites_en') sites_dis = config_opts.get('DEFAULT', 'base_dir') + config_opts.get('DEFAULT', 'sites_dis') conf_dir = config_opts.get('DEFAULT', 'base_dir') + config_opts.get('DEFAULT', 'conf_dir') conf_ext = config_opts.get('DEFAULT', 'conf_ext') def parse_arguments(): '''Parse arguments supplied by the user.''' parser = argparse.ArgumentParser(description='nginx configuration helper', epilog='Only one in group (enable|disable|remove|list) is allowed.', usage='ngx-conf [-h] (-e | -d | -x | -l) [-f] [-r] [-v] FILE [FILES]') group = parser.add_mutually_exclusive_group(required=True) group.add_argument('-e', '--enable', action='store_true', help='enable a configuration files') group.add_argument('-d', '--disable', action='store_true', help='disable a configuration files') group.add_argument('-x', '--remove', action='store_true', help='remove a configuration files; will prompt without -f') group.add_argument('-l', '--list', action='store_true', help='list configuration files') parser.add_argument('-f', '--force', action='store_true', default=config_opts.getboolean('DEFAULT', 'force'), help='force change, even if doing so will destroy data') parser.add_argument('-r', '--reload', action='store_true', default=config_opts.getboolean('DEFAULT', 'reload'), help='reload configuration after change') parser.add_argument('-v', '--verbose', action='store_true', default=config_opts.getboolean('DEFAULT', 'verbose'), help='show verbose output; default is quite unless errors') parser.add_argument('FILES', nargs=argparse.REMAINDER, help='a list of configuration files to update') return parser.parse_args() def main(): '''Main execution; read arguments and act accordingly.''' args = parse_arguments() if args.FILES == [] and not args.list: print('No files specified. These are required.') return False if args.enable: enable_configs(args.FILES, args.verbose, args.force) elif args.disable: disable_configs(args.FILES, args.verbose, args.force) elif args.remove: remove_configs(args.FILES, args.verbose, args.force) elif args.list: list_configs() if args.reload and not args.list: reload_nginx() def enable_configs(configs, verbose, force): '''Enable configurtion files specified.''' if type(configs) != list: print('Configuration list is in an incorrect format.') return 1 for conf in configs: if os.path.isfile(conf_dir + conf + conf_ext) or os.path.islink(sites_en + conf) or os.path.isfile(sites_en + conf): if verbose: print('Configuration file "{}" is already enabled.'.format(conf)) elif os.path.isfile(conf_dir + conf + conf_ext + '_disabled'): if not force and os.path.isfile(sites_dis + conf): print('Configuration file "{}" has conflicts.'.format(conf)) else: try: os.rename(conf_dir + conf + conf_ext + '_disabled', conf_dir + conf + conf_ext) if verbose: print('Configuration file "{}" has been enabled.'.format(conf)) except: print('Error occured when trying to enable "{}". Permissions?'.format(conf)) elif os.path.isfile(sites_dis + conf): try: os.symlink(sites_dis + conf, sites_en + conf) if verbose: print('Configuration file "{}" has been enabled.'.format(conf)) except: print('Error occured when trying to enable "{}". Permissions?'.format(conf)) else: print('Configuration file for "{}" was not found.'.format(conf)) def disable_configs(configs, verbose, force): '''Disable configurtion files specified.''' if type(configs) != list: print('Configuration list is in an incorrect format.') return 1 for conf in configs: if not force and os.path.isfile(conf_dir + conf + conf_ext) and os.path.islink(sites_en + conf): print('Configuration file "{}" has conflicts.'.format(conf)) elif not force and os.path.isfile(conf_dir + conf + conf_ext) and os.path.isfile(sites_en + conf): print('Configuration file "{}" has conflicts.'.format(conf)) elif os.path.isfile(conf_dir + conf + conf_ext): if not force and os.path.isfile(conf_dir + conf + conf_ext + '_disabled'): print('Unable to disable "{}". It appears to have a disabled version.'.format(conf)) break elif os.path.isfile(conf_dir + conf + conf_ext + '_disabled'): if verbose: print('Attempting to remove disabled config for {}.'.format(conf)) try: os.remove(conf_dir + conf + conf_ext + '_disabled') except: print('Error trying to remove configuration for disabled "{}".'.format(conf)) break try: os.rename(conf_dir + conf + conf_ext, conf_dir + conf + conf_ext + '_disabled') if verbose: print('Configuration file "{}" has been disabled.'.format(conf)) except: print('Error occured when trying to disable "{}". Permissions?'.format(conf)) elif os.path.islink(sites_en + conf): try: os.remove(sites_en + conf) if verbose: print('Configuration file "{}" has been disabled.'.format(conf)) except: print('Error occured when trying to disable "{}". Permissions?'.format(conf)) elif os.path.isfile(sites_en + conf): if not force and os.path.isfile(sites_dis + conf): print('Unable to disable "{}". It appears to have a disabled version.'.format(conf)) break elif os.path.isfile(sites_dis + conf): if verbose: print('Attempting to remove disabled config for {}.'.format(conf)) try: os.remove(sites_dis + conf) except: print('Error trying to remove configuration for disabled "{}".'.format(conf)) break try: os.rename(sites_en + conf, sites_dis + conf) if verbose: print('Configuration file "{}" has been disabled.'.format(conf)) except: print('Error occured when trying to disable "{}". Permissions?'.format(conf)) else: print('Configuration file for "{}" was not found.'.format(conf)) def remove_configs(configs, verbose, force): '''Remove configurtion files specified.''' if type(configs) != list: print('Configuration list is in an incorrect format.') return 1 for conf in configs: if os.path.islink(sites_en + conf): try: os.remove(sites_en + conf) if verbose: print('Symlink for "{}" removed.'.format(conf)) except: print('Error occured when trying to remove symlink for "{}". Permissions?'.format(conf)) files = [sites_en + conf, sites_dis + conf, conf_dir + conf + conf_ext, conf_dir + conf + conf_ext + '_disabled'] for f in files: if os.path.isfile(f): if not force: answer = str(raw_input('Are you sure you want to delete {}? (y/N) '.format(f))) if answer.lower() != 'y' and answer.lower() != 'yes': break try: os.remove(f) if verbose: print('Configuration file for "{}" was removed.'.format(f)) except: print('Error occured when trying to remove file for "{}". Permissions?'.format(f)) def list_configs(): '''List configuration files.''' configs = get_configs() for key, verb in [ ('conf_en', 'Configs enabled in {}:'.format(config_opts.get('DEFAULT', 'conf_dir'))), ('conf_dis', 'Configs disabled in {}:'.format(config_opts.get('DEFAULT', 'conf_dir'))), ('sites_en', 'Configs enabled in {}:'.format(config_opts.get('DEFAULT', 'sites_en'))), ('sites_dis', 'Configs disabled in {}:'.format(config_opts.get('DEFAULT', 'sites_dis'))), ('sites_avail', 'All confis available in {}:'.format(config_opts.get('DEFAULT', 'sites_dis')))]: if configs[key] == []: print(verb + '\n\t') else: print(verb) for conf in configs[key]: print('\t' + conf) def get_configs(): '''Returns a list of configuration files.''' cd = [os.path.basename(f).replace(conf_ext + '_disabled', '') for f in glob.glob(conf_dir + '*' + conf_ext + '_disabled') if os.path.isfile(f)] ce = [os.path.basename(f).replace(conf_ext, '') for f in glob.glob(conf_dir + '*' + conf_ext) if os.path.isfile(f)] se = [os.path.basename(f) for f in glob.glob(sites_en + '*') if os.path.isfile(f) or os.path.islink(f)] sd = [os.path.basename(f) for f in glob.glob(sites_dis + '*') if os.path.isfile(f) and os.path.basename(f) not in se] sa = [os.path.basename(f) for f in glob.glob(sites_dis + '*') if os.path.isfile(f)] return {'conf_dis': cd, 'conf_en': ce, 'sites_en': se, 'sites_dis': sd, 'sites_avail': sa} def reload_nginx(): '''Reload Nginx after configuration changes.''' child = subprocess.Popen( ['service', 'nginx', 'reload'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = child.communicate() if int(child.returncode) != 0: print('Error reloading nginx configs.') return False elif verbose: print('Nginx config reloaded successfully.') return True if __name__ == '__main__': main() debian/ngx-conf/README.rst0000664000000000000000000000541012705233614012401 0ustar Nginx Configuration Tool (ngx-conf) =================================== A tool to help manage nginx confuration files. Synopsis -------- ngx-conf [-h] (-e | -d | -x | -l) [-f] [-r] [-v] FILE [FILES] Description ----------- Ngx-conf is a relatively simple tool to help manage Nginx configuration files. It can be used to enable, disable, remove, and list configuration files. In the case of configuration files in conf.d/\*.conf, it will handle renaming files to an enabled/disabled state. In sites-{enabled,available}/\*, it will handle the creation and removal of symbolic links. **-h, --help** show a help message and exit **-e, --enable** enable a configuration files **-d, --disable** disable a configuration files **-x, --remove** remove a configuration files; will prompt without -f **-l, --list** list configuration files **-f, --force** force change, even if doing so will destroy data **-r, --reload** reload configuration after change **-v, --verbose** show verbose output; default is quiet unless errors **FILES** a list of configuration files to update Using --force: * In --remove will not prompt you to delete the file(s). * In --enable will ignore conflicts. * In --disable will ignore conflicts. * In --disable will also delete files from sites-enabled. Only one action (enable|disable|remove|list) can be performed at one time. Examples -------- ngx-conf -e site1 site2 site3 enable "site{1,2,3}" configurations ngx-conf -r -d site disable "site" configuration and reload nginx ngx-conf -f -r -x site1 site2 remove "site{1,2}" configurations without prompting and reload nginx Configuration Files ------------------- Three configuration files, if present, will be read. They will be read in the following order; the next read file will always override the previous. 1. /etc/nginx/ngx.cfg #. /etc/ngx.cfg #. ngx.cfg A sample configuration file with all options set to default:: [DEFAULT] base_dir = /etc/nginx/ conf_dir = conf.d/ sites_en = sites-enabled/ sites_dis = sites-available/ conf_ext = .conf verbose = no reload = no force = no Make sure that base_dir always has a trailing slash. Any arguments given to the command will override configuration options. Aliases ------- If you're interested in any sort of a2{dis,en}{conf,mod,site}, you can create some nice aliases. Examples: * a2ensite -- alias ngxensite='ngx-conf -e' * a2enconf -- alias ngxenconf='ngx-conf -e' * a2dissite -- alias ngxdissite='ngx-conf -d' * a2disconf -- alias ngxdisconf='ngx-conf -d' Bugs ---- If you experience bugs, the best way to report them is to the upstream bug tracker. This can be found at https://github.com/ngx/ngx-conf. Authors ------- The ngx-conf tool and manual page were written by Michael Lustfield . debian/ngx-conf/ngx-conf.10000664000000000000000000000634312705233614012521 0ustar .\" Title: ngx-conf .\" Author: Michael Lustfield .\" Date: 01/14/2015 .\" Manual: User Commands .\" .TH "NGX-CONF" "1" "01/14/2015" "ngx-conf" "User Commands" .\" disable hyphenation .NH .\" disable justification (adjust text to left margin only) .AD l .SH "NAME" ngx - a tool to help manage nginx confuration files .SH "SYNOPSIS" .B ngx-conf [-h] (-e | -d | -x | -l) [-f] [-r] [-v] FILE [FILES] .br .SH "DESCRIPTION" .PP Ngx-conf is a relatively simple tool to help manage Nginx configuration files. It can be used to enable, disable, remove, and list configuration files. In the case of configuration files in conf.d/*.conf, it will handle renaming files to an enabled/disabled state. In sites-{enabled,available}/*, it will handle the creation and removal of symbolic links. .SH "OPTIONS" .PP This program follows the usual command line syntax, with long options starting with two dashes (`\-'). A summary of options is included below. .TP .B \-h, \-\-help show a help message and exit .TP .B \-e, \-\-enable enable a configuration files .TP .B \-d, \-\-disable disable a configuration files .TP .B \-x, \-\-remove remove a configuration files; will prompt without -f .TP .B \-l, \-\-list list configuration files .TP .B \-f, \-\-force force change, even if doing so will destroy data .TP .B \-r, \-\-reload reload configuration after change .TP .B \-v, \-\-verbose show verbose output; default is quiet unless errors .B FILES a list of configuration files to update .PP Using --force: .IP In --remove will not prompt you to delete the file(s). .br In --enable will ignore conflicts. .br In --disable will ignore conflicts. .br In --disable will also delete files from sites-enabled. .PP Only one action (enable|disable|remove|list) can be performed at one time. .SH "EXAMPLES" .PP ngx-conf -e site1 site2 site3 enable "site{1,2,3}" configurations .br ngx-conf -r -d site disable "site" configuration and reload nginx .br ngx-conf -f -r -x site1 site2 remove "site{1,2}" configurations without prompting and reload nginx .SH "CONFIGURATION FILES" .PP Three configuration files, if present, will be read. They will be read in the following order; the next read file will always override the previous. .IP 1. /etc/nginx/ngx.cfg .br 2. /etc/ngx.cfg .br 3. ngx.cfg .PP A sample configuration file with all options set to default: .IP [DEFAULT] .br base_dir = /etc/nginx/ .br conf_dir = conf.d/ .br sites_en = sites-enabled/ .br sites_dis = sites-available/ .br conf_ext = .conf .br verbose = no .br reload = no .br force = no .PP Make sure that base_dir always has a trailing slash. .br Any arguments given to the command will override configuration options. .SH "ALIASES" .PP If you're interested in any sort of a2{dis,en}{conf,mod,site}, you can create some nice aliases. Examples: .TP .B a2ensite alias ngxensite='ngx-conf -e' .br .TP .B a2enconf alias ngxenconf='ngx-conf -e' .br .TP .B a2dissite alias ngxdissite='ngx-conf -d' .br .TP .B a2disconf alias ngxdisconf='ngx-conf -d' .SH "BUGS" .PP If you experience bugs, the best way to report them is to the upstream bug tracker. This can be found at https://github.com/ngx/ngx-conf. .SH "AUTHORS" .PP The ngx-conf tool and manual page were written by Michael Lustfield . debian/README.Packaging0000664000000000000000000000452712705233614011746 0ustar Debian Packaging ================ We use git-buildpackage for packaging. Our repository can be found at git.debian.org:/git/collab-maint/nginx.git. Workflow for Unstable ===================== We use the standard git-buildpackage workflow. Workflow for Experimental (not-active) ====================================== Now that nginx 1.6.0 is released there is no plan to package mainline 1.7 releases to experimental. The following guide is been kept as a reference. -------- Nginx mainline releases (1.5.x series) are been packaged for experimental, as they lack security support. The workflow we use is based on the assumption that packaging work happens on origin/master and experimental builds are a trivial patch away from that. The direct consequense of treating experimental as a patchset for origin/master is that the relevant branches are forced-pushed whenever we release a new 1.5.x version. In other words, **it is not safe to base your work on the experimental branch**. This is a brief description of our experimental branches and how we are using them. * experimental-base Force-pushed when origin/master changes. experimental-base tracks the changes needed for building the 1.5.x branch, such as new configure parameters, etc. On new 1.5.x releases, it is rebased on origin/master so it is always up-to-date with our latest packaging work. * experimental Force-pushed on every 1.5.x release. This branch points to the latest 1.5.x release. Before release this branch is reset to experimental-base, and then merged with the new upstream-1.5 branch. Finally all the release specific changes are commited (changelog entry etc) and the build is made. * upstream-1.5 Force-pushed on every 1.5.x release. Before a new 1.5.x release the branch is reset to origin/upstream. This is a technicallity so we can avoid resolving conflicts when a new 1.4.x release happens between two experimental releases. Older 1.5.x releases are not referenced by any branch, but they can be found by the relevant debian/* tag. 3rd party experimental workflow =============================== As we described, it is better not base you work on our forced-pushed experimental branch. A better approach would be to maintain a custom-build branch that is rebased to our latest experimental branch (basically git rebase --onto the relevant commits should work). debian/nginx-common.nginx.upstart0000664000000000000000000000062112705233614014351 0ustar description "nginx - small, powerful, scalable web/proxy server" start on filesystem and static-network-up stop on runlevel [016] expect fork respawn pre-start script [ -x /usr/sbin/nginx ] || { stop; exit 0; } /usr/sbin/nginx -q -t -g 'daemon on; master_process on;' || { stop; exit 0; } end script exec /usr/sbin/nginx -g 'daemon on; master_process on;' pre-stop exec /usr/sbin/nginx -s quit debian/nginx-core.install0000664000000000000000000000004612705233614012634 0ustar debian/build-core/objs/nginx usr/sbin debian/nginx-light.prerm0000664000000000000000000000050412705233614012471 0ustar #!/bin/sh set -e case "$1" in remove|remove-in-favour|deconfigure|deconfigure-in-favour) if [ -x /etc/init.d/nginx ]; then invoke-rc.d nginx stop || exit $? fi ;; upgrade|failed-upgrade) ;; *) echo "prerm called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 debian/nginx-common.dirs0000664000000000000000000000031112705233614012462 0ustar etc/nginx etc/nginx/sites-available etc/nginx/sites-enabled etc/nginx/conf.d etc/ufw/applications.d usr/share/nginx usr/share/vim/addons usr/share/vim/registry var/log/nginx var/lib/nginx var/www/html debian/nginx-core.postinst0000664000000000000000000000142012705233614013046 0ustar #!/bin/sh set -e case "$1" in abort-upgrade|abort-remove|abort-deconfigure|configure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then NGX_PID=`cat /run/nginx.pid` if kill -s USR2 $NGX_PID 2>/dev/null; then while [ ! -s /run/nginx.pid.oldbin ] || [ ! -s /run/nginx.pid ]; do cnt=`expr $cnt + 1` if [ $cnt -gt 10 ]; then kill -s KILL $NGX_PID invoke-rc.d nginx start exit 0 fi sleep 1 done NGX_OLD_PID=`cat /run/nginx.pid.oldbin` kill -s QUIT $NGX_OLD_PID fi else invoke-rc.d nginx start || exit $? fi fi #DEBHELPER# exit 0 debian/nginx-full.postinst0000664000000000000000000000142012705233614013060 0ustar #!/bin/sh set -e case "$1" in abort-upgrade|abort-remove|abort-deconfigure|configure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then NGX_PID=`cat /run/nginx.pid` if kill -s USR2 $NGX_PID 2>/dev/null; then while [ ! -s /run/nginx.pid.oldbin ] || [ ! -s /run/nginx.pid ]; do cnt=`expr $cnt + 1` if [ $cnt -gt 10 ]; then kill -s KILL $NGX_PID invoke-rc.d nginx start exit 0 fi sleep 1 done NGX_OLD_PID=`cat /run/nginx.pid.oldbin` kill -s QUIT $NGX_OLD_PID fi else invoke-rc.d nginx start || exit $? fi fi #DEBHELPER# exit 0 debian/nginx-common.nginx.init0000664000000000000000000001074312705233614013620 0ustar #!/bin/sh ### BEGIN INIT INFO # Provides: nginx # Required-Start: $local_fs $remote_fs $network $syslog $named # Required-Stop: $local_fs $remote_fs $network $syslog $named # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts the nginx web server # Description: starts nginx using start-stop-daemon ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/sbin/nginx NAME=nginx DESC=nginx # Include nginx defaults if available if [ -r /etc/default/nginx ]; then . /etc/default/nginx fi STOP_SCHEDULE="${STOP_SCHEDULE:-QUIT/5/TERM/5/KILL/5}" test -x $DAEMON || exit 0 . /lib/init/vars.sh . /lib/lsb/init-functions # Try to extract nginx pidfile PID=$(cat /etc/nginx/nginx.conf | grep -Ev '^\s*#' | awk 'BEGIN { RS="[;{}]" } { if ($1 == "pid") print $2 }' | head -n1) if [ -z "$PID" ]; then PID=/run/nginx.pid fi if [ -n "$ULIMIT" ]; then # Set ulimit if it is set in /etc/default/nginx ulimit $ULIMIT fi start_nginx() { # Start the daemon/service # # Returns: # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start --quiet --pidfile $PID --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start --quiet --pidfile $PID --exec $DAEMON -- \ $DAEMON_OPTS 2>/dev/null \ || return 2 } test_config() { # Test the nginx configuration $DAEMON -t $DAEMON_OPTS >/dev/null 2>&1 } stop_nginx() { # Stops the daemon/service # # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PID --name $NAME RETVAL="$?" sleep 1 return "$RETVAL" } reload_nginx() { # Function that sends a SIGHUP to the daemon/service start-stop-daemon --stop --signal HUP --quiet --pidfile $PID --name $NAME return 0 } rotate_logs() { # Rotate log files start-stop-daemon --stop --signal USR1 --quiet --pidfile $PID --name $NAME return 0 } upgrade_nginx() { # Online upgrade nginx executable # http://nginx.org/en/docs/control.html # # Return # 0 if nginx has been successfully upgraded # 1 if nginx is not running # 2 if the pid files were not created on time # 3 if the old master could not be killed if start-stop-daemon --stop --signal USR2 --quiet --pidfile $PID --name $NAME; then # Wait for both old and new master to write their pid file while [ ! -s "${PID}.oldbin" ] || [ ! -s "${PID}" ]; do cnt=`expr $cnt + 1` if [ $cnt -gt 10 ]; then return 2 fi sleep 1 done # Everything is ready, gracefully stop the old master if start-stop-daemon --stop --signal QUIT --quiet --pidfile "${PID}.oldbin" --name $NAME; then return 0 else return 3 fi else return 1 fi } case "$1" in start) log_daemon_msg "Starting $DESC" "$NAME" start_nginx case "$?" in 0|1) log_end_msg 0 ;; 2) log_end_msg 1 ;; esac ;; stop) log_daemon_msg "Stopping $DESC" "$NAME" stop_nginx case "$?" in 0|1) log_end_msg 0 ;; 2) log_end_msg 1 ;; esac ;; restart) log_daemon_msg "Restarting $DESC" "$NAME" # Check configuration before stopping nginx if ! test_config; then log_end_msg 1 # Configuration error exit $? fi stop_nginx case "$?" in 0|1) start_nginx case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; reload|force-reload) log_daemon_msg "Reloading $DESC configuration" "$NAME" # Check configuration before stopping nginx # # This is not entirely correct since the on-disk nginx binary # may differ from the in-memory one, but that's not common. # We prefer to check the configuration and return an error # to the administrator. if ! test_config; then log_end_msg 1 # Configuration error exit $? fi reload_nginx log_end_msg $? ;; configtest|testconfig) log_daemon_msg "Testing $DESC configuration" test_config log_end_msg $? ;; status) status_of_proc -p $PID "$DAEMON" "$NAME" && exit 0 || exit $? ;; upgrade) log_daemon_msg "Upgrading binary" "$NAME" upgrade_nginx log_end_msg $? ;; rotate) log_daemon_msg "Re-opening $DESC log files" "$NAME" rotate_logs log_end_msg $? ;; *) echo "Usage: $NAME {start|stop|restart|reload|force-reload|status|configtest|rotate|upgrade}" >&2 exit 3 ;; esac debian/nginx-common.README.Debian0000664000000000000000000000300612705233614013643 0ustar Noteworthy Changes Wheezy => Jessie =================================== * Disabled SSLv3 by default After POODLE we followed suit and disabled SSLv3 by default. * /var/log/nginx permissions /var/log/nginx/ is now not readable by default (www-data:adm 750), If you depend on that you can add a manual override with dpkg-statoverride. * New upgrade & rotate initscript commands You can now upgrade the nginx binary on the fly with /etc/init.d/nginx upgrade (Read more on http://nginx.org/en/docs/control.html#upgrade) * Synced configuration files are with upstream Unfortunately that might break existing configuration for some users, especially fastcgi scripts. /usr/share/doc/nginx-common/NEWS.Debian.gz contains some more information about the changes made. * Changed document root to /var/www/html The default document root has now changed to /var/www/html/. * Added a snippets directory A /etc/nginx/snippets has been added, it contains common configuration stangas. For now we ship a snakeoil.conf (self-signed ssl) and a simple fastcgi-php.conf. * Switched to graceful stop Both systemd and the initscript's stop function try to graceful stop nginx (SIGQUIT) before stopping it fast (SIGTERM). That allows nginx to serve connected clients before shutting down. * Dropped nginx-naxsi Packaging naxsi was not trivial and, unfortunately, none of the maintainers uses it. That's the reason nginx-naxsi was not in a good shape and we are not feeling comfortable to release and support it. debian/nginx-light.install0000664000000000000000000000004712705233614013014 0ustar debian/build-light/objs/nginx usr/sbin debian/nginx-light.dirs0000664000000000000000000000001112705233614012276 0ustar usr/sbin debian/help/0000775000000000000000000000000012705233614010123 5ustar debian/help/examples/0000775000000000000000000000000012705233614011741 5ustar debian/help/examples/wordpress0000664000000000000000000000472312705233614013722 0ustar ## # File: # wordpress # Description: # This file is meant to offer a basic guide to get a Wordpress site up and # running on Nginx. This file should be almost drop-in if the user is able # to understand the three lines that need to be changed. ## server { # This is the URI of your website. server_name domain.com; # This is the root of the Wordpress directory. root /var/www/wordpress; # In some cases a favicon does not exist but this is not something you # normally need to worry about. It's also a microscopic image and will # just clutter the logs. location = /favicon.ico { log_not_found off; access_log off; } # This is for the robots.txt file used by search engines. location = /robots.txt { # If you have one, you want to allow them access to it. allow all; # If you don't have one, you don't want to fill your logs with # not found errors. log_not_found off; access_log off; } # This location block protects against a known attack. It happens if # the attacker uploads a non-php file and attempts to run it as a # php file on the server. location ~ \..*/.*\.php$ { return 403; } # This is our primary location block. The try_files directive will # attempt to serve the data in the order listed. First try the exact # request (such as an image or text file). If it doesn't exist, see if # the directory exists. If not, then we move to the last options which # passes the request to /index.php with the requested query. location / { try_files $uri $uri/ /index.php?q=$uri&$args; } # If a PHP file is served, this block will handle the request. This block # works on the assumption you are using php-cgi listening on /tmp/phpcgi.socket. # Please see the php example (usr/share/doc/nginx/exmaples/php) for more # information about setting up PHP. # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; # Intercepting errors will cause PHP errors to appear in Nginx logs fastcgi_intercept_errors on; fastcgi_pass unix:/tmp/phpcgi.socket; } # As mentioned above, Nignx is king of static. If we're serving a static # file that ends with one of the following extensions, it is best to set # a very high expires time. This will generate fewer requests for the # file. These requests will be logged if found, but not if they don't # exist. location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; } } debian/help/examples/mail0000664000000000000000000000116712705233614012613 0ustar ## # File: # mail # Description: # Provides a basic example of a mail proxy. ## # All mail proxy configuration should be inside of the mail block. # Most settings here are pretty self explanatory. # See http://wiki.nginx.org/MailCoreModule mail { # See sample authentication script at: # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript # auth_http localhost/auth.php; # pop3_capabilities "TOP" "USER"; # imap_capabilities "IMAP4rev1" "UIDPLUS"; server { listen localhost:110; protocol pop3; proxy on; } server { listen localhost:143; protocol imap; proxy on; } } debian/help/examples/mailman0000664000000000000000000000356412705233614013312 0ustar ## # File: # mailman # Description: # This file explains how to install MailMan and offers a nearly drop-in # model if MailMan was installed from Debian/Ubuntu repositories. ## server { # This is the URI of your website. You can specify multiple sites to be # served by the same Drupal installation. server_name lists.DOMAIN.TLD; # This is the default MailMan root directory. root /usr/lib/cgi-bin; # If the request is exactly the server_name, then we need to redirect # the browser to the listinfo page. Notice the = for an exact match. location = / { rewrite ^ /mailman/listinfo permanent; } # Any requests need to be rewritten to /mailman/. # This happens only if no other location block matches. location / { rewrite ^ /mailman$uri; } # If /mailmain/ was part of the request, then we need to let python # handle the request. location /mailman/ { fastcgi_split_path_info (^/mailman/[^/]*)(.*)$; include fastcgi_params; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; # fcgiwrap was used to create this socket. # See /usr/share/doc/nginx-doc/fcgiwrap fastcgi_pass unix:/tmp/cgi.socket; } # If a request was made for an image, we need to change the directory # that is beeing looked at. Nothing else is needed because the images # are static content. location /images/mailman { alias /var/lib/mailman/icons; } # If a request for /pipermail was made, we are still only dealing with # static content. The archives are at a different location and we need # to point at it. Because these are public, there's no issue in letting # them be browsed; autoindex is turned on to allow browsing. location /pipermail { alias /var/lib/mailman/archives/public; autoindex on; } } debian/help/examples/virtual_hosts0000664000000000000000000001032612705233614014574 0ustar ## # File: # virtual_hosts # Description: # This file is meant to deliver a basic understanding of server blocks. ## ## # You should look at the following URL's in order to grasp a solid understanding # of Nginx configuration files in order to fully unleash the power of Nginx. # http://wiki.nginx.org/Pitfalls # http://wiki.nginx.org/Configuration ## ## # Every "virtual host" that you serve will need to be in its own server block. # # server { # ... # } # # After reading this file, you should understand the structure of server blocks # and be able to understand how to modify them to your needs. ## server { # The listen directive is only needed if this server block: # needs to listen for IPv6 # needs to listen on another port # If you need to listen for IPv6 then both of the following lines can # be included. # DO NOT listen for both SSL and non-SSL in the same server block. #listen 80; ## listen for ipv4; this line is default and implied #listen [::]:80 default ipv6only=on; ## listen for ipv6 # root specifies the document root for the requests root /usr/share/nginx/www; # index specifies the list of files (in order) to be tried in the event # no file is requested in the URI. index index.html index.htm; # Make site accessible from http://localhost/ server_name localhost; # Unless you run everything as a proxy, you will want to have a root # location block. This example controls how files are requested. location / { # First attempt to serve request as file, then as directory, # then fall back to index.html. /index.html would normally be # front end controller pattern for handling "clean url's" in # a CMS such as Drupal or Wordpress. try_files $uri $uri/ /index.html; } # This location block would server any requests for /doc as well # as anything below it. location /doc { # root changes the root directory for these requests root /usr/share; # autoindex on allows these request to display directory listings # if a directory was requested autoindex on; # We'll allow these requests for localhost allow 127.0.0.1; # Anyone outside is forbidden deny all; } # This location block would serve any requests for /images as well # as anything below it. location /images { # This is the same as /doc except we don't allow indexes root /usr/share; autoindex off; allow 127.0.0.1; deny all; } # This will serve the file 404.html in the event the request is not found. error_page 404 /404.html; # redirect server error pages to the static page /50x.html # This will hit if the server generates a 500, 502, 503, or 504 status code error_page 500 502 503 504 /50x.html; # This location block isn't actually needed because our root for the # server block is the same directory. However, this could be used to # have a central directory for all error html files. location = /50x.html { root /usr/share/nginx/www; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # If you're going to proxy to Apache, then just push the whole # request to it. You'll generally have better performance with # a dedicated php listener (fastcgi: php-cgi, php-fpm). #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # This is used for passing to php-cgi and php-fpm. # For more information see /usr/share/doc/nginx/examples/php location ~ \.php$ { # This is where the php socket is listening. fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; } # deny access to .htaccess, .htpasswd, and .htgroup files location ~ /\.ht { deny all; } } # another virtual host using mix of IP-, name-, and port-based configuration server { listen 8000; listen somename:8080; server_name somename alias another.alias; root html; index index.html index.htm; location / { try_files $uri $uri/ /index.html; } } # HTTPS server server { listen 443; server_name localhost; root html; index index.html index.htm; ssl on; ssl_certificate cert.pem; ssl_certificate_key cert.key; ssl_session_timeout 5m; ssl_protocols SSLv3 TLSv1; ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; ssl_prefer_server_ciphers on; location / { try_files $uri $uri/ /index.html; } } debian/help/examples/nginx.conf0000664000000000000000000000146212705233614013736 0ustar ## # File: # nginx.conf # Description: # Provides a very basic description of the use of nginx.conf. ## # For more options with more detailed descriptions: # See http://wiki.nginx.org/CoreModule # Sets user/group of worker processes. If group is not specified, group is assumed # to be the same as user. Syntax: user user [group] user www-data; # nginx has the ability to use more than one worker process worker_processes 4; # The pid-file. It can be used for the kill-command to send signals to nginx. # Example: To reload the config: kill -HUP `cat /var/log/nginx.pid` pid /var/run/nginx.pid; # See http://wiki.nginx.org/HttpEventsModule events { worker_connections 1024; # multi_accept on; } # See /usr/share/doc/nginx/examples/http http { } # See /usr/share/doc/nginx/examples/mail mail { } debian/help/examples/nginx_modsite0000775000000000000000000001102112705233614014531 0ustar #!/bin/bash ## # File: # nginx_modsite # Description: # Provides a basic script to automate enabling and disabling websites found # in the default configuration directories: # /etc/nginx/sites-available and /etc/nginx/sites-enabled # For easy access to this script, copy it into the directory: # /usr/local/sbin # Run this script without any arguments or with -h or --help to see a basic # help dialog displaying all options. ## # Copyright (C) 2010 Michael Lustfield # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. ## # Default Settings ## NGINX_CONF_FILE="$(awk -F= -v RS=' ' '/conf-path/ {print $2}' <<< $(nginx -V 2>&1))" NGINX_CONF_DIR="${NGINX_CONF_FILE%/*}" NGINX_SITES_AVAILABLE="$NGINX_CONF_DIR/sites-available" NGINX_SITES_ENABLED="$NGINX_CONF_DIR/sites-enabled" SELECTED_SITE="$2" ## # Script Functions ## ngx_enable_site() { [[ ! "$SELECTED_SITE" ]] && ngx_select_site "not_enabled" [[ ! -e "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" ]] && ngx_error "Site does not appear to exist." [[ -e "$NGINX_SITES_ENABLED/$SELECTED_SITE" ]] && ngx_error "Site appears to already be enabled" ln -sf "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" -T "$NGINX_SITES_ENABLED/$SELECTED_SITE" ngx_reload } ngx_disable_site() { [[ ! "$SELECTED_SITE" ]] && ngx_select_site "is_enabled" [[ ! -e "$NGINX_SITES_AVAILABLE/$SELECTED_SITE" ]] && ngx_error "Site does not appear to be \'available\'. - Not Removing" [[ ! -e "$NGINX_SITES_ENABLED/$SELECTED_SITE" ]] && ngx_error "Site does not appear to be enabled." rm -f "$NGINX_SITES_ENABLED/$SELECTED_SITE" ngx_reload } ngx_list_site() { echo "Available sites:" ngx_sites "available" echo "Enabled Sites" ngx_sites "enabled" } ## # Helper Functions ## ngx_select_site() { sites_avail=($NGINX_SITES_AVAILABLE/*) sa="${sites_avail[@]##*/}" sites_en=($NGINX_SITES_ENABLED/*) se="${sites_en[@]##*/}" case "$1" in not_enabled) sites=$(comm -13 <(printf "%s\n" $se) <(printf "%s\n" $sa));; is_enabled) sites=$(comm -12 <(printf "%s\n" $se) <(printf "%s\n" $sa));; esac ngx_prompt "$sites" } ngx_prompt() { sites=($1) i=0 echo "SELECT A WEBSITE:" for site in ${sites[@]}; do echo -e "$i:\t${sites[$i]}" ((i++)) done read -p "Enter number for website: " i SELECTED_SITE="${sites[$i]}" } ngx_sites() { case "$1" in available) dir="$NGINX_SITES_AVAILABLE";; enabled) dir="$NGINX_SITES_ENABLED";; esac for file in $dir/*; do echo -e "\t${file#*$dir/}" done } ngx_reload() { read -p "Would you like to reload the Nginx configuration now? (Y/n) " reload [[ "$reload" != "n" && "$reload" != "N" ]] && invoke-rc.d nginx reload } ngx_error() { echo -e "${0##*/}: ERROR: $1" [[ "$2" ]] && ngx_help exit 1 } ngx_help() { echo "Usage: ${0##*/} [options]" echo "Options:" echo -e "\t<-e|--enable> \tEnable site" echo -e "\t<-d|--disable> \tDisable site" echo -e "\t<-l|--list>\t\tList sites" echo -e "\t<-h|--help>\t\tDisplay help" echo -e "\n\tIf is left out a selection of options will be presented." echo -e "\tIt is assumed you are using the default sites-enabled and" echo -e "\tsites-disabled located at $NGINX_CONF_DIR." } ## # Core Piece ## case "$1" in -e|--enable) ngx_enable_site;; -d|--disable) ngx_disable_site;; -l|--list) ngx_list_site;; -h|--help) ngx_help;; *) ngx_error "No Options Selected" 1; ngx_help;; esac debian/help/examples/drupal0000664000000000000000000001011712705233614013153 0ustar ## # File: # drupal # Description: # This file is meant to offer a very detailed set of instructions and best # practices for deploying a Drupal website with Nginx. This file should be # almost drop-in if the user is able to understand the three lines that # need to be changed. ## server { # This is the URI of your website. You can specify multiple sites to be # served by the same Drupal installation. server_name domain.com www.domain.com .example.net; # This is the root of the Drupal directory. # Note that Drupal 6, Drupal 7, and Pressflow are interchangeable root /var/www/drupal6; # In some cases a favicon does not exist but this is not something you # normally need to worry about. It's also a microscopic image and will # just clutter the logs. location = /favicon.ico { log_not_found off; access_log off; } # This is for the robots.txt file used by search engines. location = /robots.txt { # If you have one, you want to allow them access to it. allow all; # If you don't have one, you don't want to fill your logs with # not found errors. log_not_found off; access_log off; } # This matters if you use drush because drush copies backups of modules # to this directory. In the event personal information wound up in the # module, you want to know outside users can't access it. location = /backup { deny all; } # Very rarely should these ever be accessed outside of your lan # The above location for robots.txt is an exact match and will override # this location block. location ~* \.(txt|log)$ { allow 192.168.0.0/16; deny all; } # This location block protects against a known attack. It happens if # the attacker uploads a non-php file and attempts to run it as a # php file on the server. location ~ \..*/.*\.php$ { return 403; } # This is our primary location block. The try_files directive will # attempt to serve the data in the order listed. First try the exact # request (such as an image or text file). If it doesn't exist, see if # the directory exists. If not, then we move to the rewrite which is # used for the front-end controller pattern. location / { try_files $uri $uri/ @rewrite; } # This will rewrite our request from domain.com/node/1/ to domain.com/index.php?q=node/1 # This could be done in try_files without a rewrite however, the GlobalRedirect # module enforces no slash (/) at the end of URL's. This rewrite removes that # so no infinite redirect loop is reached. location @rewrite { rewrite ^/(.*)$ /index.php?q=$1; } # If a PHP file is served, this block will handle the request. This block # works on the assumption you are using php-cgi listening on /tmp/phpcgi.socket. # Please see the php example (usr/share/doc/nginx/exmaples/php) for more # information about setting up PHP. # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; # Intercepting errors will cause PHP errors to appear in Nginx logs fastcgi_intercept_errors on; fastcgi_pass unix:/tmp/phpcgi.socket; } # The ImageCache module builds an image 'on the fly' which means that # if it doesn't exist, it needs to be created. Nginx is king of static # so there's no point in letting PHP decide if it needs to be servered # from an existing file. # If the image can't be served directly, it's assumed that it doesn't # exist and is passed off to PHP via our previous rewrite to let PHP # create and serve the image. # Notice that try_files does not have $uri/ in it. This is because an # image should never be a directory. So there's no point in wasting a # stat to serve it that way. location ~ ^/sites/.*/files/imagecache/ { try_files $uri @rewrite; } # As mentioned above, Nignx is king of static. If we're serving a static # file that ends with one of the following extensions, it is best to set # a very high expires time. This will generate fewer requests for the # file. These requests will be logged if found, but not if they don't # exist. location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; } } debian/help/examples/http0000664000000000000000000000226012705233614012643 0ustar ## # File: # http # Description: # This file is meant to deliver a basic understanding of the http block. ## # All web configuration should be inside of the http block. # Most settings here are pretty self explanatory. # See http://wiki.nginx.org/HttpCoreModule for details. http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## # Virtual Host Configs # These lines will include: # any files in /etc/nginx/sites-enabled/ # and any in /etc/nginx/conf.d/ ending with .conf ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } debian/help/docs/0000775000000000000000000000000012705233614011053 5ustar debian/help/docs/upstream0000664000000000000000000000252612705233614012643 0ustar ## # File: # upstream # Description: # This file describes how to use upstream blocks. ## An upstream block allows you to set a list of upstream locations for both proxy_pass and fastcgi_pass directives. Examples of upstream blocks: # PHP listening on the same server upstream php { # ip_hash ensures the same backend is used for client reconnects. ip_hash; # This assumes we have multiple PHP listeners on different known ports. server 127.0.0.1:9000; server 127.0.0.1:9001; server 127.0.0.1:9002; server 127.0.0.1:9003; # In addition to listening on ports, we can listen to unix sockets. server unix:/tmp/php-cgi.socket; } # Multiple backend Apache instances on separate servers upstream apache { # Adding a weight alters the chance the upstream server will be used. server apache1.domain.com weight 5; server apache2.domain.com; server apache3.domain.com; # Adding 'down' keeps the upstream from being used. Useful for downtime management. server apache4.domain.com down; server apache5.domain.com; } Using an upstream location: # Passing PHP to upstream location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; fastcgi_pass php; } # Passing all requests for /cgi-bin/* to Apache upstreams. location /cgi-bin { proxy_pass apache; } For more information see http://wiki.nginx.org/HttpUpstreamModule debian/help/docs/fcgiwrap0000664000000000000000000000054712705233614012606 0ustar ## # File: # fcgiwrap # Description: # The fcgiwrap tool allows a user to quickly and painlessly setup a socket # to handle CGI requests. This is useful for Python, Perl, etc. ## The easy way: apt-get install fcgiwrap The less-easy way: If your distribution does not provide it, the Nginx wiki describes the steps. http://wiki.nginx.org/Fcgiwrap debian/help/docs/php0000664000000000000000000000717412705233614011576 0ustar ## # File: # php # Description: # This file is meant to help users get a basic understanding of a PHP stack # with Nginx as the web server. ## # Note: This is not a configuration sample and comment lines will be userd differently. == PHP Options == There are a number of options that can be used to provide PHP. The two most common methods are php-cgi and php-fpm. The php-fpm option is relatively new and is not yet a standard option. This package is stable however and is moving toward being a standard option in distribution repositories. == PHP-FPM == The php-fpm option is considerably harder to debug. However, the hardest issues to debug should be solved by including that fastcgi_params file provided by this package. It should at a minimum remove all silent errors. # sudo apt-get install php5-fpm If you do not have php5-fpm available, you will want to add the repository for the package. https://launchpad.net/~nginx/+archive/php5 In php5-fpm, you will want to edit the php pool. Edit /etc/php5/fpm/pool.d/www.conf The listen directive is the most important piece in this file. It is suggested to listen to a local unix socket. This listen directive will be used in your nginx configuration. Example: listen = /tmp/phpfpm.socket The rest of this file can be tweaked to your liking. == PHP-CGI == The simplest and easiest method to run PHP is to use php-cgi. It does not offer the ability to monitor and restart processes that hang or die however. # sudo apt-get install php5-cgi To make php5-cgio work, you will need to create an init script. ===== FILE: /etc/init.d/phpcgi ===== #!/bin/bash # ### BEGIN INIT INFO # Provides: php-fcgi # Required-Start: $local_fs $remote_fs $network $syslog # Required-Stop: $local_fs $remote_fs $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: starts php-cgi processes # Description: starts php-cgi using start-stop-daemon for each user ### END INIT INFO # Number of PHP processes to be able to handle connections. CHILD=10 # Maximum number of requests each child should handle before being regenerated MAX_REQS=750 start() { start-stop-daemon --quiet --start --background --chuid "www-data" \ --exec /usr/bin/env \ -- - USER="www-data" \ PATH=/usr/bin PHP_FCGI_CHILDREN=$CHILD PHP_FCGI_MAX_REQUESTS=$MAX_REQS \ php-cgi -b /tmp/phpcgi.socket & } stop() { killall -w php-cgi rm /tmp/phpcgi.socket sync sleep 1 } case "$1" in start) start;; stop) stop;; restart) stop; start;; *) echo "Usage: php-fastcgi {start|stop|restart} [user]"; exit 1;; esac ===== END FILE ===== # Make file executable chmod +x /etc/init.d/phpcgi # Add file to startup update-rc.d phpcgi defaults == Using PHP in Nginx == In order to use the sockets you created (/tmp/phpfpm.socket or /tmp/phpcgi.socket) you will need to add a php block to your Nignx configuration. # This block adds a little security. # See /usr/share/doc/nginx/examples/drupal for context location ~ \..*/.*\.php$ { return 403; } # This is basic PHP block that can be used to handle all PHP requests. # See /usr/share/doc/nginx/examples/drupal for context location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; # Intercepting errors will cause PHP errors to appear in Nginx logs fastcgi_intercept_errors on; fastcgi_pass unix:/tmp/phpcgi.socket; } # The above example will use php5-cgi which is bound to /tmp/phpcgi.socket. # If you choose to use php5-fpm the example above will bind to /tmp/phpcgi.socket # instead and this should be used for fastcgi_pass instead. debian/help/docs/support-irc0000664000000000000000000000144012705233614013264 0ustar ## # File: # support-irc # Description: # This file explains how to get support on IRC. ## Nginx has a moderately active IRC channel on Freenode. You can get there by: * Client Using an IRC Client and pointing it to: #nginx on irc.freenode.net * Browser Opening a web browser and pointing it to: http://webchat.freenode.net?channels=nginx Common sense is expected to be followed: * Code of Conduct http://www.ubuntu.com/community/conduct * IRC Etiquette http://www.ircbeginner.com/ircinfo/etiquette.html * Patience If somebody doesn't answer you right away, then wait. Even active IRC users have to run off sometimes. If you need more help with IRC The Linux Documentation Project has more information: http://tldp.org/HOWTO/IRC/beginners.html debian/patches/0000775000000000000000000000000012705233614010622 5ustar debian/patches/ubuntu-branding.patch0000664000000000000000000000105412705460132014744 0ustar Description: Add Ubuntu token to NGINX_VER Author: Adam Conrad Forwarded: not-needed Last-Update: 2016-04-05 Index: b/src/core/nginx.h =================================================================== --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -11,7 +11,7 @@ #define nginx_version 1009015 #define NGINX_VERSION "1.9.15" -#define NGINX_VER "nginx/" NGINX_VERSION +#define NGINX_VER "nginx/" NGINX_VERSION " (Ubuntu)" #ifdef NGX_BUILD #define NGINX_VER_BUILD NGINX_VER " (" NGX_BUILD ")" debian/patches/series0000664000000000000000000000006512705233614012040 0ustar perl-use-dpkg-buildflags.patch ubuntu-branding.patch debian/patches/perl-use-dpkg-buildflags.patch0000664000000000000000000000145112705233614016435 0ustar Description: Use linker flags from environment for perl (dpkg-buildflags). Necessary for hardening flags. Author: Christos Trochalakis Index: b/src/http/modules/perl/Makefile.PL =================================================================== --- a/src/http/modules/perl/Makefile.PL +++ b/src/http/modules/perl/Makefile.PL @@ -3,6 +3,7 @@ # Copyright (C) Nginx, Inc. use 5.006001; +use Config; use ExtUtils::MakeMaker; WriteMakefile( @@ -14,6 +15,9 @@ AUTHOR => 'Igor Sysoev', CCFLAGS => "$ENV{NGX_PM_CFLAGS}", + # Pass link hardening flags + # $Config{lddlflags} is the default + LDDLFLAGS => "$Config{lddlflags} $ENV{DEBIAN_NGINX_PERL_LDFLAGS}", OPTIMIZE => '-O', INC => join(" ", map { debian/copyright0000664000000000000000000002070112705233614011126 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: nginx Source: http://nginx.org/en/download.html Files: * Copyright: 2002-2014 Igor Sysoev 2011-2014 Nginx, Inc. Maxim Dounin Valentin V. Bartenev Roman Arutyunyan Ruslan Ermilov License: BSD-2-clause Files: src/core/ngx_murmurhash.c Copyright: Copyright (C) Austin Appleby License: BSD-2-clause Files: src/http/modules/ngx_http_scgi_module.c src/http/modules/ngx_http_uwsgi_module.c Copyright: Copyright (C) Igor Sysoev Copyright (C) Nginx, Inc. 2009-2010 Unbit S.a.s. 2008 Manlio Perillo (manlio.perillo@gmail.com) License: BSD-2-clause Files: contrib/geo2nginx.pl Copyright: 2005, Andrei Nigmatulin License: BSD-2-clause Files: debian/* Copyright: 2007-2009, Fabio Tranchitella 2008, Jose Parrella 2009-2014, Kartik Mistry 2010-2014, Michael Lustfield 2011 Dmitry E. Oboukhov 2011-2013, Cyril Lavier 2013-2014, Christos Trochalakis License: BSD-2-clause Files: debian/modules/headers-more-nginx-module/* Copyright: Copyright (c) 2009-2014, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. Copyright (c) 2010-2013, Bernd Dorn Copyright (c) Igor Sysoev License: BSD-2-clause Files: debian/modules/nginx-development-kit/* Copyright: Marcus Clyne License: BSD-3-clause Files: debian/modules/nginx-development-kit/src/hash/md5.h debian/modules/nginx-development-kit/src/hash/sha.h Copyright: Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) License: BSD-4-clause Files: debian/modules/nginx-auth-pam/* Copyright: 2008-2013, Sergio Talens Oliag License: BSD-2-clause Files: debian/modules/nginx-echo/* Copyright: Copyright (c) 2009-2014, Yichun "agentzh" Zhang License: BSD-2-clause Files: debian/modules/nginx-lua/* Copyright: Copyright (C) 2009-2014, by Xiaozhe Wang (chaoslawful) . Copyright (C) 2009-2014, by Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. License: BSD-2-clause Files: debian/modules/nginx-upstream-fair/* Copyright: Copyright (c) 2007 Grzegorz Nosek Igor Sysoev License: BSD-2-clause Files: debian/modules/nginx-http-push/* Copyright: Copyright (c) 2009 Leo Ponomarev License: Expat Files: debian/modules/nginx-upload-progress/* Copyright: Brice Figureau 2002-2007, Igor Sysoev License: BSD-2-clause Files: debian/modules/nginx-cache-purge/* Copyright: 2009-2012, FRiCKLE , 2009-2012, Piotr Sikora License: BSD-2-clause Files: debian/modules/nginx-dav-ext-module/* Copyright: Arutyunyan Roman License: BSD-2-clause Files: debian/modules/ngx-fancyindex/* Copyright: Copyright (c) Adrian Perez License: BSD-2-clause Files: debian/modules/ngx_http_substitutions_filter_module/* Copyright: Copyright (C) 2014 by Weibin Yao License: BSD-2-clause License: BSD-2-clause All rights reserved. . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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. License: BSD-3-clause All rights reserved. . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. . THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. License: BSD-4-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 4. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. . THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. License: Expat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. debian/vim/0000775000000000000000000000000012705233614007766 5ustar debian/vim/nginx.yaml0000664000000000000000000000023412705233614011774 0ustar addon: nginx description: "allow syntax highlighting for Nginx configuration files" files: - ftdetect/nginx.vim - indent/nginx.vim - syntax/nginx.vim debian/changelog0000664000000000000000000025206412705460163011057 0ustar nginx (1.9.15-0ubuntu1) xenial-proposed; urgency=medium * New upstream release (1.9.15) - full changelog available at upstream website - http://nginx.org/en/CHANGES (LP: #1572223) * All Ubuntu specific changes from 1.1.14-0ubuntu1, except noted below, remain included in this upload. * Remaining changes: * debian/control: Re-add libluajit-5.1-dev build-dependency, as it will only affect nginx-extras which is in Universe. This reduces the merge delta between Ubuntu and Debian slightly, as well. (LP: #1571444) * debian/patches/ubuntu-branding.patch: Refresh Ubuntu Branding patch. -- Thomas Ward Mon, 18 Apr 2016 15:39:08 -0400 nginx (1.9.14-0ubuntu1) xenial-proposed; urgency=medium * New upstream release (1.9.14) - full changelog available at upstream website - htp://nginx.org/en/CHANGES (LP: #1566392) * All Ubuntu specific changes from 1.9.13-0ubuntu1, except noted below, remain included in this upload. * Remaining changes: * Enable HTTP/2 module for nginx-full, nginx-extras, and nginx-core (LP: #1565043) - debian/rules: Enable HTTP/2 module building in flavor rules - debian/control: Add HTTP/2 module to package descriptions. * debian/patches/ubuntu-branding.patch: Refresh Ubuntu Branding patch. -- Thomas Ward Fri, 01 Apr 2016 14:23:47 -0400 nginx (1.9.13-0ubuntu1) xenial-proposed; urgency=medium * New upstream release (1.9.13) - full changelog available at upstream website - http://nginx.org/en/CHANGES (LP: #1563393) * All Ubuntu specific changes from 1.9.12-0ubuntu1 remain included in this upload. * debian/patches/ubuntu-branding.patch: Refresh Ubuntu Branding patch. -- Thomas Ward Tue, 29 Mar 2016 18:47:36 -0400 nginx (1.9.12-0ubuntu1) xenial; urgency=medium * New upstream release (1.9.12) - full changelog available at upstream website - http://nginx.org/en/CHANGES (LP: #1549347) * All Ubuntu specific changes from 1.9.11-0ubuntu1 and -0ubuntu2 remain included in this upload. -- Thomas Ward Wed, 24 Feb 2016 10:26:31 -0500 nginx (1.9.11-0ubuntu2) xenial; urgency=medium * This is a bug-fix only upload and does not include any new changes to features. * debian/conf/sites-available/default: Modify PHP 'default example' settings to account for php5 being replaced with php7.0 in Xenial. Also adapt the UNIX socket path for php7.0-fpm to be the one used by default in Xenial. (LP: #1547642) -- Thomas Ward Fri, 19 Feb 2016 14:13:28 -0500 nginx (1.9.11-0ubuntu1) xenial; urgency=low * New upstream release (1.9.11) - see http://nginx.org/en/CHANGES for full changelog. * Ubuntu-specific changes from the 1.9.10 merge remain included here. * Additional changes: - debian/modules/nginx-lua: Apply upstream patch to fix FTBFS issue -- Thomas Ward Tue, 09 Feb 2016 10:33:14 -0500 nginx (1.9.10-1ubuntu1) xenial; urgency=low * Merge from Debian unstable. Remaining changes: (LP: #1538677) - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed) - d/{control,rules,nginx-core.*}: add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. - debian/tests/control: add nginx-core test. - debian/control: - drop luajit from Build-Depends as it is in universe. - Remove HTTP/2 references in package descriptions, per Ubuntu Security Team mandate to disable HTTP/2 support. - debian/rules: - Disable HTTP/2 module support in all flavors, per Ubuntu Security Team mandate. - debian/apport/source_nginx.py: Add apport hooks for additional bug information gathering. - debian/nginx-common.install: Add install rule for apport hooks. * Additional bugs fixed by this merge: - nginx-common should not depend on python (LP: #1480513) -- Thomas Ward Tue, 27 Jan 2016 12:52:00 -0500 nginx (1.9.10-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release (1.9.10) (Closes: #812806) * debian/control: + Drop python dependency from nginx-common. (Closes: #808699) -- Christos Trochalakis Tue, 26 Jan 2016 20:12:06 +0200 nginx (1.9.10-0ubuntu1) xenial; urgency=medium * New upstream release. * debian/patches/ubuntu-branding.patch: Refreshed Ubuntu Branding patch * Security content of this upload addresses the following vulnerabilities and CVE-numbered Security issues: (LP: #1538165) - Invalid pointer dereference might occur during DNS server response processing, allowing an attacker who is able to forge UDP packets from the DNS server to cause worker process crash (CVE-2016-0742). - Use-after-free condition might occur during CNAME response processing. This problem allows an attacker who is able to trigger name resolution to cause worker process crash, or might have potential other impact (CVE-2016-0746). - CNAME resolution was insufficiently limited, allowing an attacker who is able to trigger arbitrary name resolution to cause excessive resource consumption in worker processes (CVE-2016-0747). -- Thomas Ward Tue, 26 Jan 2016 14:53:01 -0500 nginx (1.9.9-1ubuntu1) xenial; urgency=low * Merge from Debian unstable. Remaining changes: (LP: #1534208) - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed) - d/{control,rules,nginx-core.*}: add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. - debian/tests/control: add nginx-core test. - debian/control: - drop luajit from Build-Depends as it is in universe. - Update nginx-core description to match nginx-full description of the standard and optional HTTP modules that are enabled. - Remove HTTP/2 references in package descriptions, per Ubuntu Security Team mandate to disable HTTP/2 support. - debian/rules: - Update nginx-core configure flags to match nginx-full config flags, due to refreshing the nginx-core 'enabled modules' to match the nginx-full modules (minus third-party modules) - Disable HTTP/2 module support in all flavors, per Ubuntu Security Team mandate. - debian/apport/source_nginx.py: Add apport hooks for additional bug information gathering. - debian/nginx-common.install: Add install rule for apport hooks. * debian/control: Remove HTTP/2 reference in nginx-extras description, which was missed previously due to accidental oversight. (LP: #1534368) -- Thomas Ward Thu, 14 Jan 2016 18:42:00 -0500 nginx (1.9.9-1) unstable; urgency=medium [ Michael Lustfield ] * debian/nginx-common.nginx.logrotate: + Switching logrotate to 14 days. (Closes: #805322) [ Christos Trochalakis ] * New upstream release (1.9.9). * debian/modules/nginx-lua: + Update nginx-lua to v0.10.0. -- Christos Trochalakis Thu, 14 Jan 2016 10:40:35 +0200 nginx (1.9.9-0ubuntu1) xenial; urgency=medium * New upstream release. * debian/patches/ubuntu-branding.patch: Refreshed Ubuntu Branding patch -- Thomas Ward Sun, 03 Jan 2016 12:49:21 -0500 nginx (1.9.6-2ubuntu2) xenial; urgency=medium * Rebuild for Perl 5.22.1. -- Colin Watson Fri, 18 Dec 2015 12:53:05 +0000 nginx (1.9.6-2ubuntu1) xenial; urgency=medium * Merge from Debian unstable. Remaining changes: (LP: #1510096) - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed) - d/{control,rules,nginx-core.*}: add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. - debian/tests/control: add nginx-core test. - debian/control: drop luajit from Build-Depends as it is in universe. - debian/apport/source_nginx.py: Add apport hooks for additional bug information gathering. - debian/nginx-common.install: Add install rule for apport hooks. * Additional changes: * debian/rules: - Update nginx-core configure flags to match nginx-full config flags, due to refreshing the nginx-core 'enabled modules' to match the nginx-full modules (minus third-party modules) - Disable HTTP/2 module support in all flavors, per Ubuntu Security Team mandate. * debian/control: - Update nginx-core description to match nginx-full description of the standard and optional HTTP modules that are enabled. - Remove HTTP/2 references in package descriptions, per Ubuntu Security Team mandate to disable HTTP/2 support. -- Thomas Ward Mon, 14 Dec 2015 10:34:42 -0500 nginx (1.9.6-2) unstable; urgency=medium [ Christos Trochalakis] * debian/modules/nginx-lua: + Update nginx-lua to v0.9.19 fixing HTTP/2 compatibility. -- Christos Trochalakis Fri, 13 Nov 2015 16:08:01 +0200 nginx (1.9.6-1) unstable; urgency=medium [ Christos Trochalakis] * New upstream release. * Enable http2 module in nginx-full & nginx-extras -- Christos Trochalakis Tue, 03 Nov 2015 08:59:21 +0200 nginx (1.9.4-1) unstable; urgency=medium [ Christos Trochalakis] * New upstream release. * debian/copyright: + Fix licence order. -- Christos Trochalakis Mon, 24 Aug 2015 16:23:20 +0300 nginx (1.9.3-1ubuntu1) wily; urgency=medium * Merge from Debian. Remaining changes: (LP: #1476811) - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed) - d/{control,rules,nginx-core.*}: add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. - debian/tests/control: add nginx-core test. - debian/control: drop luajit from Build-Depends as it is in universe. - debian/apport/source_nginx.py: Add apport hooks for additional bug information gathering. - debian/nginx-common.install: Add install rule for apport hooks. -- Thomas Ward Wed, 22 Jul 2015 11:39:44 -0400 nginx (1.9.3-1) unstable; urgency=medium [ Christos Trochalakis] * New upstream Release. (Closes: #789924) * debian/control: + Remove XS-Testsuite header, it is now automatically added when `debian/tests/control` is present. * debian/modules/nginx-lua: + Update nginx-lua to v0.9.16 and drop our backported patches. * debian/conf/*: + Add REQUEST_SCHEME to fcgi, wsgi and scgi configs (sync with upstream). -- Christos Trochalakis Tue, 14 Jul 2015 20:24:52 +0300 nginx (1.9.2-1) unstable; urgency=medium [ Michael Lustfield ] * debian/nginx-common.nginx.init: + Init script now returns the proper exit status. (Closes: #788573) + Cleaned up the init script to have consistent naming/structure. [ Christos Trochalakis ] * New upstream Release. * debian/rules: + Add stream module to nginx-full & nginx-extras. + Add thread pool support to nginx-full & nginx-extras. * debian/modules/nginx-lua: + Backport upstream's 9531e5e7 fixing build failure when thread pool support is enabled. -- Christos Trochalakis Mon, 22 Jun 2015 10:16:19 +0300 nginx (1.9.1-1) unstable; urgency=medium [ Michael Lustfield ] * debian/conf/nginx.conf: + Switch worker_processes to auto. (Closes: #781711) * debian/conf/sites-available/default: + Add comment about disabling gzip in HTTPS. (Closes: #773332) + Add comment about checking ssl_ciphers. (Closes: #765782) * debian/modules/*: + Updated nginx-auth-pam 1.3 -> 1.4. (Closes: #777120) + Updated nginx-echo v0.56 -> v0.57. + Updated nginx-lua v0.9.13 -> v0.9.15. + Updated nginx-cache-purge 2.1 -> 2.3. + Updated ngx-fancyindex v0.3.4 -> v0.3.5. * debian/nginx-common.NEWS: + Document potential issues with newer versions on i386. * debian/nginx-common.{dirs,install}, debian/vim/*: + Installing vim syntax highlighting from package. (Closes: #771609) Thanks Emmanuel Bouthenot for building this patch. * debian/nginx-common.nginx.upstart: + Created file to support upstart jobs. (Closes: #745483) Thanks Cameron Norman for building this file. * debian/rules: + Add hardening flags with dpkg-buildflags. (Closes: #747025, #781703) Thanks Thomas Ward. + Supply custom DEB_BUILD_MAINT_OPTIONS for debian_ldflags generation. Thanks Thomas Ward. + Added back missing module gunzip. (Closes: #782065) Thanks Peter Wu for the initial patch. * debian/modules/nginx-lua/*: + Updated module version. (Closes: #762494) * debian/ngx-conf/* + Added configuration utility, not shipped yet. (Closes: #652108) * debian/nginx-common.manpages: + Replaced man page with upstream maintained version. (Closes: #781345) * debian/nginx-common.install: + Changed debian/index.html -> html/index.html. This installs the package maintained version of this file as opposed to our out of date version. [ Christos Trochalakis ] * New upstream release. Switching to mainline version. (Closes: #777677) * debian/nginx-common.manpages: + Build & ship manpages with binary packages. * debian/rules: + Adjust configure flags for limit_zone module (renamed to limit_conn). * debian/modules/nginx-lua: + Backport upstream's f4e1311 fixing build failure with mainline nginx. * debian/control: + Depend on libgd-dev now that jessie is released. -- Christos Trochalakis Fri, 12 Jun 2015 15:42:49 +0300 nginx (1.6.2-5ubuntu4) wily; urgency=medium * debian/apport/source_nginx.py: - Add apport hooks for additional bug information gathering, as a result of non-useful reports due to postinstall script failure bugs. This is necessary in order to be able to actually debug what is going on in the bug reports, thanks to systemd not putting startup errors to stdout or stderr anymore, like Upstart and others did. (LP: #1472683) * debian/nginx-common.install: - Add install rule for debian/apport/source_nginx.py, which is the new apport hooks to gather additional 'Package' bugtype debug data. -- Thomas Ward Fri, 10 Jul 2015 12:51:48 -0400 nginx (1.6.2-5ubuntu3) vivid-proposed; urgency=medium * debian/rules: * Reversed Debian change in 1.6.2-5ubuntu2. * Added DEB_BUILD_MAINT_OPTIONS=hardening=+all to enable all dpkg-buildflags to harden the code, except for PIE flags. * Manually define DEB_BUILD_MAINT_OPTIONS in DEBIAN_NGINX_PERL_LDFLAGS to not have -fPIE conflicts in Perl flags. -- Thomas Ward Wed, 01 Apr 2015 14:57:34 -0400 nginx (1.6.2-5ubuntu2) vivid-proposed; urgency=medium * debian/rules: * Added -fPIE -pie to build rules (enables position-independent builds) using Debian's committed change to enable. (LP: #1315426) -- Thomas Ward Wed, 01 Apr 2015 14:26:32 -0400 nginx (1.6.2-5ubuntu1) vivid; urgency=medium * Merge from Debian. Remaining changes: (LP: #1399967) - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed) - debian/rules: Drop from -O3 to -O2 to work around a build failure. - d/{control,rules,nginx-core.*}: add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. - debian/tests/control: add nginx-core test. - debian/control: drop luajit from Build-Depends as it is in universe. -- Thomas Ward Sat, 06 Dec 2014 13:06:55 -0500 nginx (1.6.2-5) unstable; urgency=medium [ Christos Trochalakis ] * debian/conf/nginx.conf: + Drop SSLv3 protocol (POODLE), and prefer server ciphers by default. (Closes: #767456) * debian/copyright: + Add copyright for ngx_http_substitutions_filter_module. * debian/nginx-common.{preinst,postinst,postrm}: + Remove /etc/nginx/naxsi-ui.conf conffile. (Closes: #768233) * debian/README.Debian: + Add a list of important changes since wheezy. -- Christos Trochalakis Sun, 30 Nov 2014 10:39:55 +0200 nginx (1.6.2-4ubuntu1) vivid; urgency=medium * Merge from Debian. Remaining changes: (LP: #1388621) - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed). - debian/rules: Drop from -O3 to -O2 to work around a build failure. - d/{control,rules,nginx-core.*}: add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. - debian/tests/control: add nginx-core test. - debian/control: drop luajit from Build-Depends as it is in universe. * debian/control: * Remove nginx-naxsi* from nginx-core and related package stanzas, as the naxsi packages have all been dropped. * Remove reference to nginx-naxsi from nginx metapackage description * debian/index.html: Modify included index.html file to have Ubuntu branding, Ubuntu bug reporting tool references, and a link to the Launchpad bugs page for the nginx package. -- Thomas Ward Wed, 05 Nov 2014 10:05:07 -0500 nginx (1.6.2-4) unstable; urgency=medium [ Christos Trochalakis ] * debian/modules/nginx-development-kit: + Upgrade v0.2.17-7-g24202b4 -> v0.2.19 * debian/modules/nginx-echo: + Upgrade v0.51 -> v0.56 * debian/modules/nginx-upload-progress: + Upgrade v0.9.0-0-ga788dea -> 0.9.1 * debian/modules/ngx-fancy-index: + Upgrade v0.3.3 -> v0.3.4 * debian/copyright: + Rewrite copyright file fixing various issues. * debian/nginx-common.nginx.logrotate: + Switch postrotate to the initscript's rotate command. -- Christos Trochalakis Sun, 19 Oct 2014 08:23:33 +0300 nginx (1.6.2-3) unstable; urgency=medium [ Christos Trochalakis ] * Change the default document root to /var/www/html according to debian policy 3.9.6.0. (Closes: #730382) * Provide a new, debian specific, default landing page. * debian/nginx-common.nginx.service: + Graceful stopping of nginx was not handled correctly with systemd. * debian/nginx-common.nginx.init: + Gracefully stop nginx by default, we are switcing to a configurable STOP/5/TERM/5/KILL/5 schedule. We are now in sync with the systemd service file. (Closes: #762708) * debian/conf: + Introduce a `snippets/fastcgi-php.conf` snippet with a basic php configuration that can be included when needed. (Closes: #762491) + Introduce a `snippets/snakeoil.conf` snippet that enabled https using the certs installed by the ssl-cert package. + Suggest disabling SSLv3 in default site with a ref to POODLE. * debian/control: + nginx-common now suggests ssl-cert. -- Christos Trochalakis Thu, 16 Oct 2014 13:34:29 +0300 nginx (1.6.2-2) unstable; urgency=medium [ Christos Trochalakis ] * Drop nginx-naxsi, nginx-naxsi-dbg, nginx-naxsi-ui packages. (Closes: #746199, #737146, #712445) * debian/conf/nginx.conf: + Remove relic passenger stanga. -- Christos Trochalakis Fri, 26 Sep 2014 11:06:47 +0300 nginx (1.6.2-1ubuntu1.1) utopic; urgency=medium * debian/conf/sites-available/default: Remove SSLv3 from the ssl_protocols line in the default config example, due to POODLE vulnerability. -- Thomas Ward Wed, 22 Oct 2014 09:43:35 -0400 nginx (1.6.2-1ubuntu1) utopic; urgency=medium * Merge from Debian. Remaining changes: - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed). - debian/rules: Drop from -O3 to -O2 to work around a build failure. - d/{control,rules,nginx-core.*}: add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. * debian/tests/control: add nginx-core test. * debian/control: drop luajit from Build-Depends as it is in universe. -- Marc Deslauriers Mon, 22 Sep 2014 13:32:30 -0400 nginx (1.6.2-1) unstable; urgency=high [ Christos Trochalakis ] * New upstream release. CVE-2014-3616: "it was possible to reuse SSL sessions in unrelated contexts if a shared SSL session cache or the same TLS session ticket key was used for multiple "server" blocks". (Closes: #761940) -- Christos Trochalakis Wed, 17 Sep 2014 11:19:01 +0300 nginx (1.6.1-2) unstable; urgency=medium [ Christos Trochalakis ] * debian/control: + Build nginx-extras against luajit (Closes: #755875) * debian/modules/nginx-lua: + Update nginx-lua to v0.9.12 * debian/nginx-common.nginx.init: + Better pidfile extraction from nginx.conf (Closes: #747329) * debian/conf/mime.types: + Upgrade to the latest upstream mime types. As a consequence, nginx now uses "application/javascript" for javascript files. * debian/conf/nginx.conf: + Add application/javascript to the gzip_types list. (Closes: #737176) * debian/rules: + Make naxsi module first in configure parameters. Fixes erratic naxsi behaviour. (Closes: #758642) * debian/conf/{koi-utf,koi-win,scgi_params,uwsgi_params}: + Sync with upstream config files. * debian/conf/fastcgi_params: + Sync with upstream and remove `SCRIPT_FILENAME` parameter. This change might break fastcgi sites. (Closes: #718639) + debian/conf/fastcgi.conf: + Ship upstream file. * debian/nginx-common.NEWS: + Document syncing conf files with upstream. * debian/tests/control: + Include some simple autopkgtests. Thanks to Robie Basak for the initial patch. (Closes: #756391) * debian/modules/nginx-http-push: + Update to v0.73. Fixes fd leak on reload. (Closes: #745921) -- Christos Trochalakis Thu, 04 Sep 2014 13:00:46 +0300 nginx (1.6.1-1ubuntu2) utopic; urgency=medium * Rebuild for Perl 5.20.0. -- Colin Watson Sun, 24 Aug 2014 06:43:36 -0700 nginx (1.6.1-1ubuntu1) utopic; urgency=medium * Merge from Debian. Remaining changes: - debian/patches/ubuntu-branding.patch: add Ubuntu branding (refreshed). - debian/rules: Drop from -O3 to -O2 to work around a build failure. - d/{control,rules,nginx-core.*}: add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. * Add dep8 smoke test -- Robie Basak Fri, 15 Aug 2014 16:46:48 +0000 nginx (1.6.1-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release. Handle CVE-2014-3556 SMTP STARTTLS vulnerability (Closes: #757196) http://mailman.nginx.org/pipermail/nginx-announce/2014/000144.html -- Christos Trochalakis Wed, 06 Aug 2014 10:05:08 +0300 nginx (1.6.0-2) unstable; urgency=medium [ gregor herrmann ] * Patch from Gregor Herrmann : Fix "hardcodes /usr/lib/perl5": - drop debian/nginx-extras.dirs, not needed, dh_install uses the directories from debian/nginx-extras.install - make debian/nginx-extras.install executable, and use $Config{vendorarch} for the perl library path there (Closes: #752796) -- Kartik Mistry Tue, 29 Jul 2014 04:56:03 +0000 nginx (1.6.0-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release. * debian/rules: + Enable auth request http module. (Closes: #725732) * debian/patches/series: + Remove backported openssl guard patch. -- Christos Trochalakis Thu, 24 Apr 2014 19:23:22 +0300 nginx (1.4.7-2) unstable; urgency=medium [ Christos Trochalakis ] * debian/rules: + Convert to dh $@ As a side effect, fixes make dependency issues (Closes: #744050) -- Christos Trochalakis Thu, 17 Apr 2014 14:30:27 +0300 nginx (1.4.7-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release. (Closes: #742059) + Fixes pottential arbitrary code execution (CVE-2014-0133) Debian build was not vulnerable since it was compiled with the --with-debug configure option. * debian/modules/nginx-http-push: + Update to v0.711 (Closes: #732251) * debian/modules/headers-more-nginx-module: + Update to v0.25, containing several bugfixes. * debian/modules/nginx-echo: + Update to v0.51, containing several bugfixes. * debian/modules/nginx-dav-ext-module: + Update to v0.0.3, containing some uri encoding fixes. * debian/modules/ngx_http_substitutions_filter_module: + Update to v0.6.4, containing some enhancements. * debian/modules/nginx-auth-pam: + Update to v1.3. This version contains our downstream patch (See: #721702) -- Christos Trochalakis Tue, 18 Mar 2014 22:03:47 +0200 nginx (1.4.6-1ubuntu3) trusty; urgency=medium * Add new binary package for main, nginx-core, which contains only source-tarball-included modules and no third-party modules. * Changes to debian/ directory: - control: + Add entry for nginx-core and nginx-core-dbg. - rules: + Add nginx-core flavor to the build rules. - nginx-core.*: Add new packaging files for nginx-core based on the packaging files for nginx-full. * The above changes satisfy the requirements for main (LP: #1262710) -- Thomas Ward Mon, 10 Mar 2014 18:23:36 -0400 nginx (1.4.6-1ubuntu2) trusty; urgency=medium * debian/rules: Drop from -O3 to -O2 to work around a build failure. -- Adam Conrad Sun, 09 Mar 2014 11:49:28 -0600 nginx (1.4.6-1ubuntu1) trusty; urgency=low * Merge from Debian unstable. Remaining changes: - debian/patches/ubuntu-branding.patch: Add Ubuntu branding. -- Adam Conrad Sun, 09 Mar 2014 11:13:26 -0600 nginx (1.4.6-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release. * debian/rules: + Avoid double declaration of hardening flags. + Expand buildflags so the build log is easier to follow. + Switch to --with--cc-opt, --with-ld-opt configure flags. Nginx is now compiled with --Werror, making all warnings into errors. + Split common configure options. + Enable realip module for nginx-light. + Enable debug module for nginx-light and nginx-extras. * debian/patches/perl-use-dpkg-buildflags.patch: + Rewrite patch to just just override LDDLFLAGS and not CCFLAGS since this is handled by --with-cc-opt. * debian/watch, debian/upstream/signing-key.asc: + Fix upstream signature verification. -- Christos Trochalakis Tue, 04 Mar 2014 18:06:55 +0200 nginx (1.4.5-1ubuntu1) trusty; urgency=medium * Resynchronise with Debian (LP: #1280511). Remaining changes: - debian/patches/ubuntu-branding.patch: + Add Ubuntu branding to server_tokens. -- Colin Watson Sat, 15 Feb 2014 03:05:42 +0000 nginx (1.4.5-1) unstable; urgency=medium [ Christos Trochalakis ] * New upstream release. * debian/modules/nginx-lua: + Update nginx-lua to v0.9.4 * debian/nginx-naxsi-ui.preinst: + Fix exit status issue (Closes: #735152) * debian/control: + Fix arch:all to arch:any dependencies + Make nginx depend on specific flavor version * debian/nginx-*.postinst: + Make nginx start by default (Closes: #735551) * debian/nginx-*.prerm: + No need to check for invoke-rc.d, correctly set the exit code on error * debian/nginx-common.nginx.init: + Rewrite some parts of the initscript + Introduce rotate command + Introduce upgrade command -- Christos Trochalakis Thu, 13 Feb 2014 11:41:49 +0200 nginx (1.4.4-4) unstable; urgency=medium [ Christos Trochalakis ] * debian/nginx-common.postinst: + Fix log re-opening issue due to wrong /var/log/nginx permissions. (Closes: #734139) -- Christos Trochalakis Sat, 04 Jan 2014 09:41:40 +0200 nginx (1.4.4-3) unstable; urgency=medium [ Christos Trochalakis ] * debian/nginx-naxsi-ui.postinst: + Fix early exit issue (Closes: #715435) -- Christos Trochalakis Tue, 31 Dec 2013 11:47:07 +0200 nginx (1.4.4-2ubuntu1) trusty; urgency=medium * Resynchronise with Debian. Remaining changes: - debian/patches/ubuntu-branding.patch: + Add Ubuntu branding to server_tokens. -- Colin Watson Sat, 28 Dec 2013 10:21:44 +0000 nginx (1.4.4-2) unstable; urgency=low [ Michael Lustfield ] * debian/control: + Added Provides: httpd-cgi to packages. (Closes: #701508) + Added other options to nginx depends. (Closes: #729860) + Added Spdy to nginx-full package description. * debian/nginx-common.nginx.init: + Added missing line from patch. (Closes: #728103) * debian/conf/sites-available/default: + Changed ssl_protocols and ssl_ciphers. (Closes: 730142) * debian/nginx-common.preinst: + Modify permissions of /var/log/nginx. (Closes: #701112) * debian/rules: + Added spdy support to nginx-full. (Closes: #730432) [ Christos Trochalakis ] * debian/nginx-doc,docs, debian/nginx-common.NEWS: + Ship NEWS with nginx-common instead of nginx-doc. * debian/conf/proxy_params: + Host header should be passed unmodified to the proxied server. + Pass X-Forwarded-Proto header to the proxied server. * debian/control: + Fix nginx-naxsi-ui Depends and Conflicts lines. [ Neutron Soutmun ] * debian/patches/guard-use-of-deprecated-openssl-definition.patch: + Fix FTBFS against the recent libssl-dev. (Closes: #733107) [ Kartik Mistry ] * debian/control: + Updated to Standards-Version 3.9.5 * debian/watch, debian/upstream-signing-key.pgp: + Use upstream PGP signature to verify by watch file. -- Kartik Mistry Fri, 27 Dec 2013 21:16:01 +0530 nginx (1.4.4-1ubuntu1) trusty; urgency=low * Resynchronise with Debian (LP: #1253691). Remaining changes: - debian/patches/ubuntu-branding.patch: + Add Ubuntu branding to server_tokens. -- Colin Watson Fri, 22 Nov 2013 12:23:25 +0000 nginx (1.4.4-1) unstable; urgency=low [ Christos Trochalakis ] * New upstream release. (Closes: #730012) * debian/nginx-*.postinst: + Wait for the new master to write its pid file before sending QUIT to the old master. This solves an issue with systemd and the upgrade mechanism. Systemd receives the SIGCHLD from the old master but it can't see the new pid because the new master has not written it yet. As a result, it kills everything inside the cgroup, including the new master. * debian/modules/ngx-fancyindex: + Upgrade Fancy Index module to v0.3.3 (Closes: #728721) * debian/control: + Remove Upload module from nginx-extras description (Closes: #729003) [ Michael Lustfield ] * debian/control: + Added spdy to package description (Closes: #728038) * debian/nginx-common.nginx.init: + Showing better start/stop messages. Thanks Pim van den Berg. (Closes: #728103) -- Michael Lustfield Thu, 21 Nov 2013 19:25:50 +0530 nginx (1.4.3-2ubuntu1) trusty; urgency=low * Resynchronise with Debian. Remaining changes: - debian/patches/ubuntu-branding.patch: + Add Ubuntu branding to server_tokens. -- Colin Watson Mon, 21 Oct 2013 13:26:52 +0100 nginx (1.4.3-2) unstable; urgency=low [ Kartik Mistry ] * Renamed debian/nginx-common.service to debian/nginx-common.nginx.service so it is installed properly for systemd. Thanks to Christos Trochalakis. * Set debian/compat to 9 and updated debhelper dependency. [ Christos Trochalakis ] * debian/rules, debian/nginx-common.dirs, debian/debian-common.nginx.logrotate: + Switch to dh_installlogrotate. * debian/rules: + *-stamp files are deleted by dh_clean. + Remove unused mime-types target. + Remove not needed config.sub and config.guess targets. * debian/nginx-common.dirs: + Don't ship an empty /run dir. * debian/nginx-{light,full,extras}.lintian-overrides: + Override false lintian spelling error warning. -- Kartik Mistry Wed, 16 Oct 2013 14:58:11 +0530 nginx (1.4.3-1) unstable; urgency=low [ Cyril Lavier ] * debian/nginx-naxsi-ui.postinst, debian/nginx-naxsi-ui.preinst: + Added missing arguments to have clean postinst/preinst scripts. * debian/conf/fastcgi_params: + Defined fastcgi param HTTPS the same as upstream default. (Closes: #712989) [ Michael Lustfield ] * conf/sites-available/default: + Removed /doc/ section per bug #715804. [ Christos Trochalakis ] * New upstream release. (Closes: #722640) * debian/nginx-common.nginx.init: + Better pidfile extraction from nginx.conf. We now accept multiple spaces and tabs as a field separator. * debian/modules/nginx-auth-pam: + Fixed upstream bug. (Closes: #721702) * debian/watch: + Only check for stable releases. * debian/conf/sites-available/default: + Correctly fallback to 404 when the requested file is missing. (Closes: #724232) * debian/logrotate: + Gracefully handle empty pidfile in logrotate script. (Closes: #696797) [ Kartik Mistry ] * Switch to dh-systemd (Closes: #713853) -- Kartik Mistry Thu, 10 Oct 2013 17:28:56 +0530 nginx (1.4.1-3ubuntu1) saucy; urgency=low * Resynchronise with Debian. Remaining changes: - debian/patches/ubuntu-branding.patch: + Add Ubuntu branding to server_tokens. -- Colin Watson Thu, 20 Jun 2013 15:08:44 +0100 nginx (1.4.1-3) unstable; urgency=low [ Kartik Mistry ] * debian/control: + Changed libgd2-dev build-dep to libgd2-dev|libgd2-noxpm-dev allow backporting (Closes: #711505) [ Cyril Lavier ] * debian/nginx-naxsi-ui.preinst + Added argument "install" to the preinst script. (Closes: #711590) -- Kartik Mistry Sun, 09 Jun 2013 13:07:52 +0530 nginx (1.4.1-2ubuntu1) saucy; urgency=low * Resynchronise with Debian. Remaining changes: - debian/patches/ubuntu-branding.patch: + Add Ubuntu branding to server_tokens. -- Colin Watson Fri, 07 Jun 2013 15:41:48 +0100 nginx (1.4.1-2) unstable; urgency=medium [ Kartik Mistry] * Urgency set to medium due to Security and RC bugs. * debian/conf/sites-available/default: + Fixed typo in listen ipv6only=on (Closes: #707684) [ Cyril Lavier ] * debian/control: + Replaced the build-dep libgd2-noxpm-dev to libgd2-dev as part of the libgd2-{xpm,noxpm}-dev -> libgd2-dev transition. * debian/nginx-naxsi-ui.preinst, debian/nginx-naxsi-ui.postinst, debian/conf/naxsi-ui.conf.1.4.1: + Added preinst script and renamed the new config file to avoid prompting the user. (Closes: #707291) * debian/rules: + Made "debian/rules binary" enough to build binary package. (Closes: #708522) -- Kartik Mistry Thu, 06 Jun 2013 12:55:23 +0530 nginx (1.4.1-1ubuntu2) saucy; urgency=low * Rebuild for libgd3. -- Colin Watson Mon, 20 May 2013 00:45:10 +0100 nginx (1.4.1-1ubuntu1) saucy; urgency=low * Merge with Debian unstable (LP: #1177919). Remaining changes: - debian/conf/sites-available/default: + Modify default site configuration file to correct a typo that prevented out-of-the-box usability (LP: #1162177). - debian/patches/ubuntu-branding.patch: + Add ubuntu branding to server_tokens. * Refresh all patches. -- Dmitry Shachnev Sat, 11 May 2013 14:47:53 +0400 nginx (1.4.1-1) unstable; urgency=low * New upstream release: + Fixes arbitrary code execution (CVE-2013-2028). * Uploaded to unstable. * debian/control: + Updated Standards-Version to 3.9.4 -- Kartik Mistry Tue, 07 May 2013 19:53:46 +0530 nginx (1.4.0-2) experimental; urgency=low [ Ondřej Surý ] * debian/modules/: + Updated nginx-echo, nginx-cache-purge and naxsi modules. + Removed useless .gitignore, .gitmodules files. [ Kartik Mistry ] * debian/modules/nginx-upload: + This module no longer works with 1.3.x and above. Removed as of now. * debian/modules/ngx-fancyindex: + Added Fancy Indexes module (Closes: #704210) * debian/copyright: + Fixed path for modules in Files: field. + Updated copyright for debian/* * debian/rules: + Enabled spdy module (Closes: #706195). * debian/control: + Suggests: fcgiwrap (Closes: #701508). [ Cyril Lavier ] * debian/conf/naxsi-ui.conf: + Added configuration file for nginx-naxsi-ui using SQLite (Closes: #699678). * debian/nginx-naxsi-ui.config, debian/nginx-naxsi-ui.postinst, debian/nginx-naxsi-ui.postrm, debian/nginx-naxsi-ui.prerm, debian/nginx-naxsi-ui.templates: + Removed these files as they are not necessary anymore with the database engine switching from MySQL to SQLite. * debian/control: + Removed dependencies against MySQL. * debian/rules, debian/modules/ngx_http_substitutions_filter_module, debian/README.Modules-versions: + Added http_substitutions_filter module. (Closes: #706456) -- Kartik Mistry Wed, 01 May 2013 10:48:43 +0530 nginx (1.4.0-1) experimental; urgency=low [ Kartik Mistry ] * New upstream release (Closes: #706127). * debian/rules, debian/modules/: + Removed chunkin-nginx-module as it no longer supported for nginx 1.3.9+ + Updated nginx-lua module to 0.8.0 + Patched nginx-upload module as described in modules/README file. * Refreshed debian/patches/perl-use-dpkg-buildflags.patch * debian/logrotate: + Set default log to keep for 52 weeks instead of 52 days. Thanks to RjY for patch (Closes: #696440) * debian/rules: + Added cache purge module to nginx-extras. * debian/control: + Suggests: nginx-docs. Thanks to colliar for reporting bug (Closes: #702923) * debian/copyright: + Updated copyright year. + Fixed broken license text. [ Michael Lustfield ] * debian/conf/sites-available/default: + Added ipv6_only=on to default server block. (Closes: #700857) + Added default_server to ipv4 default server block. Now matches ipv6. * debian/rules: + Removed obsolete --with-md5 and --with-sha1 -- Kartik Mistry Thu, 25 Apr 2013 12:51:45 +0530 nginx (1.2.6-1ubuntu4) saucy; urgency=low * debian/patches/ubuntu-branding.patch: Move Ubuntu branding from the numerical version string to the long version (LP: #1174158) -- Adam Conrad Thu, 09 May 2013 11:50:52 -0600 nginx (1.2.6-1ubuntu3) raring; urgency=low * debian/patches/ubuntu-branding.patch: Add ubuntu branding to server_tokens. -- Chuck Short Tue, 09 Apr 2013 10:23:26 -0500 nginx (1.2.6-1ubuntu2) raring; urgency=low * debian/conf/sites-available/default: * Modify default site configuration file to correct a typo that prevented out-of-the-box usability (LP: #1162177) -- Thomas Ward Fri, 05 Apr 2013 20:22:38 +0100 nginx (1.2.6-1ubuntu1) raring; urgency=low * debian/conf/sites-available/default: * Modify default site default configuration file to bind to IPv6 only for IPv6 default listen statement (LP: #1132678) -- Thomas Ward Tue, 12 Mar 2013 00:23:02 +0000 nginx (1.2.6-1) unstable; urgency=low [ Kartik Mistry ] * New upstream release. * debian/nginx-common.nginx.init: + Used log_*_msg instead of echo for better init messages. + Added patch to check start-stop-daemon exit status, Thanks to Sergey B Kirpichev (Closes: #695374). * debian/po/ja.po: + Added new Japanese translation. Thanks to victory (Closes: #692481). * debian/po/pt_BR.po: + Added new Brazilian Portuguese translation. Thanks to Adriano Rafael Gomes (Closes: #692481). [ Cyril Lavier ] * debian/rules + Added RealIP module in nginx-naxsi (Closes: #693302). * debian/modules/nginx-cache-purge/ + Updated nginx-cache-purge module with the 2.0 version. * debian/modules/nginx-lua/ + Updated nginx-lua module with the 0.7.8 version. * debian/modules/nginx-echo/ + Updated the nginx-echo module with the 0.41 version. * debian/modules/headers-more-nginx-module/ + Updated the Headers-more module with the 0.19 version. * debian/modules/README.Modules-versions + Updated the current version of modules following the updates. [ Michael Lustfield ] * debian/conf/sites-available/default + Uncommented listen lines to make server block default. -- Kartik Mistry Tue, 18 Dec 2012 10:29:18 +0530 nginx (1.2.4-2) unstable; urgency=low * debian/conf/nginx.conf: + Fixed pid path to /run/nginx.pid in config. * debian/po/*.po, debian/nginx-naxsi-ui.templates, debian/po/templates.pot: + Fixed ^M characters in template file. Thanks to Christian Perrier for help (Closes: #692191, #692335) -- Kartik Mistry Mon, 05 Nov 2012 13:05:34 +0530 nginx (1.2.4-1) unstable; urgency=low [ Michael Lustfield ] * debian/nginx-common.nginx.init + Added --retry to start-stop-daemon. (Closes: #682360) + Added $named to Required-Start/Stop. (Closes: #679879) + Added some other modifications after testing. (LP: #1033856) * debian/rules: + Added -DFORTIFY_SOURCE=2 -fstack-protector to build flags. (Closes: #680712) * debian/nginx-common.install: + Moved default docs to /usr/share/nginx/html. (Closes: #1031515) * debian/rules: + Set prefix to /usr/share/nginx. * debian/po/fr.po + Updated French translation file. (Closes: #679601) * debian/logrotate: + Removed semicolon after an fi statement. (Closes: #683870) * debian/copyright: + Removed trailing slash from File: fields. * Changed /var/run to /run in multiple files. (LP: #1050516) * debian/nginx-common.dirs: + Added /run to .dirs to avoid conflicts with backports. (LP: #1072641) * debian/nginx-*.postinst: + Added sites-enabled/available directory checks. (Closes: #688410) - Thanks Andreas Marschke + Moved the symlink creation to nginx-common. * Updated debconf templates. * conf/sites-available/default: + Updated root to point at /usr/share/nginx/html instead of www. [ Kartik Mistry ] * Acknowledged NMUs (Closes: #681758, #681381) * New upstream release (Closes: #683704) * debian/po/*.po: + Removed ^M characters from headers. + Fixed all files with recent unneeded template change. -- Kartik Mistry Tue, 30 Oct 2012 10:10:34 +0530 nginx (1.2.1-2.2) unstable; urgency=low * Non-maintainer upload. * Fix "removes files that were installed by another package": don't remove directories that are owned by (and removed from) nginx-common from nginx-extras.postrm. This seems to have been the idea in commit e30a854 ("Moved configuration purging to nginx-common.") except that it was added in nginx-common.postrm without being removed in nginx-extras.postrm. Remove nginx-extras.postrm since it's empty after this change. (Closes: #681758) -- gregor herrmann Sat, 04 Aug 2012 18:13:10 +0200 nginx (1.2.1-2.1) unstable; urgency=low * Non-maintainer upload to deal with the goal of 100% translated debconf templates for 7 languages in wheezy. * Drop nasty ^M characters from the templates file. They break debconf-updatepo and therefore translations. Closes: #681381 * As a consequence, fix translations as some of them had been "updated" in the meantime wrt broken templates -- Christian Perrier Thu, 12 Jul 2012 21:23:57 +0200 nginx (1.2.1-2) unstable; urgency=medium [Cyril Lavier] * Urgency set to medium, security bug in naxsi module, fix via upstream. * debian/modules/naxsi: + Updated naxsi module to version 0.46-1 fixing the following security issue : potential file disclosure in nx_extract. -- Cyril Lavier Wed, 27 Jun 2012 13:52:03 +0200 nginx (1.2.1-1) unstable; urgency=medium [Kartik Mistry] * Urgency set to medium, RC bug fix. * New upstream release (Closes: #677396) * debian/nginx.1: + Updated with description taken from debian/control. * debian/po/cs.po: + Added Czech translation of PO debconf template. (Closes: #673120, #678659) * debian/po/da.po: + Added Danish translation of PO debconf template. (Closes: #674461, #677806) * debian/po/it.po: + Added Italian translation of PO debconf template. (Closes: #679185) * debian/po/nl.po: + Added Dutch translation of PO debconf template. (Closes: #675314) * debian/po/pl.po: + Added Polish translation of PO debconf template. (Closes: #678156) * debian/po/pt.po: + Added Portuguese translation of PO debconf template. (Closes: #674609, #679149) * debian/po/sk.po: + Added Slovak translation of PO debconf template. (Closes: #677282) * debian/po/sv.po: + Added Swedish translation of PO debconf template. (Closes: #675107, #677032) * debian/copyright: + Removed duplicate Copyright fields. * debian/modules/nginx-lua: + Updated to latest upstream git tag 0.5.0rc29-6446ee71b8, Fix for worker process crashes (Closes: #674928) * debian/nginx-naxsi-ui.templates, debian/po/templates.pot: + Updated debconf template after review from l10n-english team. (Closes: #675237) + Do not add empty line. * debian/po/*.po: + Refreshed after template update. [Cyril Lavier] * debian/rules: + Added status module to nginx-naxsi. (Closes: #672998) * debian/control: + Updated nginx-naxsi module list. + Updated nginx-full module list. (Closes: #677128) * debian/po/de.po: + Added German translation of PO debconf template. (Closes: #673861, #677790) * debian/po/ru.po: + Added Russian translation of PO debconf template. (Closes: #674188) * debian/po/es.po: + Added Spanish translation of PO debconf template. (Closes: #678915) * debian/po/gl.po: + Added Galician translation of PO debconf template. (Closes: #678910) * debian/nginx-naxsi-ui.postrm, debian/nginx-naxsi-ui.prerm: + Added postrm and prerm scripts for nginx-naxsi-ui. (Closes: #673787) [Michael Lustfield] * debian/nginx-common.preinst: + Copied install stuff to upgrade in case statement. (LP: #1014506) * debian/rules + Added --with-pcre-jit to build. (LP: #915344) * debian/conf/sites-available/default: + Changed default try_files example. (LP: #969207) * debian/nginx-*.postrm: + Changed a few things so files are only purged on purge. (Closes: #678060) - Thanks Jeroen Dekkers -- Kartik Mistry Wed, 27 Jun 2012 09:24:50 +0530 nginx (1.2.0-1) unstable; urgency=low [Cyril Lavier] * New upstream release. (Closes: #670306) + 1.2.x is stable release now. * debian/modules/chunkin-nginx-module: + Updated chunkin-nginx-module to v0.23rc2-3-g85eca98. * debian/modules/headers-more-module: + Updated headers-more-module to v0.17rc1-4-g33a82ed. * debian/modules/nginx-development-kit: + Updated nginx-development-kit to v0.2.17-7-g24202b4. * debian/modules/nginx-echo: + Updated nginx-echo to v0.38rc2-7-g080c0a1. * debian/modules/nginx-lua: + Updated nginx-lua to v0.5.0rc25-5-g8d28785. * debian/modules/nginx-upstream-fair: + Updated nginx-upstream-fair to a18b409. * debian/modules/nginx-upload-progress: + Updated nginx-upload-progress to v0.9.0-0-ga788dea. * debian/modules/naxsi: + Updated naxsi to 0.46 * debian/modules/README.Modules-versions: + Updated versions and URLs for modules. * debian/naxsi-ui-extract, debian/naxsi-ui-intercept, debian/nginx-naxsi-ui.*, debian/naxsi-ui-extract.1, debian/naxsi-ui-intercept.1, debian/rules: + Added nginx-naxsi-ui package containing the learning daemon and the WebUI. * debian/nginx-common.nginx.default, debian/nginx-common.nginx.init: + Renamed files to be compliant with the nginx-naxsi-ui package. * debian/po: + Added needed files for using po-debconf. + Added French translation. * debian/control: + Applied the modifications given after the review by Justin Rye. [Michael Lustfield] * debian/conf/uwsgi_params: + Added UWSGI_SCHEME to uwsgi_params. (Closes: #664878) * debian/conf/sites-available/default: + Added allow directive for ipv6 localhost. (Closes: #664271) [Kartik Mistry] * debian/control: + wrap-and-sort. * debian/copyright: + Added missing copyrights, minor formatting fixes. * debian/nginx-common.nginx.init: + Added ulimit for restarts, Thanks to Daniel Roschka for patch. (Closes: #673580) * debian/conf/sites-available/default: + Added patch to fix deprecated "listen" directive, Thanks to Guillaume Plessis for patch. (Closes: #672632) -- Kartik Mistry Mon, 14 May 2012 11:15:00 +0530 nginx (1.1.19-1) unstable; urgency=high [Cyril Lavier] * New upstream release. + Fixed a buffer overflow in the ngx_http_mp4_module. See: CVE-2012-2089 for more details. * debian/copyright: + Updated licenses. * debian/nginx-extras.postinst, debian/nginx-full.postinst, debian/nginx-light.postinst, debian/nginx-naxsi.postinst: + Removing the debug markers. (Closes: #667894) * debian/control, debian/rules, debian/copyright, debian/modules/nginx-dav-ext-module: + Added nginx-dav-ext-module in full and extras. * debian/modules/naxsi: + Updated naxsi to the SVN snapshot (r280) to fix the licence issue with OpenSSL. [Kartik Mistry] * Misc cleanups in debian/control, debian/copyright. -- Cyril Lavier Fri, 13 Apr 2012 16:58:59 +0530 nginx (1.1.18-1) unstable; urgency=low [Cyril Lavier] * New upstream release. * New binaries introduced: nginx-naxsi, nginx-naxsi-dbg. * debian/modules/nginx-cache-purge: + Added nginx cache purge 1.5 to nginx-naxsi. * debian/rules, debian/control, debian/nginx-naxsi.dirs, debian/nginx-naxsi.install, debian/nginx-naxsi.postinst, debian/nginx-naxsi.postrm, debian/nginx-naxsi.prerm, debian/modules/naxsi, debian/conf/naxsi_core.rules, debian/modules/README.Modules-versions, debian/conf/nginx.conf: + Added nginx-naxsi flavour. + Added naxsi 0.44 to nginx-naxsi. -- Cyril Lavier Thu, 29 Mar 2012 22:43:07 +0530 nginx (1.1.17-2) unstable; urgency=high [Cyril Lavier] * debian/control: + Added build dependency to dpkg-dev (>= 1.15.7). (Closes: #664212) * debian/patches/perl-use-dpkg-buildflags.patch: + Added patch to harden flags for perl module (Thanks to Simon Ruderich for the patch). (Closes: #664090) [Kartik Mistry] * Set urgency due to fix for security and RC bugs with 1.17.1-1 upload. -- Cyril Lavier Sun, 18 Mar 2012 09:31:19 +0530 nginx (1.1.17-1) unstable; urgency=medium [Kartik Mistry] * New upstream release. (Closes: #664137) + Fixed malformed HTTP responses. See: CVE-2012-1180 for more details. * Set urgency to medium due to security issue. [Cyril Lavier] * debian/rules: + Set NUMJOBS to 1 if no value is given + Added Auth PAM module to nginx-extras + Enable hardened flags for perl module (Thanks to Simon Ruderich for the patch) (Closes: #664090). * debian/conf/sites-available/default: + Added the fastcgi_pass for php5-fpm. (Closes: #662997) * debian/nginx-common.postrm, debian/rules, debian/nginx-common.postinst, debian/nginx-common.prerm, debian/nginx-common.service: + Added the systemd support. Thanks to Michael Stapelberg for the patch. (Closes: #662799) -- Kartik Mistry Fri, 16 Mar 2012 10:27:38 +0530 nginx (1.1.16-1) unstable; urgency=low [Cyril Lavier] * Modified the parallel build to avoid random FTBFS in Ubuntu. * New upstream release. * debian/modules: + Updated nginx-upload-progress to 0.8.3-2-g03cbf1f. * debian/control: + Added myself as uploader. + Added libpam0g-dev to Build-Depends. + Use wrap-and-sort to wrap control file fields. [Michael Lustfield] * debian/nginx-common.postinst: + Changed postinst to not change permissions on all log files. (Closes: #658492) * debian/rules: + Added Auth PAM module at debian/modules/nginx-auth-pam. (Closes: #660408) [Kartik Mistry] * debian/control: + Added conflict between -dbg packages as seen by Lintian. + Updated Standards-Version to 3.9.3 * debian/copyright: + Updated for copyright-format 1.0 + Updated upstream copyright year and details. * debian/rules: + Moved nginx-auth-pam module to nginx-full package. -- Kartik Mistry Sun, 04 Mar 2012 10:31:21 +0530 nginx (1.1.14-1) unstable; urgency=low [Cyril Lavier] * New upstream release. * debian/rules: + Resolved the lintian errors "unstripped-binary-or-object" with a cleaner correction (Thanks to Steven Chamberlain for the patch). + Added a check on the parallel building to force NUMJOBS to 1 if the value 0 is given. * debian/modules: + Updated nginx-lua module to version 0.4.1. [Kartik Mistry] * debian/rules, debian/control, debian/copyright, debian/modules/nginx-upload-module: + Added Upload module to nginx-extras, updated long description and copyright. (Closes: #654593) * debian/modules/README.modules: + Added Homepage information for some modules. * debian/rules: + Enable hardened build flags, Thanks to Moritz Muehlenhoff for patch. (Closes: #658186) -- Kartik Mistry Wed, 01 Feb 2012 17:50:05 +0530 nginx (1.1.12-1) unstable; urgency=low [Kartik Mistry] * debian/control: + Set myself as Maintainer, Jose Parrella as Uploaders with approval from team. * debian/copyright: + Fixed DEP5 URL. + Updated debian/* copyright. * debian/modules: + Updated nginx-lua module to version 0.3.1rc43 [Cyril Lavier] * New upstream release. * debian/conf/sites-available/default: + Added a / in the alias directive. (Closes: #653160) * debian/rules: + Added necessary lines for parallel building. -- Kartik Mistry Sun, 01 Jan 2012 17:21:02 +0530 nginx (1.1.11-1) unstable; urgency=low [Kartik Mistry] * New upstream release. * debian/control: + Set priority to extra for nginx-light and nginx-extras binaries (Policy: Section 2.5) * debian/patches/607418-ipv6-addresses.diff: + Removed. Merged upstream with 1.1.9 release. * debian/copyright: + Updated upstream copyright year, updated Michael's email address, misc changes for format. [Michael Lustfield] * debian/conf/fastcgi_params: + Changed $server_https to $https per new feature in 1.1.11. * debian/conf/nginx.conf: + Removed map for $server_https as it's no longer needed. -- Kartik Mistry Wed, 14 Dec 2011 09:45:40 +0530 nginx (1.1.8-2) unstable; urgency=low * debian/modules/chunkin-nginx-module: + Reinclude HttpChunkin Module with new upstream version (closes: #638814) * debian/control: + Add myself to uploaders list. -- Dmitry E. Oboukhov Thu, 24 Nov 2011 14:16:50 +0530 nginx (1.1.8-1) unstable; urgency=low [Kartik Mistry] * New upstream release. * debian/modules/chunkin-nginx-module: + Removed as of now, as it breaks with Perl 5.14 (Closes: #649061) [Michael Lustfield] * debian/control: + Added Map module to nginx-light modules list. * debian/rules: + Removed --without-http_map_module form nginx-light. * debian/nginx-common.install: + Changed ufw profile installation (LP: #825349). - debian/ufw.profile -> debian/ufw/nginx. * debian/nginx-common.preinst: + Cleanup of moved nginx profile. * debian/conf/nginx.conf: + Added a default map for $server_https (on|off). * debian/conf/fastcgi_params: + Pass HTTPS so $_SERVER['HTTPS'] is set (LP: #857831). * debian/conf/mime.types: + Added json type (LP: #883440). * debian/conf/sites-available/default: + Added notes about PHP (Closes: #642995). + Changed location /doc from root to alias. + Changed location /doc to /doc/ for people that don't bother reading or learning anything about Nginx configuration files (LP: #840358). -- Kartik Mistry Fri, 18 Nov 2011 23:44:00 +0530 nginx (1.1.4-2) unstable; urgency=low [Kartik Mistry] * debian/modules: + Updated nginx-upload-progress module, Thanks to upstream for fixing issue that FTBFS nginx on kFreeBSD-* archs. + Updated nginx-lua module to latest upstream. -- Kartik Mistry Mon, 26 Sep 2011 10:17:04 +0530 nginx (1.1.4-1) unstable; urgency=low [Kartik Mistry] * New upstream release. * debian/rules: + Added 'HTTPStubStatus' module in nginx-light also (Closes: #639661). + Added 'HTTP MP4' module in nginx-extras. (Closes: #642022). * Add new modules, Thanks to Dmitry E. Oboukhov : + NginxHttpHeadersMore Module (closes: #638820). + HttpChunkin Module (closes: #638814). * Renamed debian/modules/versions to debian/modules/README.modules-version, added missing homepage and version information. -- Kartik Mistry Sun, 25 Sep 2011 13:44:48 +0530 nginx (1.1.2-1) unstable; urgency=low [ Kartik Mistry ] * New upstream release * debian/control: + Added missing 'http-push' module in long description of nginx-extras. (Closes: #638924) + Removed 'File AIO' module from description, which we don't provide. (Closes: #639360) + Added 'HTTP Sub Module' in long description of nginx-extras, nginx-full. + Updated Breaks/Replaces fields. [ Michael Lustfield ] * debian/copyright: + Updated email address for Michael Lustfield * debian/control: + Updated email address for Michael Lustfield + Updated Breaks on nginx-common to address conflicting versions -- Kartik Mistry Wed, 07 Sep 2011 12:15:36 +0530 nginx (1.1.0-1) unstable; urgency=low [ Kartik Mistry ] * New upstream release * debian/control: + Added 'Upload Progress' module in long description of nginx-extras (Closes: #635313) * debian/rules, debian/modules: + Removed deprecated module: nginx-secure-download * debian/modules: + Updated nginx-lua module to version: v0.2.1rc2 + Updated nginx-echo module to version: v0.37rc1 -- Kartik Mistry Tue, 02 Aug 2011 20:06:43 +0530 nginx (1.0.5-1) unstable; urgency=low * New upstream release * debian/control: + nginx Depends on either nginx-full or nginx-light, Thanks to Hans van Kranenburg (Closes: #633879) * debian/copyright: + Updated to latest DEP-5 specification + Added some missing copyrights for modules + Updated copyright years -- Kartik Mistry Wed, 20 Jul 2011 10:16:45 +0530 nginx (1.0.4-1) unstable; urgency=low * New upstream release * debian/*.lintian-overrides, debian/rules: + Removed unused lintian for missing manpages -- Kartik Mistry Wed, 01 Jun 2011 19:12:25 +0530 nginx (1.0.1-1) unstable; urgency=low * New upstream release * debian/rules: + Removed if surrounding copy of man/ as it is required for builds. + Added nginx-upload-progress to nginx-extras. (Closes: #618306) + Added nginx-secure-downloads to nginx-extras. (Closes: #622268) + Added --prefix to configure command. (Closes: #619482) * debian/modules: + Added nginx-upload-progress/*. + Added nginx-secure-download/*. + Updated nginx-lua/*. + Updated versions. * debian/control: + Added libmhash-dev build dependency. + Updated Standards-Version to 3.9.1. -- Michael Lustfield Mon, 09 May 2011 00:36:54 +0530 nginx (1.0.0-2) unstable; urgency=low * debian/rules: + Removed --with-file-aio support. Fixed FTBFS on kFreeBSD-* arch (Closes: #621882) -- Kartik Mistry Sat, 16 Apr 2011 13:47:58 +0530 nginx (1.0.0-1) unstable; urgency=low [Kartik Mistry] * New upstream release: + Removed debian/patches/609343-log-time-iso8601.diff, merged upstream. * debian/rules: + Fixed: FTBFS on sparc64, detects sparc64 as sparc. Thanks to Aurelien Jarno (Closes: #617924) * debian/watch: + Updated for 1.x.x release [Michael Lustfield] * debian/rules: + Added Echo module back to nginx-full. (LP: #735622) + Moved nginx-push-0.96 to nginx-http-push. * debian/modules: + Updated nginx-development-kit. + Updated nginx-echo. + Updated nginx-http-push. + Updated nginx-lua. + Updated nginx-upstream-fair. + Added versions to track module versions. * debian/conf/fastcgi_params: + Changed $document_root$fastcgi_script_name to $request_filename. -- Kartik Mistry Thu, 14 Apr 2011 10:41:08 +0530 nginx (0.8.54-4) unstable; urgency=low [Micheal Lustfield] * debian/nginx-{full,light,extras}.default: + Added comment about alternative to ULIMIT. * debian/nginx-{full,light,extras}.init.d: + Added quotes around a test variable. (Closes: #610946, LP: #699736) * debian/patches/609343-log-time-iso8601.diff: + Added patch to add $time_iso8601 variable to logs. (Closes: #609343) * Clean up old logrotate files. (Closes: #608983, Closes: #610289) + Added Files: - debian/nginx-common.preinst + Modified Files: - debian/rules + Moved debian/nginx-common.logrotate to debian/logrotate. * Added common files to nginx-common package. (Closes: #610290) + Removed Files: - debian/nginx-full.dirs - debian/nginx-light.dirs - debian/nginx-full.install - debian/nginx-light.install - debian/nginx-extras.install - debian/nginx.* + Added Files: - debian/nginx-common.default - debian/nginx-common.dirs - debian/nginx-common.init.d - debian/nginx-common.install - debian/nginx-common.manpages - debian/logrotate + Modified Files: - debian/nginx-extras.dirs - debian/control - debian/rules * debian/nginx-*.install: (Closes: #609797) + Removed NEWS.Debian from nginx-{full,light,extras}.install. + Added NEWS.Debian to nginx-common.install. * nginx-common.postinst: + Enforce /var/log/nginx mode and user:group. (Closes: #610983) + Enforce /var/log/nginx/*.log mode and user:group. (Closes: #612832) * debian/rules: + Added --with-file-aio to nginx-extras. (Closes: #613175) + Removed split clients and user id modules from nginx-light. * debian/conf/sites-available/default: + Fixed a minor typo ( s/Quickstart/QuickStart/ ). (Closes: #613355) * debian/conf/mime.types: + Changed xml type to application/xhtml+xml. (Closes: #613851) * debian/help/docs/fcgiwrap: + Removed Ubuntu specific line in docs. (Closes: #614987) * debian/conf/sites-available/default: + Fixed a pointer to a file. (Closes: #614980) [Kartik Mistry] * debian/*.lintian-overrides: + Add Lintian overrides for nginx man page. We've manpage in nginx-common binary -- Michael Lustfield Thu, 03 Mar 2011 23:39:07 +0530 nginx (0.8.54-3) unstable; urgency=low * debian/control: + Added Breaks: and Replaces: to nginx packages. (Closes: #609254) * debian/rules: + Adding SSL support to nginx-light. (Closes: #609134) + Adding HTTP Addition module to nginx-full and nginx-extras. (Closes: #609411) + Added HTTP Push module to nginx-extras. (LP: #694456) -- Michael Lustfield Tue, 11 Jan 2011 05:27:39 -0600 nginx (0.8.54-2) unstable; urgency=low * Do not install nginx.8 man page in debug packages (Closes: #608633) -- Kartik Mistry Sun, 02 Jan 2011 18:46:03 +0530 nginx (0.8.54-1) unstable; urgency=low [ Michael Lustfield ] * Added ipv6 patch. (Closes: #607418) + Edited files: - src/http/ngx_http_request.c * Added ulmit patches. (Closes: #606094) + Added files: - debian/nginx-full.default - debian/nginx-light.default - debian/nginx-extras.default + Edited files: - debian/nginx-full.init.d - debian/nginx-light.init.d - debian/nginx-extras.init.d * Added perl module to nginx-extras. (Closes: #598461) + debian/rules: - Added --with-http_perl_module to nginx-extras. + debian/control: - Added libperl-dev build dependency. + debian/nginx-extras.install: - Added perl install files + debian/nginx-extras.dirs: - Added directory to install perl files. * debian/rules: + Added ifeq to handle nginx.8 (man page) if it exists in the source. * debian/control: + Added descriptions to make clear the differences between nginx packages. * Removed patches: + debian/patches/nginx-echo.diff - Put source into debian/patches/. + debian/patches/nginx-upstream-fair.diff - Put source into debian/patches/. + debian/patches/dlopen.diff - Patch no longer relevant. * Added modules: + debian/modules/nginx-development-kit + debian/modules/nginx-upstream-fair + debian/modules/nginx-echo + debian/modules/nginx-lua * Split Nginx into multiple variations of the package. + Added files for nginx-full: - debian/nginx-full.install - debian/nginx-full.dirs - debian/nginx-full.logrotate - debian/nginx-full.init.d - debian/nginx-full.postinst - debian/nginx-full.prerm - debian/nginx-full.postrm + Added files for nginx-light: - debian/nginx-light.install - debian/nginx-light.dirs - debian/nginx-light.logrotate - debian/nginx-light.init.d - debian/nginx-light.postinst - debian/nginx-light.prerm - debian/nginx-light.postrm + Added files for nginx-extras: - debian/nginx-extras.install - debian/nginx-extras.dirs - debian/nginx-extras.logrotate - debian/nginx-extras.init.d - debian/nginx-extras.postinst - debian/nginx-extras.prerm - debian/nginx-extras.postrm + Removed files for nginx: - debian/nginx.install - debian/nginx.dirs - debian/nginx.logrotate - debian/init.d - debian/postinst - debian/prerm - debian/postrm + Updated debian/rules: - Modified rules to create extra packages. + Updated debian/control: - Added packages for nginx-{full,light,extras}. - Added packages for nginx-{full,light,extras}-dbg. - Changed nginx to a dummy package selecting nginx-full. [Kartik Mistry] * debian/control: + Added doc section for nginx-doc + Wrapped some long descriptions, updated short descriptions + Added perl:Depends for nginx-extras * debian/rules: + Fixed dh_installchangelogs, dh_compress -- Michael Lustfield Thu, 30 Dec 2010 14:15:26 +0530 nginx (0.8.53-2) unstable; urgency=low [Kartik Mistry] * debian/conf/mime.types: + Added html5 codecs support (Closes: #605212) * debian/conf/fastcgi_params: + Fixed typo (Closes: #605582) [Michael Lustfield] * debian/conf/nginx.conf: + Reduced worker_connections to 768 (Closes: #605529) * Add an nginx site management script to nginx-doc. (Closes: #593580) + debian/help/examples/nginx_modsite: Added. * debian/nginx.logrotate: + Added prerotate chunk for awstats. (Closes: #590098) * debian/copyright: + Added Michael Lustfield * Created nginx-doc: + Added 'Package: nginx-doc' section to debian/control + Moved debian/nginx.examples -> debian/nginx-doc.examples + Moved debian/nginx.docs -> debian/nginx-doc.docs -- Kartik Mistry Mon, 06 Dec 2010 11:26:22 +0530 nginx (0.8.53-1) unstable; urgency=low [Kartik Mistry] * debian/control: + Added Michael Lustfield as co-maintainer * nginx.conf: + No need to use regex in gzip_disable for msie6, Thanks to António P. P. Almeida (Closes: #592147) * conf/sites-available/default: + Fixed typo for "include fastcgi", Thanks to Mostafa Ghadamyari (Closes: #593142, #593143) * debian/patches/fix_reloading_ipv6.diff: + Removed, merged upstream * debian/init.d: + Added fix to control nginx by user in a simple way by setting DAEMON variable to an invalid name in /etc/default/nginx. Patch by Toni Mueller (Closes: #594598) * debian/NEWS.Debian: + Updated news for 0.8.x as stable branch [Michael Lustfield] * New upstream release (Closes: #602970) + 0.8.x branch is declared stable by upstream now * Add a UFW profile set: + debian/nginx.ufw.profile: Added. + debian/control: nginx: Suggests ufw. + debian/dirs: Add 'etc/ufw/applications.d' + debian/rules: Add install rule for the nginx UFW profile. * Moved debian/dirs to debian/nginx.dirs * Added types_hash_max_size to nginx.conf * Install simple default index.html file (Closes: #581416) + debian/dirs: Add 'usr/share/nginx/www'. + debian/nginx.install: Add 'html/* usr/share/nginx/www'. * debian/patches/nginx-echo.diff: + Added Echo module * Added files for nginx.docs - /usr/share/doc/nginx/ + debian/help/docs/fcgiwrap + debian/help/docs/php + debian/help/docs/support-irc + debian/help/docs/upstream * Added files for nginx.examples - /usr/share/doc/nginx/examples/ + debian/help/docs/drupal + debian/help/docs/http + debian/help/docs/mail + debian/help/docs/mailman + debian/help/docs/nginx.conf + debian/help/docs/virtual_hosts + debian/help/docs/wordpress * debian/conf/: + Removed excess spaces + Added tabs where appropriate + Added SCRIPT_FILENAME to fastcgi_params -- Kartik Mistry Sat, 27 Nov 2010 21:04:02 +0530 nginx (0.7.67-3) unstable; urgency=low * debian/rules: + Readded the configure option --with-mail_ssl_module, Thanks to Roland Rosenfeld (Closes: #590815) * debian/control: + Updated Standards-Version to 3.9.1 (no changes needed) -- Kartik Mistry Thu, 29 Jul 2010 21:41:52 +0530 nginx (0.7.67-2) unstable; urgency=low * debian/conf/sites-available/default: + Removed reference to SSLv2 protocol (Closes: #589139) * debian/control: + Updated Standards-Version to 3.9.0 * debian/copyright: + Don't point to BSD license file, included exact upstream version of license text + Added missing copyright owner for contrib/ scripts + debian/* license is same as upstream now as discussed with co-maintainers -- Kartik Mistry Mon, 19 Jul 2010 10:36:32 +0530 nginx (0.7.67-1) unstable; urgency=low * New upstream release -- Kartik Mistry Wed, 16 Jun 2010 01:26:51 +0530 nginx (0.7.65-7) unstable; urgency=low [Kartik Mistry] * debian/rules: + Enabled HTTPSubModule module in configure (Closes: #584828) + Arranged configure options in better manner -- Kartik Mistry Mon, 07 Jun 2010 14:33:24 +0530 nginx (0.7.65-6) unstable; urgency=low [Kartik Mistry] * debian/README.Debian: + Fixed typo and somewhat better wordings * debian/conf/mime.types: + Added entry to support 7zip files (Closes: #580423) * debian/init.d: + Do not print config testing info until an error found, Thanks to Ubuntu bug 568293 * debian/copyright: + Updated as per DEP-5 specification -- Kartik Mistry Sat, 22 May 2010 01:41:33 +0530 nginx (0.7.65-5) unstable; urgency=low [Kartik Mistry] * debian/patches/fix_reloading_ipv6.diff: + Added patch to fix reloading with IPv6 addresses, Thanks to Matthias-Christian Ott for patch (Closes: #577456) -- Kartik Mistry Wed, 14 Apr 2010 11:36:48 +0530 nginx (0.7.65-4) unstable; urgency=low [Kartik Mistry] * debian/conf/sites-available/default: + Really listen for both IPv4 and IPv6 addresses. Thanks to Nikolaus Schulz for notice (Closes: #574983) * debian/control, debian/rules: + Added GeoIP support, Thanks to Caetano Carezzato (Closes: #575280) * debian/conf/mime.types: + Added svg entry to mime.types, Jeremy Lal (Closes: #575155) -- Kartik Mistry Thu, 25 Mar 2010 00:21:50 +0530 nginx (0.7.65-3) unstable; urgency=medium [Kartik Mistry] * Urgency set to medium due to Release Goal * debian/conf/sites-available/default: + Listen for both IPv4 and IPv6 addresses by default (Closes: #574983) -- Kartik Mistry Tue, 23 Mar 2010 10:30:18 +0530 nginx (0.7.65-2) unstable; urgency=low * debian/README.Debian: + Added explanation about not installing files in /var/www/ (Closes: #572513) * debian/rules: + Readded realip module support (Closes: #507419) -- Kartik Mistry Sat, 06 Mar 2010 13:14:48 +0530 nginx (0.7.65-1) unstable; urgency=low [Kartik Mistry] * New upstream release * debian/init.d: + $local_fs $remote_fs $network $syslog is what we need in Required-Start and Required-Stop (Closes: #568238) * debian/copyright: + Updated package copyright year + Updated license text to make same as upstream license -- Kartik Mistry Fri, 05 Feb 2010 11:20:28 +0530 nginx (0.7.64-3) unstable; urgency=low [Kartik Mistry] * debian/conf/sites-available/default: + Added patch to fix default virtual host, Thanks to Thomas Venieris (Closes: #564726) * debian/init.d: + Added dependency on $remote_fs in Required-Start and Required-Stop (Closes: #566862) * Converted package to use 3.0 (quilt) source format * Updated to Standards-Version 3.8.4 -- Kartik Mistry Mon, 01 Feb 2010 23:44:21 +0530 nginx (0.7.64-2) unstable; urgency=low [Kartik Mistry] * debian/rules: + Used dh_prep instead of dh_clean -k * debian/control: + Added ${misc:Depends} in Depends * Added patch for adding debug package, Thanks to Matthew Palmer (Closes: #563339) * debian/copyright: + Added missing copyright owners for Debian package and fixed year and licence doesn't point to versionless symlink [Fabio Tranchitella] * debian/init.d: + Added patch from Wouter de Bie to add $DAEMON_OPTS in test_nginx_config() -- Kartik Mistry Sat, 09 Jan 2010 11:15:59 +0530 nginx (0.7.64-1) unstable; urgency=medium [Kartik Mistry] * Urgency set to medium due to security issue * New upstream release (Closes: #557602) + fixes SSL renegotiation vuln CVE-2009-3555 (Closes: #557873) * debian/nginx.1: + Corrected homepage entry (Closes: #556617) + Minor whitespace and empty line cleanups, added SEE ALSO section. Used .TP instead of .br, Added missing options, and this should (Closes: #556616) * debian/copyright: + Used © instead of deprecated (C) symbol + Formatted some texts * debian/control: + Added myself as uploader + Wrapped and rearranged Build-Depends for better readability * debian/patches/dlopen.dpatch: + Fixed patch name in comment + Added missing DP comment from changelog * debian/rules: + Minor fixes related to formatting of file and whitespaces * debian/watch: + Removed comments out of it -- Kartik Mistry Fri, 27 Nov 2009 11:10:18 +0530 nginx (0.7.63-1) unstable; urgency=low * New upstream release. -- Fabio Tranchitella Sun, 08 Nov 2009 09:53:46 +0100 nginx (0.7.62-4) unstable; urgency=low * debian/conf/nginx.conf: commented out the mail proxy example. (Closes: #551682) * debian/init.d: do not redirect the output of nginx -t. (Closes: #551683) -- Fabio Tranchitella Thu, 22 Oct 2009 19:50:05 +0200 nginx (0.7.62-3) unstable; urgency=low * debian/rules: fix the FTBFS on sparc. -- Fabio Tranchitella Fri, 16 Oct 2009 06:39:22 +0000 nginx (0.7.62-2) unstable; urgency=low * debian/rules: added --with-mail and --with-mail_ssl_module. * debian/patches/nginx-upstream-fair.dpatch: added support for the nginx-upstream-fair module. (Closes: #521447) * debian/patches/dlopen.dpatch: applied patch to remove the unnecesssary link to libdl. (Closes: #540599) -- Fabio Tranchitella Thu, 15 Oct 2009 18:32:00 +0000 nginx (0.7.62-1) unstable; urgency=low * New upstream release. * debian/rules: added --with-ipv6. (Closes: #547249) -- Fabio Tranchitella Sun, 27 Sep 2009 22:25:16 +0200 nginx (0.7.61-2) unstable; urgency=low * debian/control: bumped Standards-Version to 3.8.3, no changes needed. * debian/init.d: added status action. (Closes: #541228) * debian/rules: - added -with-http_gzip_static_module. (Closes: #541229) - use the switch --with-cc-opt="-m32 -mcpu=ultrasparc" on sparc. (Closes: #543571) -- Fabio Tranchitella Sat, 29 Aug 2009 17:03:44 +0200 nginx (0.7.61-1) unstable; urgency=low * New upstream version: *) Bugfix: nginx could not be built --without-http-cache; the bug had appeared in 0.7.60. *) Bugfix: a segmentation fault occurred in worker process, if a backend 401 error was intercepted and the backend did not set the "WWW-Authenticate" response header line. Thanks to Eugene Mychlo. *) Feature: the "keepalive_requests" directive. *) Bugfix: in open_file_cache and proxy/fastcgi cache interaction on start up. *) Bugfix: open_file_cache might cache open file descriptors too long. *) Bugfix: XLST filter did not work in subrequests. * Fix "gzip_disable in default conf for old IE", adding ignore rules for certain MSIE versions in the default configuration (Closes: #540025) * Fix "init.d: Config test before allowing a restart" adding a function and calling it before reloading, restarting and starting (Closes: #539778) * Drops path for pidof call in postinst script. -- Jose Parrella Wed, 05 Aug 2009 14:00:11 -0500 nginx (0.7.59-1) unstable; urgency=low * New upstream release, first in Debian for the 0.7 branch. Among other issues, it also fixes the problem with wildcard dns names used with SSL. (Closes: #515904) * debian/watch: updated. * debian/postinst: fixed a bashism. (Closes: #507913) * debian/conf/nginx.conf: removed default_type. (Closes: #509390) * debian/control: updated Standards-Version to 3.8.1, no changes needed. * debian/NEWS.Debian: documented the issues with server_names_hash_bucket_size. (Closes: #524785) -- Fabio Tranchitella Sun, 31 May 2009 18:38:56 +0200 nginx (0.7.14-1) experimental; urgency=low * New upstream release. * Adding configtest to the init.d script (Closes: #496279) * postinst now calls the builtin kill, so tweaks on the specific signal calls were needed. * Default HTML files are no longer installed. * The default configuration file no longer requires a 50x file under /var/www. -- Jose Parrella Tue, 02 Sep 2008 20:48:58 -0430 nginx (0.6.34-2) unstable; urgency=low * Added support for realip module. (Closes: #507419) -- Fabio Tranchitella Sat, 06 Dec 2008 10:34:01 +0100 nginx (0.6.34-1) unstable; urgency=low * New upstream release. * debian/rules: removed the --with-debug configure switch. (Closes: #500891) -- Fabio Tranchitella Sun, 30 Nov 2008 11:37:13 +0100 nginx (0.6.32-3) unstable; urgency=low * debian/control: build again on all the architectures, but use the switch --with-cc-opt="-m32 -mcpu=ultrasparc" on sparch. (Closes: #479185) -- Fabio Tranchitella Thu, 25 Sep 2008 17:14:27 +0200 nginx (0.6.32-2) unstable; urgency=low * debian/control: disabled support for sparc. (Closes: #479185) -- Fabio Tranchitella Sat, 20 Sep 2008 11:48:48 +0200 nginx (0.6.32-1) unstable; urgency=low * New upstream release. -- Fabio Tranchitella Fri, 18 Jul 2008 09:15:58 +0200 nginx (0.6.31-2) unstable; urgency=low * debian/control: removed httpd-cgi, nginx doesn't support executing external programs. (Closes: #482332) -- Fabio Tranchitella Thu, 22 May 2008 08:18:52 +0200 nginx (0.6.31-1) unstable; urgency=low * New upstream release. -- Fabio Tranchitella Mon, 12 May 2008 22:34:55 +0200 nginx (0.6.30-2) unstable; urgency=low * Upload into unstable. -- Fabio Tranchitella Mon, 12 May 2008 14:24:53 +0200 nginx (0.6.30-1) experimental; urgency=low * New upstream release. * Sync with the unstable packages. * debian/conf/nginx.conf: add support for a conf.d directory. (Closes: #476952) -- Fabio Tranchitella Fri, 02 May 2008 09:32:46 +0200 nginx (0.5.35-3) unstable; urgency=low * debian/conf/sites-available/default: adding support for /doc and /images namespaces (Closes: #474519) -- Jose Parrella Mon, 07 Apr 2008 13:22:32 -0430 nginx (0.5.35-2) unstable; urgency=low * debian/init.d: do not break if start-stop-daemon exits with an error. (Closes: #464453) -- Fabio Tranchitella Sun, 10 Feb 2008 17:57:57 +0100 nginx (0.5.35-1) unstable; urgency=low * New upstream release. -- Fabio Tranchitella Wed, 09 Jan 2008 07:58:56 +0100 nginx (0.5.34-1) unstable; urgency=low * New upstream release. * debian/control: added Homepage, Vcs-Svn, Vcs-Browser fields; updated Standard-Versions to 3.7.3. -- Fabio Tranchitella Mon, 24 Dec 2007 12:26:27 +0100 nginx (0.5.33-1) unstable; urgency=low * New stable upstream release (Closes: #451173) * nginx now provides httpd, httpd-cgi virtual packages (Closes: #439468, #452025) * sites-enabled/default link is now provided only on fresh installations (Closes: #432961) * Updated code for online upgrading of nginx (Closes: #445246) * Reviewed maintainer scripts for correct behaviour on updates (Closes: #452787, #435965) * Removed debian/nginx.links and debian/preinst. * Changing Maintainer address to bureado@debian.org. * Welcoming Fabio Tranchitella as an nginx uploader for Debian. Thanks for your patches. -- Jose Parrella Sat, 08 Dec 2007 11:27:54 -0400 nginx (0.5.30-1) unstable; urgency=low * New stable upstream release. * Adding mime.types (and other upstream conffiles) to the package since it was lost on 0.5.26 (Closes: #435964) -- Jose Parrella Sat, 04 Aug 2007 10:39:40 -0400 nginx (0.5.26-1) unstable; urgency=low * New stable upstream release. * Updating init.d usage message. * Installing logrotate script (Closes: #397978) -- Jose Parrella Sun, 17 Jun 2007 20:43:35 +0100 nginx (0.5.18-1) unstable; urgency=low * New upstream version (Closes: #420063) * Adding DAV support (Closes: #415678) * Adding support for sites-[available|enabled]/ (Closes: #419912) -- Jose Parrella Thu, 19 Apr 2007 21:50:37 -0400 nginx (0.5.13-1) unstable; urgency=low * Adding FLV support. (Closes: #411105) * Adding SSL support. -- Jose Parrella Mon, 19 Feb 2007 10:30:07 -0400 nginx (0.5.12-2) unstable; urgency=low * Patching src/core/ngx_shmtx.h in order to solve FTBFS problems in non-x86 archs (Thanks to Igor Sysoev) (Closes: #410884) -- Jose Parrella Wed, 14 Feb 2007 13:32:01 -0400 nginx (0.5.12-1) unstable; urgency=low * New upstream version fixes FTBFS problems in non-x86 archs (Closes: #409878) -- Jose Parrella Mon, 12 Feb 2007 19:37:07 -0400 nginx (0.5.11-1) unstable; urgency=low * New upstream version. (Closes: #405983) -- Jose Parrella Sun, 5 Feb 2007 19:35:56 -0400 nginx (0.4.13-2) unstable; urgency=low * Fixed default installation paths for www/ files, avoiding the default installation of index.html in /var/www (Closes: #400103) * Alexey Besciokov provided new postinst and prerm scripts with the ability to reload the master binary (Closes: #398009) -- Jose Parrella Fri, 24 Nov 2006 07:12:46 -0400 nginx (0.4.13-1) unstable; urgency=low * New upstream version * Fixed default configuration file which made nginx to fail at installation and purge. -- Jose Parrella Thu, 16 Nov 2006 22:44:33 -0400 nginx (0.4.12-1) unstable; urgency=low * New upstream version (Closes: #397969) * nginx will now compile with debugging and status support (Closes: #397967) * Added configuration reload support in the init.d script (Closes: #397980) * Added logrotate script (Closes: #397978) * Added debian/upstream.pl as a brief helper for new upstream version packaging. * Thanks to Alexey Besciokov for suggestions, bug reports and patches. -- Jose Parrella Sun, 12 Nov 2006 18:31:24 -0400 nginx (0.4.2-1) unstable; urgency=low * Initial release (Closes: #386151) * Tweaked the configuration file and the path handling for Debian. -- Jose Parrella Thu, 14 Sep 2006 11:40:20 -0400 debian/nginx-core.lintian-overrides0000664000000000000000000000007412705233614014625 0ustar nginx-core: spelling-error-in-binary usr/sbin/nginx tEH the debian/nginx-full.manpages0000664000000000000000000000003712705233614012773 0ustar debian/build-full/objs/nginx.8 debian/nginx-extras.install0000775000000000000000000000050612705233614013216 0ustar #!/usr/bin/perl -w use Config; my $vendorarch = substr($Config{vendorarch}, 1); print "debian/build-extras/objs/src/http/modules/perl/blib/arch/auto/nginx/* $vendorarch/auto/nginx\n"; print "debian/build-extras/objs/src/http/modules/perl/blib/lib/nginx.pm $vendorarch\n"; print "debian/build-extras/objs/nginx usr/sbin\n"; debian/nginx-core.dirs0000664000000000000000000000001112705233614012117 0ustar usr/sbin debian/nginx-light.postinst0000664000000000000000000000142012705233614013225 0ustar #!/bin/sh set -e case "$1" in abort-upgrade|abort-remove|abort-deconfigure|configure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then NGX_PID=`cat /run/nginx.pid` if kill -s USR2 $NGX_PID 2>/dev/null; then while [ ! -s /run/nginx.pid.oldbin ] || [ ! -s /run/nginx.pid ]; do cnt=`expr $cnt + 1` if [ $cnt -gt 10 ]; then kill -s KILL $NGX_PID invoke-rc.d nginx start exit 0 fi sleep 1 done NGX_OLD_PID=`cat /run/nginx.pid.oldbin` kill -s QUIT $NGX_OLD_PID fi else invoke-rc.d nginx start || exit $? fi fi #DEBHELPER# exit 0 debian/tests/0000775000000000000000000000000012705233614010335 5ustar debian/tests/control0000664000000000000000000000127712705233614011747 0ustar Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ Restrictions: allow-stderr isolation-container Depends: nginx-core, curl Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ Restrictions: allow-stderr isolation-container Depends: nginx-light, curl Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ Restrictions: allow-stderr isolation-container Depends: nginx-full, curl Test-Command: curl --silent --fail -o /dev/null -w "response_code: %{http_code}\n" http://127.0.0.1/ Restrictions: allow-stderr isolation-container Depends: nginx-extras, curl debian/nginx-doc.docs0000664000000000000000000000003212705233614011726 0ustar README debian/help/docs/* debian/nginx-full.lintian-overrides0000664000000000000000000000007412705233614014637 0ustar nginx-full: spelling-error-in-binary usr/sbin/nginx tEH the debian/nginx-extras.postinst0000664000000000000000000000142012705233614013424 0ustar #!/bin/sh set -e case "$1" in abort-upgrade|abort-remove|abort-deconfigure|configure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac if [ -x /etc/init.d/nginx ]; then if [ -f /run/nginx.pid ] && pidof /usr/sbin/nginx >/dev/null; then NGX_PID=`cat /run/nginx.pid` if kill -s USR2 $NGX_PID 2>/dev/null; then while [ ! -s /run/nginx.pid.oldbin ] || [ ! -s /run/nginx.pid ]; do cnt=`expr $cnt + 1` if [ $cnt -gt 10 ]; then kill -s KILL $NGX_PID invoke-rc.d nginx start exit 0 fi sleep 1 done NGX_OLD_PID=`cat /run/nginx.pid.oldbin` kill -s QUIT $NGX_OLD_PID fi else invoke-rc.d nginx start || exit $? fi fi #DEBHELPER# exit 0 debian/nginx-full.dirs0000664000000000000000000000001112705233614012131 0ustar usr/sbin debian/nginx-extras.prerm0000664000000000000000000000050412705233614012670 0ustar #!/bin/sh set -e case "$1" in remove|remove-in-favour|deconfigure|deconfigure-in-favour) if [ -x /etc/init.d/nginx ]; then invoke-rc.d nginx stop || exit $? fi ;; upgrade|failed-upgrade) ;; *) echo "prerm called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 debian/nginx-common.nginx.logrotate0000664000000000000000000000051112705233614014645 0ustar /var/log/nginx/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 www-data adm sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ run-parts /etc/logrotate.d/httpd-prerotate; \ fi \ endscript postrotate invoke-rc.d nginx rotate >/dev/null 2>&1 endscript } debian/nginx-common.install0000664000000000000000000000036312705233614013176 0ustar debian/conf/* etc/nginx debian/ufw/nginx etc/ufw/applications.d debian/apport/source_nginx.py usr/share/apport/package-hooks html/index.html usr/share/nginx/html/ debian/vim/nginx.yaml usr/share/vim/registry contrib/vim/* usr/share/vim/addons debian/source/0000775000000000000000000000000012705233614010473 5ustar debian/source/format0000664000000000000000000000001412705233614011701 0ustar 3.0 (quilt) debian/nginx-common.NEWS0000664000000000000000000001434512705233614012311 0ustar nginx-common (1.9.9-1) unstable; urgency=medium Starting with this release we are changing the default logrotate rule to keep daily logs for 14 days, this aligns our policy with apache2 (Bug #805322). -- Christos Trochalakis Thu, 14 Jan 2016 10:17:33 +0200 nginx-common (1.9.6-1) unstable; urgency=medium As of nginx 1.9.5 spdy has been replaced by the http2 module. Make sure to replace "spdy" with "http2" in your config files. -- Christos Trochalakis Fri, 25 Sep 2015 14:06:28 +0300 nginx-common (1.9.1-1) unstable; urgency=medium Starting with this release, we have enabled PIE build features which allows Address Space Layout Randomization. This is a hardening feature that prevents some potential security issues. While this will significantly help increase security, it can potentially cause significant performance issues on i386 systems. -- Michael Lustfield Tue, 07 Apr 2015 18:57:45 -0500 nginx-common (1.6.2-5) unstable; urgency=medium We have disabled SSLv3 in nginx.conf for security reasons (ref: POODLE), don't forget to re-enable it if your site depends on it. In this release we also include a summary of important changes since wheezy at /usr/share/doc/nginx-common/README.Debian. -- Christos Trochalakis Sun, 02 Nov 2014 09:10:09 +0200 nginx-common (1.6.2-3) unstable; urgency=medium Starting with this release, we changed the default document root from /var/www to /var/www/html, so that sensitive files from other virtual hosts wich are typically put into some directory below /var/www are not exposed by the default virtual host. -- Christos Trochalakis Tue, 30 Sep 2014 17:34:58 +0300 nginx-common (1.6.1-2) unstable; urgency=medium As of nginx-1.6.1-2 we have synced all configuration files with upstream and we plan to keep them in sync from now on. Unfortunately that might break existing configuration for some users. Please check the matrix below for more information: File Changes ----------------------- koi-win whitespace koi-utf whitespace mime-types whitespace, changed js/rss mime type, minor other changes & additions scgi_params whitespace, added HTTPS uwsgi_params whitespace, added HTTPS, removed UWSGI_SCHEME fastcgi_params whitespace, removed SCRIPT_FILENAME fastcgi.conf new upstream configuration file Fastcgi configuration issues ============================ nginx shipped a modified `fastcgi_params`, which declared `SCRIPT_FILENAME` fastcgi_param. This line has now been removed. From now on we are also shipping fastcgi.conf from the upstream repository, which includes a sane `SCRIPT_FILENAME` parameter value. So, if you are using fastcgi_params, you can try switching to fastcgi.conf or manually set the relevant params. You might also want to read the documentation section before proceeding. http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html section: $fastcgi_script_name variable. -- Christos Trochalakis Thu, 28 Aug 2014 14:23:42 +0300 nginx-common (1.4.4-2) unstable; urgency=low Per CVE-2013-0337 (bug #701112), we are changing /var/log/nginx permissions to root:adm 750. If you have manipulated these permissions in any way, you can add a dpkg-statoverride entry and the directory will not be touched. You also have to manually set the permissions once, as dpkg doesn't do that automatically for directories. e.g. chown root:adm /var/log/nginx chmod 0755 /var/log/nginx dpkg-statoverride --add root adm 0755 /var/log/nginx -- Michael Lustfield Sun, 24 Nov 2013 15:59:52 -0600 nginx (1.4.1-2) unstable; urgency=medium Started with nginx 1.4.1-2 upload, nginx-naxsi-ui switched backend from MySQL to SQLite. This was mostly caused by the future removal of MySQL support in naxsi-ui. Thus, the nginx maintainers decided to switch from MySQL to SQLite. All data contained in the MySQL database is not affected by this switch but you need to start with a clean SQLite database to ensure nginx-naxsi-ui reliability. -- Cyril Lavier Wed, 5 Jun 2013 09:45:03 +0200 nginx (0.8.53-1) unstable; urgency=low As stated by upstream, the 0.7.x branch is consedered legacy and 0.8.x will be the new stable branch. For this reason, the nginx maintainers decided to upload 0.8.53 to unstable. -- Kartik Mistry Fri, 26 Nov 2010 19:42:09 +0530 nginx (0.7.59-1) unstable; urgency=low As stated by upstream, the 0.6.x branch is consedered legacy and 0.7.x will be the new stable branch. For this reason, the nginx maintainers decided to upload 0.7.59 to unstable. Should you get the following error while starting nginx: could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32 Please add the following parameter to your nginx.conf: server_names_hash_bucket_size 100; Where 100 is the size of your server names hash bucket. For more information about this option, please read the following resources: http://wiki.nginx.org/NginxHttpCoreModule#server_names_hash_bucket_size http://thread.gmane.org/gmane.comp.web.nginx.english/820/focus=821 http://thread.gmane.org/gmane.comp.web.nginx.english/985/focus=989 -- Fabio Tranchitella Sun, 31 May 2009 18:30:10 +0200 nginx (0.6.30-2) unstable; urgency=low As of May 4th., nginx 0.5.x branch is considered legacy and 0.6.x will be the new stable branch. The announcement was made by Igor Sysoev when releasing the last 0.5.x version, nginx 0.5.36. Debian, the universal operating system, has provided binary packages for both 0.5 and 0.6 branches in unstable and experimental, and will now offer only 0.6 packages in the unstable distribution, starting with the 0.6.30-1 package. In the future, Debian will also provide experimental packages for the next testing branch of nginx, at the moment upstream announces it. Should you have any problem with nginx in Debian, please file a bug in the Debian Bug Tracking System. -- Fabio Tranchitella Mon, 12 May 2008 14:24:53 +0200 debian/watch0000664000000000000000000000014312705233614010222 0ustar version=3 opts=pgpsigurlmangle=s/$/.asc/ \ http://nginx.org/download/nginx-(\d\.\d+\.\d+)\.tar\.gz debian/nginx-core.prerm0000664000000000000000000000050412705233614012312 0ustar #!/bin/sh set -e case "$1" in remove|remove-in-favour|deconfigure|deconfigure-in-favour) if [ -x /etc/init.d/nginx ]; then invoke-rc.d nginx stop || exit $? fi ;; upgrade|failed-upgrade) ;; *) echo "prerm called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 debian/nginx-common.nginx.default0000664000000000000000000000060512705233614014275 0ustar # Note: You may want to look at the following page before setting the ULIMIT. # http://wiki.nginx.org/CoreModule#worker_rlimit_nofile # Set the ulimit variable if you need defaults to change. # Example: ULIMIT="-n 4096" #ULIMIT="-n 4096" # Define the stop schedule for nginx # see the start-stop-daemon --retry documentation for more information # #STOP_SCHEDULE="QUIT/5/TERM/5/KILL/5" debian/control0000664000000000000000000002531012705233650010577 0ustar Source: nginx Section: httpd Priority: optional Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Kartik Mistry Uploaders: Jose Parrella , Fabio Tranchitella , Michael Lustfield , Dmitry E. Oboukhov , Cyril Lavier , Christos Trochalakis Build-Depends: autotools-dev, debhelper (>= 9), dh-systemd (>= 1.5), dpkg-dev (>= 1.15.5), libexpat-dev, libgd-dev, libgeoip-dev, libluajit-5.1-dev [i386 amd64 kfreebsd-i386 armel armhf powerpc powerpcspe mips mipsel] | liblua5.1-0-dev, libmhash-dev, libpam0g-dev, libpcre3-dev, libperl-dev, libssl-dev, libxslt1-dev, po-debconf, zlib1g-dev Standards-Version: 3.9.6.0 Homepage: http://nginx.net Vcs-Git: git://anonscm.debian.org/collab-maint/nginx.git Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/nginx.git;a=summary Package: nginx Architecture: all Depends: nginx-core (>= ${source:Version}) | nginx-full (>= ${source:Version}) | nginx-light (>= ${source:Version}) | nginx-extras (>= ${source:Version}) , nginx-core (<< ${source:Version}.1~) | nginx-full (<< ${source:Version}.1~) | nginx-light (<< ${source:Version}.1~) | nginx-extras (<< ${source:Version}.1~) , ${misc:Depends} Description: small, powerful, scalable web/proxy server Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This is a dependency package to install either nginx-core (by default), nginx-full, nginx-light, or nginx-extras. Package: nginx-doc Architecture: all Section: doc Depends: lsb-base (>= 3.2-14), ${misc:Depends} Description: small, powerful, scalable web/proxy server - documentation Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides extra documentation to help unleash the power of Nginx. Package: nginx-common Architecture: all Depends: lsb-base (>= 3.2-14), ${misc:Depends} Replaces: nginx (<< 0.8.54-4), nginx-extras (<< 0.8.54-4), nginx-full (<< 0.8.54-4), nginx-light (<< 0.8.54-4) Breaks: nginx (<< 0.8.54-4), nginx-extras (<< 0.8.54-4), nginx-full (<< 0.8.54-4), nginx-light (<< 0.8.54-4) Suggests: fcgiwrap, nginx-doc, ssl-cert Description: small, powerful, scalable web/proxy server - common files Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package contains base configuration files used by all versions of nginx. Package: nginx-core Architecture: any Depends: nginx-common (= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx Conflicts: nginx-extras, nginx-light, nginx-full Suggests: nginx-doc (= ${source:Version}) Description: nginx web/proxy server (core version) Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides a version of nginx with the complete set of standard modules included (but omitting some of those included in nginx-extras). . STANDARD HTTP MODULES: Core, Access, Auth Basic, Auto Index, Browser, Empty GIF, FastCGI, Geo, Limit Connections, Limit Requests, Map, Memcached, Proxy, Referer, Rewrite, SCGI, Split Clients, UWSGI. . OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, GeoIP, Gunzip, Gzip, Gzip Precompression, Headers, HTTP/2, Image Filter, Index, Log, Real IP, SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. . NOTE: This is identical to the -full build, but without any third party modules built in. Package: nginx-core-dbg Architecture: any Section: debug Priority: extra Depends: nginx-core (= ${binary:Version}), ${misc:Depends} Conflicts: nginx-extras-dbg, nginx-light-dbg, nginx-full-dbg Description: nginx web/proxy server (core version) - debugging symbols Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides debugging symbols for nginx-core, to assist in debugging issues that you may find. It should not be required for normal operation. Package: nginx-full Architecture: any Depends: nginx-common (= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx Conflicts: nginx-extras, nginx-light, nginx-core Suggests: nginx-doc (= ${source:Version}) Description: nginx web/proxy server (standard version) Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides a version of nginx with the complete set of standard modules included (but omitting some of those included in nginx-extra). . STANDARD HTTP MODULES: Core, Access, Auth Basic, Auto Index, Browser, Empty GIF, FastCGI, Geo, Limit Connections, Limit Requests, Map, Memcached, Proxy, Referer, Rewrite, SCGI, Split Clients, UWSGI. . OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, GeoIP, Gunzip, Gzip, Gzip Precompression, Headers, HTTP/2, Image Filter, Index, Log, Real IP, SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. . THIRD PARTY MODULES: Auth PAM, DAV Ext, Echo, HTTP Substitutions, Upstream Fair Queue. Package: nginx-full-dbg Architecture: any Section: debug Priority: extra Depends: nginx-full (= ${binary:Version}), ${misc:Depends} Conflicts: nginx-extras-dbg, nginx-light-dbg, nginx-core-dbg Description: nginx web/proxy server (standard version) - debugging symbols Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides debugging symbols for nginx-full, to assist in debugging issues that you may find. It should not be required for normal operation. Package: nginx-light Architecture: any Priority: extra Depends: nginx-common (= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx Conflicts: nginx-extras, nginx-full, nginx-core Suggests: nginx-doc (= ${source:Version}) Description: nginx web/proxy server (basic version) Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides a very light version of nginx with only the minimal set of features and modules. . STANDARD HTTP MODULES: Core, Access, Auth Basic, Auto Index, Empty GIF, FastCGI, Map, Proxy, Rewrite. . OPTIONAL HTTP MODULES: Auth Request, Charset, Gzip, Gzip Precompression, Headers, Index, Log, Real IP, SSL, Stub Status, Upstream. . THIRD PARTY MODULES: Echo. Package: nginx-light-dbg Architecture: any Section: debug Priority: extra Depends: nginx-light (= ${binary:Version}), ${misc:Depends} Conflicts: nginx-extras-dbg, nginx-full-dbg, nginx-core-dbg Description: nginx web/proxy server (basic version) - debugging symbols Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides debugging symbols for nginx-light, to assist in debugging issues that you may find. It should not be required for normal operation. Package: nginx-extras Architecture: any Priority: extra Depends: nginx-common (= ${source:Version}), ${misc:Depends}, ${perl:Depends}, ${shlibs:Depends} Breaks: nginx (<< 1.4.5-1) Provides: httpd, httpd-cgi, nginx Conflicts: nginx-full, nginx-light, nginx-core Suggests: nginx-doc (= ${source:Version}) Description: nginx web/proxy server (extended version) Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides a version of nginx with the standard modules, plus extra features and modules such as the Perl module, which allows the addition of Perl in configuration files. . STANDARD HTTP MODULES: Core, Access, Auth Basic, Auto Index, Browser, Empty GIF, FastCGI, Geo, Limit Connections, Limit Requests, Map, Memcached, Proxy, Referer, Rewrite, SCGI, Split Clients, UWSGI. . OPTIONAL HTTP MODULES: Addition, Auth Request, Charset, WebDAV, FLV, GeoIP, Gunzip, Gzip, Gzip Precompression, Headers, HTTP/2, Image Filter, Index, Log, MP4, Embedded Perl, Random Index, Real IP, Secure Link, SSI, SSL, Stream, Stub Status, Substitution, Thread Pool, Upstream, User ID, XSLT. . MAIL MODULES: Mail Core, Auth HTTP, Proxy, SSL, IMAP, POP3, SMTP. . THIRD PARTY MODULES: Auth PAM, Cache Purge, DAV Ext, Echo, Fancy Index, Headers More, Embedded Lua, HTTP Push, HTTP Substitutions, Upload Progress, Upstream Fair Queue. Package: nginx-extras-dbg Architecture: any Section: debug Priority: extra Depends: nginx-extras (= ${binary:Version}), ${misc:Depends} Conflicts: nginx-full-dbg, nginx-light-dbg, nginx-core-dbg Description: nginx web/proxy server (extended version) - debugging symbols Nginx ("engine X") is a high-performance web and reverse proxy server created by Igor Sysoev. It can be used both as a standalone web server and as a proxy to reduce the load on back-end HTTP or mail servers. . This package provides debugging symbols for nginx-extras, to assist in debugging issues that you may find. It should not be required for normal operation. debian/gbp.conf0000664000000000000000000000003712705233614010612 0ustar [DEFAULT] pristine-tar = True debian/nginx-full.install0000664000000000000000000000004612705233614012646 0ustar debian/build-full/objs/nginx usr/sbin debian/conf/0000775000000000000000000000000012705233614010120 5ustar debian/conf/mime.types0000664000000000000000000000756512705233614012152 0ustar types { text/html html htm shtml; text/css css; text/xml xml; image/gif gif; image/jpeg jpeg jpg; application/javascript js; application/atom+xml atom; application/rss+xml rss; text/mathml mml; text/plain txt; text/vnd.sun.j2me.app-descriptor jad; text/vnd.wap.wml wml; text/x-component htc; image/png png; image/tiff tif tiff; image/vnd.wap.wbmp wbmp; image/x-icon ico; image/x-jng jng; image/x-ms-bmp bmp; image/svg+xml svg svgz; image/webp webp; application/font-woff woff; application/java-archive jar war ear; application/json json; application/mac-binhex40 hqx; application/msword doc; application/pdf pdf; application/postscript ps eps ai; application/rtf rtf; application/vnd.apple.mpegurl m3u8; application/vnd.ms-excel xls; application/vnd.ms-fontobject eot; application/vnd.ms-powerpoint ppt; application/vnd.wap.wmlc wmlc; application/vnd.google-earth.kml+xml kml; application/vnd.google-earth.kmz kmz; application/x-7z-compressed 7z; application/x-cocoa cco; application/x-java-archive-diff jardiff; application/x-java-jnlp-file jnlp; application/x-makeself run; application/x-perl pl pm; application/x-pilot prc pdb; application/x-rar-compressed rar; application/x-redhat-package-manager rpm; application/x-sea sea; application/x-shockwave-flash swf; application/x-stuffit sit; application/x-tcl tcl tk; application/x-x509-ca-cert der pem crt; application/x-xpinstall xpi; application/xhtml+xml xhtml; application/xspf+xml xspf; application/zip zip; application/octet-stream bin exe dll; application/octet-stream deb; application/octet-stream dmg; application/octet-stream iso img; application/octet-stream msi msp msm; application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; audio/midi mid midi kar; audio/mpeg mp3; audio/ogg ogg; audio/x-m4a m4a; audio/x-realaudio ra; video/3gpp 3gpp 3gp; video/mp2t ts; video/mp4 mp4; video/mpeg mpeg mpg; video/quicktime mov; video/webm webm; video/x-flv flv; video/x-m4v m4v; video/x-mng mng; video/x-ms-asf asx asf; video/x-ms-wmv wmv; video/x-msvideo avi; } debian/conf/koi-win0000664000000000000000000000425712705233614011430 0ustar charset_map koi8-r windows-1251 { 80 88 ; # euro 95 95 ; # bullet 9A A0 ; #   9E B7 ; # · A3 B8 ; # small yo A4 BA ; # small Ukrainian ye A6 B3 ; # small Ukrainian i A7 BF ; # small Ukrainian yi AD B4 ; # small Ukrainian soft g AE A2 ; # small Byelorussian short u B0 B0 ; # ° B3 A8 ; # capital YO B4 AA ; # capital Ukrainian YE B6 B2 ; # capital Ukrainian I B7 AF ; # capital Ukrainian YI B9 B9 ; # numero sign BD A5 ; # capital Ukrainian soft G BE A1 ; # capital Byelorussian short U BF A9 ; # (C) C0 FE ; # small yu C1 E0 ; # small a C2 E1 ; # small b C3 F6 ; # small ts C4 E4 ; # small d C5 E5 ; # small ye C6 F4 ; # small f C7 E3 ; # small g C8 F5 ; # small kh C9 E8 ; # small i CA E9 ; # small j CB EA ; # small k CC EB ; # small l CD EC ; # small m CE ED ; # small n CF EE ; # small o D0 EF ; # small p D1 FF ; # small ya D2 F0 ; # small r D3 F1 ; # small s D4 F2 ; # small t D5 F3 ; # small u D6 E6 ; # small zh D7 E2 ; # small v D8 FC ; # small soft sign D9 FB ; # small y DA E7 ; # small z DB F8 ; # small sh DC FD ; # small e DD F9 ; # small shch DE F7 ; # small ch DF FA ; # small hard sign E0 DE ; # capital YU E1 C0 ; # capital A E2 C1 ; # capital B E3 D6 ; # capital TS E4 C4 ; # capital D E5 C5 ; # capital YE E6 D4 ; # capital F E7 C3 ; # capital G E8 D5 ; # capital KH E9 C8 ; # capital I EA C9 ; # capital J EB CA ; # capital K EC CB ; # capital L ED CC ; # capital M EE CD ; # capital N EF CE ; # capital O F0 CF ; # capital P F1 DF ; # capital YA F2 D0 ; # capital R F3 D1 ; # capital S F4 D2 ; # capital T F5 D3 ; # capital U F6 C6 ; # capital ZH F7 C2 ; # capital V F8 DC ; # capital soft sign F9 DB ; # capital Y FA C7 ; # capital Z FB D8 ; # capital SH FC DD ; # capital E FD D9 ; # capital SHCH FE D7 ; # capital CH FF DA ; # capital hard sign } debian/conf/uwsgi_params0000664000000000000000000000123012705233614012540 0ustar uwsgi_param QUERY_STRING $query_string; uwsgi_param REQUEST_METHOD $request_method; uwsgi_param CONTENT_TYPE $content_type; uwsgi_param CONTENT_LENGTH $content_length; uwsgi_param REQUEST_URI $request_uri; uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; uwsgi_param REQUEST_SCHEME $scheme; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; uwsgi_param REMOTE_PORT $remote_port; uwsgi_param SERVER_PORT $server_port; uwsgi_param SERVER_NAME $server_name; debian/conf/koi-utf0000664000000000000000000000542512705233614011427 0ustar # This map is not a full koi8-r <> utf8 map: it does not contain # box-drawing and some other characters. Besides this map contains # several koi8-u and Byelorussian letters which are not in koi8-r. # If you need a full and standard map, use contrib/unicode2nginx/koi-utf # map instead. charset_map koi8-r utf-8 { 80 E282AC ; # euro 95 E280A2 ; # bullet 9A C2A0 ; #   9E C2B7 ; # · A3 D191 ; # small yo A4 D194 ; # small Ukrainian ye A6 D196 ; # small Ukrainian i A7 D197 ; # small Ukrainian yi AD D291 ; # small Ukrainian soft g AE D19E ; # small Byelorussian short u B0 C2B0 ; # ° B3 D081 ; # capital YO B4 D084 ; # capital Ukrainian YE B6 D086 ; # capital Ukrainian I B7 D087 ; # capital Ukrainian YI B9 E28496 ; # numero sign BD D290 ; # capital Ukrainian soft G BE D18E ; # capital Byelorussian short U BF C2A9 ; # (C) C0 D18E ; # small yu C1 D0B0 ; # small a C2 D0B1 ; # small b C3 D186 ; # small ts C4 D0B4 ; # small d C5 D0B5 ; # small ye C6 D184 ; # small f C7 D0B3 ; # small g C8 D185 ; # small kh C9 D0B8 ; # small i CA D0B9 ; # small j CB D0BA ; # small k CC D0BB ; # small l CD D0BC ; # small m CE D0BD ; # small n CF D0BE ; # small o D0 D0BF ; # small p D1 D18F ; # small ya D2 D180 ; # small r D3 D181 ; # small s D4 D182 ; # small t D5 D183 ; # small u D6 D0B6 ; # small zh D7 D0B2 ; # small v D8 D18C ; # small soft sign D9 D18B ; # small y DA D0B7 ; # small z DB D188 ; # small sh DC D18D ; # small e DD D189 ; # small shch DE D187 ; # small ch DF D18A ; # small hard sign E0 D0AE ; # capital YU E1 D090 ; # capital A E2 D091 ; # capital B E3 D0A6 ; # capital TS E4 D094 ; # capital D E5 D095 ; # capital YE E6 D0A4 ; # capital F E7 D093 ; # capital G E8 D0A5 ; # capital KH E9 D098 ; # capital I EA D099 ; # capital J EB D09A ; # capital K EC D09B ; # capital L ED D09C ; # capital M EE D09D ; # capital N EF D09E ; # capital O F0 D09F ; # capital P F1 D0AF ; # capital YA F2 D0A0 ; # capital R F3 D0A1 ; # capital S F4 D0A2 ; # capital T F5 D0A3 ; # capital U F6 D096 ; # capital ZH F7 D092 ; # capital V F8 D0AC ; # capital soft sign F9 D0AB ; # capital Y FA D097 ; # capital Z FB D0A8 ; # capital SH FC D0AD ; # capital E FD D0A9 ; # capital SHCH FE D0A7 ; # capital CH FF D0AA ; # capital hard sign } debian/conf/win-utf0000664000000000000000000000577712705233614011454 0ustar # This map is not a full windows-1251 <> utf8 map: it does not # contain Serbian and Macedonian letters. If you need a full map, # use contrib/unicode2nginx/win-utf map instead. charset_map windows-1251 utf-8 { 82 E2809A; # single low-9 quotation mark 84 E2809E; # double low-9 quotation mark 85 E280A6; # ellipsis 86 E280A0; # dagger 87 E280A1; # double dagger 88 E282AC; # euro 89 E280B0; # per mille 91 E28098; # left single quotation mark 92 E28099; # right single quotation mark 93 E2809C; # left double quotation mark 94 E2809D; # right double quotation mark 95 E280A2; # bullet 96 E28093; # en dash 97 E28094; # em dash 99 E284A2; # trade mark sign A0 C2A0; #   A1 D18E; # capital Byelorussian short U A2 D19E; # small Byelorussian short u A4 C2A4; # currency sign A5 D290; # capital Ukrainian soft G A6 C2A6; # borken bar A7 C2A7; # section sign A8 D081; # capital YO A9 C2A9; # (C) AA D084; # capital Ukrainian YE AB C2AB; # left-pointing double angle quotation mark AC C2AC; # not sign AD C2AD; # soft hypen AE C2AE; # (R) AF D087; # capital Ukrainian YI B0 C2B0; # ° B1 C2B1; # plus-minus sign B2 D086; # capital Ukrainian I B3 D196; # small Ukrainian i B4 D291; # small Ukrainian soft g B5 C2B5; # micro sign B6 C2B6; # pilcrow sign B7 C2B7; # · B8 D191; # small yo B9 E28496; # numero sign BA D194; # small Ukrainian ye BB C2BB; # right-pointing double angle quotation mark BF D197; # small Ukrainian yi C0 D090; # capital A C1 D091; # capital B C2 D092; # capital V C3 D093; # capital G C4 D094; # capital D C5 D095; # capital YE C6 D096; # capital ZH C7 D097; # capital Z C8 D098; # capital I C9 D099; # capital J CA D09A; # capital K CB D09B; # capital L CC D09C; # capital M CD D09D; # capital N CE D09E; # capital O CF D09F; # capital P D0 D0A0; # capital R D1 D0A1; # capital S D2 D0A2; # capital T D3 D0A3; # capital U D4 D0A4; # capital F D5 D0A5; # capital KH D6 D0A6; # capital TS D7 D0A7; # capital CH D8 D0A8; # capital SH D9 D0A9; # capital SHCH DA D0AA; # capital hard sign DB D0AB; # capital Y DC D0AC; # capital soft sign DD D0AD; # capital E DE D0AE; # capital YU DF D0AF; # capital YA E0 D0B0; # small a E1 D0B1; # small b E2 D0B2; # small v E3 D0B3; # small g E4 D0B4; # small d E5 D0B5; # small ye E6 D0B6; # small zh E7 D0B7; # small z E8 D0B8; # small i E9 D0B9; # small j EA D0BA; # small k EB D0BB; # small l EC D0BC; # small m ED D0BD; # small n EE D0BE; # small o EF D0BF; # small p F0 D180; # small r F1 D181; # small s F2 D182; # small t F3 D183; # small u F4 D184; # small f F5 D185; # small kh F6 D186; # small ts F7 D187; # small ch F8 D188; # small sh F9 D189; # small shch FA D18A; # small hard sign FB D18B; # small y FC D18C; # small soft sign FD D18D; # small e FE D18E; # small yu FF D18F; # small ya } debian/conf/nginx.conf0000664000000000000000000000266612705233614012124 0ustar user www-data; worker_processes auto; pid /run/nginx.pid; events { worker_connections 768; # multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } #mail { # # See sample authentication script at: # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript # # # auth_http localhost/auth.php; # # pop3_capabilities "TOP" "USER"; # # imap_capabilities "IMAP4rev1" "UIDPLUS"; # # server { # listen localhost:110; # protocol pop3; # proxy on; # } # # server { # listen localhost:143; # protocol imap; # proxy on; # } #} debian/conf/fastcgi_params0000664000000000000000000000175712705233614013040 0ustar fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200; debian/conf/proxy_params0000664000000000000000000000026412705233614012571 0ustar proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; debian/conf/scgi_params0000664000000000000000000000117412705233614012336 0ustar scgi_param REQUEST_METHOD $request_method; scgi_param REQUEST_URI $request_uri; scgi_param QUERY_STRING $query_string; scgi_param CONTENT_TYPE $content_type; scgi_param DOCUMENT_URI $document_uri; scgi_param DOCUMENT_ROOT $document_root; scgi_param SCGI 1; scgi_param SERVER_PROTOCOL $server_protocol; scgi_param REQUEST_SCHEME $scheme; scgi_param HTTPS $https if_not_empty; scgi_param REMOTE_ADDR $remote_addr; scgi_param REMOTE_PORT $remote_port; scgi_param SERVER_PORT $server_port; scgi_param SERVER_NAME $server_name; debian/conf/snippets/0000775000000000000000000000000012705233614011765 5ustar debian/conf/snippets/snakeoil.conf0000664000000000000000000000033112705233614014436 0ustar # Self signed certificates generated by the ssl-cert package # Don't use them in a production server! ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; debian/conf/snippets/fastcgi-php.conf0000664000000000000000000000064612705233614015047 0ustar # regex to split $uri to $fastcgi_script_name and $fastcgi_path fastcgi_split_path_info ^(.+\.php)(/.+)$; # Check that the PHP script exists before passing it try_files $fastcgi_script_name =404; # Bypass the fact that try_files resets $fastcgi_path_info # see: http://trac.nginx.org/nginx/ticket/321 set $path_info $fastcgi_path_info; fastcgi_param PATH_INFO $path_info; fastcgi_index index.php; include fastcgi.conf; debian/conf/sites-available/0000775000000000000000000000000012705233614013165 5ustar debian/conf/sites-available/default0000664000000000000000000000403212705233614014533 0ustar ## # You should look at the following URL's in order to grasp a solid understanding # of Nginx configuration files in order to fully unleash the power of Nginx. # http://wiki.nginx.org/Pitfalls # http://wiki.nginx.org/QuickStart # http://wiki.nginx.org/Configuration # # Generally, you will want to move this file somewhere, and start with a clean # file but keep this around for reference. Or just disable in sites-enabled. # # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. ## # Default server configuration # server { listen 80 default_server; listen [::]:80 default_server; # SSL configuration # # listen 443 ssl default_server; # listen [::]:443 ssl default_server; # # Note: You should disable gzip for SSL traffic. # See: https://bugs.debian.org/773332 # # Read up on ssl_ciphers to ensure a secure configuration. # See: https://bugs.debian.org/765782 # # Self signed certs generated by the ssl-cert package # Don't use them in a production server! # # include snippets/snakeoil.conf; root /var/www/html; # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; server_name _; location / { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # include snippets/fastcgi-php.conf; # # # With php7.0-cgi alone: # fastcgi_pass 127.0.0.1:9000; # # With php7.0-fpm: # fastcgi_pass unix:/run/php/php7.0-fpm.sock; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # Virtual Host configuration for example.com # # You can move that to a different file under sites-available/ and symlink that # to sites-enabled/ to enable it. # #server { # listen 80; # listen [::]:80; # # server_name example.com; # # root /var/www/example.com; # index index.html; # # location / { # try_files $uri $uri/ =404; # } #} debian/conf/fastcgi.conf0000664000000000000000000000206512705233614012412 0ustar fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param REQUEST_SCHEME $scheme; fastcgi_param HTTPS $https if_not_empty; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200; debian/nginx-doc.examples0000664000000000000000000000002712705233614012620 0ustar debian/help/examples/* debian/modules/0000775000000000000000000000000012705233614010643 5ustar debian/modules/nginx-http-push/0000775000000000000000000000000012705233614013720 5ustar debian/modules/nginx-http-push/protocol.txt0000664000000000000000000001771112705233614016331 0ustar Basic HTTP Push Relay Protocol Rev. 2.23 1. Introduction 1.1. Purpose The primary purpose of this protocol is to enable a method of long-polling, transparent to the web client, where client connections idle only on the HTTP server and need not be forwarded. 1.2. Requirements The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC2119. An implementation is not compliant if it fails to satisfy one or more of the MUST or REQUIRED level requirements for the protocols it implements. An implementation that satisfies all the MUST or REQUIRED level and all the SHOULD level requirements for its protocols is said to be "unconditionally compliant"; one that satisfies all the MUST level requirements but not all the SHOULD level requirements for its protocols is said to be "conditionally compliant." 1.3. Terminology This specification uses a number of terms to refer to the roles played by participants in, and objects of, this protocol: server The HTTP server implementing this protocol. client A program that initiates TCP/IP connections with the HTTP server for the purpose of sending HTTP requests. message Application specific data, usually enclosed in a request or response body. channel A resource representing an isolated pathway for message transmission. Each channel has a single unique message queue. subscriber A client that sends HTTP requests to the server for the purposes of receiving messages via some channel. publisher A client that sends HTTP requests to the server in order to transmit messages to subscribers via a channel. channel id A unique identifier for a channel. location A url (or set of urls) on the server. 2. Requirements 2.1. Server Requirements The HTTP server MUST have a mechanism of specifying a url, or a set of urls as publisher and subscriber locations. All requests to the publisher location MUST be treated as publisher requests, all to the subscriber location as subscriber requests. The server MUST implement a mechanism for identifying channels with unique ids. This MAY, for example, be a url parameter (/foo/?id=123) or a cookie. Methods of channel identification other than those using the url MAY be used, but are strongly discouraged. The server MUST accept requests on publisher locations and respond to them immediately. It MUST also accept requests on subscriber locations, but need not respond immediately. 2.2. Client Requirements All clients must prodice valid HTTP requests. Subscriber clients must have a caching mechanism that appropriately reacts to Last-Modified and Etag response headers (web browsers, for example). 2.3. The Channel ID It is not the responsibility of the server to generate IDs. 3. Server Operation A publisher request functions as notification to the server of a message to send to some subscribers over some channel. A subscriber request notifies the server of the subscriber's intent to receive a message. 3.1. The Subscriber The server MUST accept all valid HTTP GET requests to the subscriber location. All other request methods SHOULD be responded to with a 405 Method Not Allowed status code. Subscriber requests are considered notifications of intent to receive some message. Subscribers may request existing messages, messages that are not yet available, and messages that are no longer available. The requested message is identified using the If-Modified-Since and If-None-Match request headers. A request with no If-Modified-Since header MUST be assumed to be requesting the oldest available message in a channel. Each 200 OK response containing a message MUST have its Last-Modified and Etag headers set so that a request using those headers will be interpreted as a request for the next available message. Additionally, said 200 OK MUST contain the Content-Type header of the message publisher request, unless no Content-Type header had been provided or it is explicitly overridden by server configuration. There are several common mechanisms for performing an HTTP server push. The rest of the behavior of the server in response to a subscriber request SHOULD be configurable and MUST be selected from the following list of mechanisms: Long-Polling Requests for existing messages will be responded to immediately; responses to requests for messages not yet available MUST be delayed until the message becomes available. Delayed responses MUST satisfy all of the following conditions: + A 200 OK response containing the message (and its Content-Type) MUST be sent immediately after the message becomes available. The entire response must be indistinguishable from a response to a request for an existing message. + If the channel the subscriber is waiting on is deleted or for some reason becomes unavailable, the server MUST immediately send a 410 Gone response. + If another subscriber has conflicted with this request, the server MUST immediately send a 409 Conflict response. Interval-Polling All requests will be responded to immediately. Requests for messages not yet available MUST produce a 304 Not Modified response code. In addition, when the server receives more than one concurrent subscriber request on the same channel, it MUST do one of the following: Broadcast No additional actions are performed Last-in, first-out All but the most recent long-held subscriber request on the channel are sent a 409 Conflict response. First-in, last-out All but the oldest request will be sent a 409 Conflict The server SHOULD make this selection configurable, and MUST default to broadcast behavior. 3.2. The Publisher The server MUST accept all valid HTTP requests to the publisher location. The server, when sent a publisher request, MUST satisfy all of the following conditions: * GET requests receive a 200 OK response for existing channels and a 404 Not Found otherwise. * PUT requests receive a 200 OK response. The request creates a channel if no channel with the given channel id exists. * DELETE requests receive a 200 OK if the channel identified by the channel id exists and has been completely deleted. All subscribers MUST have been sent a 410 Gone response. Requests for nonexistent channels MUST be responded to with a 404 Not Found. * POST requests are used to send messages. The request MAY contain a body in any encoding representing a message to be sent over the channel. The message MUST be immediately delivered to all currently long-held subscriber requests. Additionally, the message MAY be stored for future retrieval and the oldest message stored for the channel MAY be deleted. A POST request MUST be replied to with a 201 Created if there were any long-held subscribers that have been sent this message, and with a 202 Accepted otherwise. The Content-Type header of the request MUST be forwarded with the message. Message storage limits SHOULD be configurable. publisher locations SHOULD be configurable to allow foregoing message storage on POST requests. All 200-level responses MUST, in the response body, contain information about the applicable channel. This information MAY contain the number of stored messages and the number of subscribers' requests being long-held prior to this request. The server MAY implement a content-negotiation scheme for this information. debian/modules/nginx-http-push/README0000664000000000000000000002066312705233614014607 0ustar NGiNX HTTP push module - Turn NGiNX into an adept HTTP Push (Comet) server. This module takes care of all the connection juggling, and exposes a simple interface to broadcast messages to clients via plain old HTTP requests. This makes it possible to write live-updating applications without having to wait on idle connections via upstream proxies or making your code all asynchronous and concurrent. ---------------- Configuration Directives & Variables ------------------------ Variables: $push_channel_id A token uniquely identifying a communication channel. Must be present in the context of the push_subscriber and push_publisher directives. Example: set $push_channel_id $arg_id; #channel id is now the url query string parameter "id" #(/foo/bar?id=channel_id_string) Directives: ==Publisher/Subscriber== push_subscriber [ long-poll | interval-poll ] default: long-poll context: server, location Defines a server or location as a subscriber. This location represents a subscriber's interface to a channel's message queue. The queue is traversed automatically via caching information request headers (If-Modified-Since and If-None-Match), beginning with the oldest available message. Requests for upcoming messages are handled in accordance with the setting provided. See the protocol documentation for a detailed description. push_subscriber_concurrency [ last | first | broadcast ] default: broadcast context: http, server, location Controls how multiple subscriber requests to a channel (identified by some common ID) are handled. The values work as follows: - broadcast: any number of concurrent subscriber requests may be held. - last: only the most recent subscriber request is kept, all others get a 409 Conflict response. - first: only the oldest subscriber request is kept, all others get a 409 Conflict response. push_publisher default: none context: server, location Defines a server or location as a message publisher. Requests to a publisher location are treated as messages to be sent to subscribers. See the protocol documentation for a detailed description. == Message storage == push_store_messages [ on | off ] default: on context: http, server, location Whether or not message queuing is enabled. "Off" is equivalent to the setting push_channel_buffer_length 0; push_max_reserved_memory [ size ] default: 32M context: http The size of the memory chunk this module will use for all message queuing and buffering. push_min_message_buffer_length [ number ] default: 1 context: http, server, location The minimum number of messages to store per channel. A channel's message buffer will retain at least this many most recent messages. push_max_message_buffer_length [ number ] default: 10 context: http, server, location The maximum number of messages to store per channel. A channel's message buffer will retain at most this many most recent messages. push_message_buffer_length [ number ] default: none context: http, server, location The exact number of messages to store per channel. Sets both push_max_message_buffer_length and push_min_message_buffer_length to this value. push_delete_oldest_received_message [ on | off ] default: off context: http, server, location When enabled, as soon as the oldest message in a channel's message queue has been received by a subscriber, it is deleted -- provided there are more than push_min_message_buffer_length messages in the channel's message buffer. Recommend avoiding this directive as it violates subscribers' assumptions of GET request idempotence. push_message_timeout [ time ] default: 1h context: http, server, location The length of time a message may be queued before it is considered expired. If you do not want messages to expire, set this to 0. Applicable only if a push_publisher is present in this or a child context. push_subscriber_timeout [ time ] default: 0 context: http, server, location The length of time a subscriber's long-polling connection can last before it's timed out. If you don't want subscriber's connection to timeout, set this to 0. Applicable only if a push_subscriber is present in this or a child context. push_channel_timeout [ time ] default: 0 context: http, server, location The length of time a channel will be removed after it has no subscriber and no queued messages. If you want to remove a channel as soon as possible, set this to 0. Applicable only if a push_publisher or push_subscriber is present in this or a child context and push_subscriber_timeout is greater than 0. This value should be greater than push_subscriber_timeout to make sense. == Security == push_authorized_channels_only [ on | off ] default: off context: http, server, location Whether or not a subscriber may create a channel by making a request to a push_subscriber location. If set to on, a publisher must send a POST or PUT request before a subscriber can request messages on the channel. Otherwise, all subscriber requests to nonexistent channels will get a 403 Forbidden response. push_channel_group [ string ] default: (none) context: server, location Because settings are bound to locations and not individual channels, it is useful to be able to have channels that can be reached only from some locations and never others. That's where this setting comes in. Think of it as a prefix string for the channel id. push_max_channel_id_length [ number ] default: 512 context: main, server, location Maximum permissible channel id length (number of characters). Longer ids will be truncated. push_max_channel_subscribers [ number ] default: 0 (unlimited) context: main, server, location Maximum concurrent subscribers. Pretty self-explanatory. --------------------------- Example Config ----------------------------------- http { #maximum amount of memory the push module is allowed to use #for buffering and stuff push_max_reserved_memory 12M; #default is 3M # internal publish endpoint (keep it private / protected) location /publish { set $push_channel_id $arg_channel; #/?channel=239aff3 or some-such push_publisher; push_message_timeout 2h; # expire buffered messages after 2 hours push_max_message_buffer_length 10; # store absolutely at most 10 messages push_min_message_recipients 0; # minimum recipients before purge } # public long-polling endpoint location /activity { push_subscriber; # how multiple subscriber requests to the same channel id are handled # - last: only the most recent subscriber request is kept, 409 for others. # - first: only the oldest subscriber request is kept, 409 for others. # - broadcast: any number of subscriber requests may be long-polling. push_subscriber_concurrency broadcast; set $push_channel_id $arg_channel; #/?channel=239aff3 or some-such default_type text/plain; } } ---------------------------- Operation --------------------------------------- The following describes what is likely to be the most commonly desired setup: Assuming the example config given above, Clients will connect to http://example.com/activity?id=... and have the response delayed until a message is POSTed to http://example.com/publish?id=... Messages can be sent to clients that have not yet connected, i.e. they are queued. Upon sending a request to a push_publisher location, the message, contained in the publisher request body, will be sent to the channel identified by $push_channel_id and to all presently connected channel subscribers. If there are no subscribers waiting for a message at the time, the publisher will be sent to with a with a 202 Accepted response. Otherwise, a 201 Created response is sent. Additionally, the body of the publisher response will contain information about the channel (number of current subscribers, message queue length, etc). If you intend to have the publisher be a server-side application, it's a damn good idea to make sure the push_publisher location is not publicly accessible. Traversal through a channel's message buffer by a subscriber requires proper HTTP caching support from the subscriber client. Make sure it correctly sends Last-Modified and Etag headers. (All modern web browsers do this.) ----------------------- Protocol Spec -------------------------------------- This module is unconditionally (fully) compliant with the Basic HTTP Push Relay Protocol, Rev. 2.21, found in the file protocol.txt. debian/modules/nginx-http-push/changelog.txt0000664000000000000000000000635412705233614016420 0ustar fix: turning on gzip cleared Etag subscriber response header fix: channels incorrectly deleted when overwhelmed with connections feature: CORS support via OPTIONS request method response fix: file descriptor leak when restarting nginx via SIGHUP improve: concurrency for interprocess notifications refactor: completely encapsulated message store fix: slow memory leak introduced in 0.7 fix: memory leak when not using message buffer 0.712 (Mar. 21 2014) fix: intermittently dropped long-polling connections on internal redirects fix: unable to proxy long-polling subscribers. (thanks wandenberg and sanmai) 0.711 (Mar. 13 2014) fix: incompatibility with cache manager (proxy_cache and fastcgi_cache directives) 0.71 (Mar. 1 2014) fix: removed unused variables and functions to quiet down GCC 0.7: (Feb. 20 2014) fix: last-in concurrency setting wasn't working reliably refactor: partially separated message storage. add a test harness. fix: segfault from concurrency bug while garbage-collecting channels fix: some large messages got lost 0.692 (Feb. 3 2010) fix: error log reported failed close() for some publisher requests with large messages fix: occasional memory leak during message deletion fix: worker messages intended for dead worker processes were not deleted 0.691 (Feb. 2 2010) fix: server reload (via SIGHUP signal) was failing fix: segfault on messages longer than client_body_buffer_size (thanks wfelipe) change: removed push_min_message_recipients, added push_delete_oldest_received_message 0.69 (Nov. 17 2009) fix: publisher got a 201 Created response even if the channel had no subscribers at the time (should be 202 Accepted) fix: small memory leak after each message broadcast to a channel feature: optional push_max_channel_subscribers setting added fix: first-in concurrency setting wasn't responding to subscribers with a correct status code on conflict fix: reused subscriber connections sometimes failed to receive messages unfeature: no more nginx 0.6 support. not worth the hassle. 0.683 (Nov. 10 2009) change: default max. reserved memory size changed form 16MB to 32 MB change: unused node garbage collection made a little more aggressive (max. 3 unused channels per channel search instead of 1) fix: unused nodes were deleted only on channel id hash collision (very rare) fix: segmentation fault from allocating insufficient memory for interprocess messaging 0.681 (Nov. 6 2009) feature: added push_message_buffer_length setting, which sets push_message_max_buffer_length and push_message_min_buffer_length at once. fix: publisher channel info text/json response now uses double quotes instead of single. fix: interprocess messages were not removed from shared memory correctly, causing weird errors 0.68 (Nov. 5 2009) change: default push_subscriber_concurrency value is now "broadcast" fix: incorrect error messages for invalid push_pubscriber and push_subscriber_concurrency settings change: removed deprecated push_buffer_size and push_queue_messages settings feature: rudimentary content-type negotiation for publisher channel info response. support text/plain, text/json, text/yaml and application/xml (and mimetype equivalents) fix: publisher GET response has HTTP status 0 0.67beta (Nov. 4 2009) and older see git repository debian/modules/nginx-http-push/config0000664000000000000000000000135112705233614015110 0ustar ngx_feature="http_push_module" ngx_feature_name= ngx_feature_run=no ngx_feature_incs= ngx_feature_path= ngx_feature_libs= ngx_feature_test= ngx_addon_name=ngx_http_push_module HTTP_MODULES="$HTTP_MODULES ngx_http_push_module" CORE_INCS="$CORE_INCS \ $ngx_addon_dir/src" NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ ${ngx_addon_dir}/src/ngx_http_push_defs.c \ ${ngx_addon_dir}/src/store/rbtree_util.c \ ${ngx_addon_dir}/src/store/ngx_http_push_module_ipc.c \ ${ngx_addon_dir}/src/store/memory/store.c \ ${ngx_addon_dir}/src/store/ngx_rwlock.c \ ${ngx_addon_dir}/src/ngx_http_push_module.c \ " have=NGX_HTTP_HEADERS . auto/have . auto/feature CORE_LIBS="$CORE_LIBS $ngx_feature_libs" CORE_INCS="$CORE_INCS $ngx_feature_incs"debian/modules/nginx-http-push/tests/0000775000000000000000000000000012705233614015062 5ustar debian/modules/nginx-http-push/tests/sub.rb0000775000000000000000000000250512705233614016205 0ustar #!/usr/bin/ruby require 'securerandom' require_relative 'pubsub.rb' require "optparse" server= "localhost:8082" par=1 quit_msg='FIN' no_message=false max_wait=60 msg_count=0 opt=OptionParser.new do |opts| opts.on("-s", "--server SERVER (#{server})", "server and port."){|v| server=v} opts.on("-p", "--parallel NUM (#{par})", "number of parallel clients"){|v| par = v.to_i} opts.on("-t", "--timeout SEC (#{max_wait})", "Long-poll timeout"){|v| max_wait = v} opts.on("-q", "--quit STRING (#{quit_msg})", "Quit message"){|v| quit_msg = v} opts.on("-n", "--no-message", "Don't output retrieved message."){|v| no_message = true} opts.on("-v", "--verbose", "somewhat rather extraneously wordful output"){Typhoeus::Config.verbose=true} end opt.banner="Usage: sub.rb [options] url" opt.parse! url = "http://#{server}#{ARGV.last}" puts "Subscribing #{par} client#{par!=1 ? "s":""} to #{url}." puts "Timeout: #{max_wait}sec, quit msg: #{quit_msg}" sub = Subscriber.new url, par, timeout: max_wait, quit_message: quit_msg nomsgmessage="\r"*20 + "Received message #" sub.on_message do |msg| if no_message msg_count+=1 print nomsgmessage print msg_count else puts msg end end errors_shown=false sub.on_failure do |x,y| puts sub.errors.join "\r\n" unless errors_shown errors_shown=true false end sub.run sub.wait debian/modules/nginx-http-push/tests/test.rb0000775000000000000000000002527512705233614016404 0ustar #!/usr/bin/ruby require 'minitest' require 'minitest/reporters' Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new require "minitest/autorun" require 'securerandom' require_relative 'pubsub.rb' SERVER=ENV["PUSHMODULE_SERVER"] || "127.0.0.1" PORT=ENV["PUSHMODULE_PORT"] || "8082" #Typhoeus::Config.verbose = true def url(part="") part=part[1..-1] if part[0]=="/" "http://#{SERVER}:#{PORT}/#{part}" end puts "Server at #{url}" def pubsub(concurrent_clients=1, opt={}) urlpart=opt[:urlpart] || 'broadcast' timeout = opt[:timeout] sub_url=opt[:sub] || "sub/broadcast/" pub_url=opt[:pub] || "pub/" chan_id = opt[:channel] || SecureRandom.hex sub = Subscriber.new url("#{sub_url}#{chan_id}"), concurrent_clients, timeout: timeout, use_message_id: opt[:use_message_id], quit_message: 'FIN', gzip: opt[:gzip], retry_delay: opt[:retry_delay], client: opt[:client] pub = Publisher.new url("#{pub_url}#{chan_id}") return pub, sub end def verify(pub, sub, check_errors=true) assert sub.errors.empty?, "There were subscriber errors: \r\n#{sub.errors.join "\r\n"}" if check_errors ret, err = sub.messages.matches?(pub.messages) assert ret, err || "Messages don't match" sub.messages.each do |msg| assert_equal sub.concurrency, msg.times_seen, "Concurrent subscribers didn't all receive a message." end end class PubSubTest < Minitest::Test def setup Celluloid.boot end def test_interval_poll pub, sub=pubsub 1, client: :intervalpoll, quit_message: 'FIN', retry_delay:0.1 sub.run pub.post ["hello this", "is a thing"] sleep 1 pub.post ["oh now what", "is this even a thing?"] sleep 1 pub.post "FIN" sub.wait verify pub, sub sub.terminate end def test_channel_info require 'json' require 'nokogiri' require 'yaml' subs=20 chan=SecureRandom.hex pub, sub = pubsub(subs, channel: chan) pub.nofail=true pub.get assert_equal 404, pub.response_code pub.post ["hello", "what is this i don't even"] assert_equal 202, pub.response_code pub.get assert_equal 200, pub.response_code assert_match /last requested: \d+ sec/, pub.response_body pub.get "text/json" info_json=JSON.parse pub.response_body assert_equal 2, info_json["messages"] #assert_equal 0, info_json["requested"] assert_equal 0, info_json["subscribers"] sub.run sleep 0.2 pub.get "text/json" info_json=JSON.parse pub.response_body assert_equal 2, info_json["messages"] #assert_equal 0, info_json["requested"] assert_equal subs, info_json["subscribers"] pub.get "text/xml" ix = Nokogiri::XML pub.response_body assert_equal 2, ix.at_xpath('//messages').content.to_i #assert_equal 0, ix.at_xpath('//requested').content.to_i assert_equal subs, ix.at_xpath('//subscribers').content.to_i pub.get "text/yaml" yaml_resp1=pub.response_body pub.get "application/yaml" yaml_resp2=pub.response_body pub.get "application/x-yaml" yaml_resp3=pub.response_body yam=YAML.load pub.response_body assert_equal 2, yam["messages"] #assert_equal 0, yam["requested"] assert_equal subs, yam["subscribers"] assert_equal yaml_resp1, yaml_resp2 assert_equal yaml_resp2, yaml_resp3 pub.post "FIN" sub.wait pub.get "text/json" info_json=JSON.parse pub.response_body assert_equal 3, info_json["messages"] #assert_equal 0, info_json["requested"] assert_equal 0, info_json["subscribers"] sub.terminate end def test_message_delivery pub, sub = pubsub sub.run sleep 0.2 assert_equal 0, sub.messages.messages.count pub.post "hi there" assert_equal 201, pub.response_code sleep 0.2 assert_equal 1, sub.messages.messages.count pub.post "FIN" assert_equal 201, pub.response_code sleep 0.2 assert_equal 2, sub.messages.messages.count assert sub.messages.matches? pub.messages sub.terminate end def test_authorized_channels #must be published to before subscribing pub, sub = pubsub 5, timeout: 1, sub: "sub/authorized/" sub.on_failure { false } sub.run sub.wait assert_equal 5, sub.finished assert sub.match_errors(/code 40[34]/) sub.reset pub.post %w( fweep ) assert_match /20[12]/, pub.response_code.to_s sleep 0.1 sub.run sleep 0.1 pub.post ["fwoop", "FIN"] { assert_match /20[12]/, pub.response_code.to_s } sub.wait verify pub, sub sub.terminate end def test_deletion #delete active channel pub, sub = pubsub 5, timeout: 10 sub.on_failure { false } sub.run sleep 0.2 pub.delete sleep 0.2 assert_equal 200, pub.response_code sub.wait assert sub.match_errors(/code 410/), "Expected subscriber code 410: Gone, instead was \"#{sub.errors.first}\"" #delete channel with no subscribers pub, sub = pubsub 5, timeout: 1 pub.post "hello" assert_equal 202, pub.response_code pub.delete assert_equal 200, pub.response_code #delete nonexistent channel pub, sub = pubsub pub.nofail=true pub.delete assert_equal 404, pub.response_code end def test_no_message_buffer chan_id=SecureRandom.hex pub = Publisher.new url("/pub/nobuffer/#{chan_id}") sub=[] 40.times do sub.push Subscriber.new(url("/sub/broadcast/#{chan_id}"), 1, use_message_id: false, quit_message: 'FIN') end pub.post ["this message should not be delivered", "nor this one"] sub.each {|s| s.run} sleep 0.2 pub.post "received1" sleep 0.2 pub.post "received2" sleep 0.2 pub.post "FIN" sub.each {|s| s.wait} sub.each do |s| assert s.errors.empty?, "There were subscriber errors: \r\n#{s.errors.join "\r\n"}" ret, err = s.messages.matches? ["received1", "received2", "FIN"] assert ret, err || "Messages don't match" end end def test_channel_isolation rands= %w( foo bar baz bax qqqqqqqqqqqqqqqqqqq eleven andsoon andsoforth feh ) pub=[] sub=[] 10.times do |i| pub[i], sub[i]=pubsub 15 sub[i].run end pub.each do |p| rand(1..10).times do p.post rands.sample end end sleep 1 pub.each do |p| p.post 'FIN' end sub.each do |s| s.wait end pub.each_with_index do |p, i| verify p, sub[i] end sub.each {|s| s.terminate } end def test_broadcast(clients=400) pub, sub = pubsub clients pub.post "yeah okay" sub.run #celluloid async FTW sleep 0.5 pub.post ["hello there", "what is this", "it's nothing", "nothing at all really"] pub.post "FIN" sub.wait verify pub, sub sub.terminate end #def test_broadcast_for_3000 # test_broadcast 3000 #end def test_subscriber_concurrency chan=SecureRandom.hex pub_first = Publisher.new url("pub/first#{chan}") pub_last = Publisher.new url("pub/last#{chan}") sub_first, sub_last = [], [] { url("sub/first/first#{chan}") => sub_first, url("sub/last/last#{chan}") => sub_last }.each do |url, arr| 3.times do sub=Subscriber.new(url, 1, quit_message: 'FIN', timeout: 20) sub.on_failure do |resp, req| false end arr << sub end end sub_first.each {|s| s.run; sleep 0.1 } assert sub_first[0].no_errors? sub_first[1..2].each do |s| assert s.errors? assert s.match_errors(/code 409/) end sub_last.each {|s| s.run; sleep 0.1 } assert sub_last[2].no_errors? sub_last[0..1].each do |s| assert s.errors? assert s.match_errors(/code 40[49]/) end pub_first.post %w( foo bar FIN ) pub_last.post %w( foobar baz somethingelse FIN ) sub_first[0].wait sub_last[2].wait verify pub_first, sub_first[0] verify pub_last, sub_last[2] sub_first[1..2].each{ |s| assert s.messages.count == 0 } sub_last[0..1].each{ |s| assert s.messages.count == 0 } [sub_first, sub_last].each {|sub| sub.each{|s| s.terminate}} end def test_queueing pub, sub = pubsub 5 pub.post %w( what is this_thing andnow 555555555555555555555 eleven FIN ) sleep 0.3 sub.run sub.wait verify pub, sub sub.terminate end def test_long_message(kb=1) pub, sub = pubsub 10, timeout: 10 sub.run pub.post ["q" * kb * 1024, "FIN"] sub.wait verify pub, sub sub.terminate end def test_long_message_500kb test_long_message 500 end def test_long_message_700kb test_long_message 700 end def test_long_message_950kb test_long_message 950 end def test_message_length_range pub, sub = pubsub 2, timeout: 6 sub.run n=5 while n <= 10000 do pub.post "T" * n n=n*1.01 sleep 0.001 end pub.post "FIN" sub.wait verify pub, sub sub.terminate end def test_message_timeout pub, sub = pubsub 10, pub: "/pub/2_sec_message_timeout/", timeout: 4 pub.post %w( foo bar etcetera ) #these shouldn't get delivered pub.messages.clear sleep 3 sub.run pub.post %w( what is this even FIN ) sub.wait verify pub, sub sub.terminate end def test_subscriber_timeout chan=SecureRandom.hex sub=Subscriber.new(url("sub/timeout/#{chan}"), 2, timeout: 10) sub.on_failure { false } pub=Publisher.new url("pub/#{chan}") sub.run pub.post "hello" sub.wait verify pub, sub, false assert sub.match_errors(/code 304/) end def assert_header_includes(response, header, str) assert response.headers[header].include?(str), "Response header '#{header}:#{response.headers[header]}' must include \"#{str}\", but does not." end def test_options chan=SecureRandom.hex request = Typhoeus::Request.new url("sub/broadcast/#{chan}"), method: :OPTIONS resp = request.run assert_equal "*", resp.headers["Access-Control-Allow-Origin"] %w( GET OPTIONS ).each {|v| assert_header_includes resp, "Access-Control-Allow-Methods", v} %w( If-None-Match If-Modified-Since Origin ).each {|v| assert_header_includes resp, "Access-Control-Allow-Headers", v} request = Typhoeus::Request.new url("pub/#{chan}"), method: :OPTIONS resp = request.run assert_equal "*", resp.headers["Access-Control-Allow-Origin"] %w( GET POST DELETE OPTIONS ).each {|v| assert_header_includes resp, "Access-Control-Allow-Methods", v} %w( Content-Type Origin ).each {|v| assert_header_includes resp, "Access-Control-Allow-Headers", v} end def test_gzip #bug: turning on gzip cleared the response etag pub, sub = pubsub 1, sub: "/sub/gzip/", gzip: true, retry_delay: 0.3 sub.run pub.post ["2", "123456789A", "alsdjklsdhflsajkfhl", "boq"] sleep 1 pub.post "foobar" pub.post "FIN" sleep 1 verify pub, sub end end debian/modules/nginx-http-push/tests/chattertest.rb0000775000000000000000000000237412705233614017752 0ustar #!/usr/bin/ruby require 'test/unit' require 'securerandom' require "./pubsub.rb" #invocation: ./chattertest.rb [channel] [pub/sub] [concurrency/message] role, channel, sub_concurrency, pub_msg = nil, nil, nil, nil #parse args raise "Not enough args. ./chattertest.rb [channel] [pub/sub] [concurrency/message]" if ARGV.length < 3 channel=ARGV[0] role=ARGV[1] sub_concurrency=ARGV[2].to_i if role=="sub" pub_msg=ARGV[2] if role=="pub" def url(part) "http://127.0.0.1:8082/#{part}" end def pubsub(concurrent_clients=1, opt={}) urlpart=opt[:urlpart] || 'broadcast' timeout = opt[:timeout] || 120 sub_url=opt[:sub] || "sub/#{urlpart}/" pub_url=opt[:pub] || "pub/" chan_id = opt[:channel] || SecureRandom.hex sub = Subscriber.new url("#{sub_url}#{chan_id}"), concurrent_clients, timeout: timeout, quit_message: 'FIN' pub = Publisher.new url("#{pub_url}#{chan_id}") return pub, sub end pub, sub = pubsub(sub_concurrency, channel: channel) if role=="sub" puts "Subscribing #{sub_concurrency} client(s) to channel #{channel}." sub.on_message do |msg| puts "got message \"#{msg.to_s}\"" end sub.run false elsif role=="pub" puts "Publishing #{pub_msg} to channel #{channel}" pub.post pub_msg else raise "unknown role #{role}" enddebian/modules/nginx-http-push/tests/memparse.lua0000775000000000000000000001530712705233614017407 0ustar #!/usr/bin/luajit local lines_tailed=100000 local filename="errors.log" local follow=false local write=io.write local shm, size_by_label, count_by_label, weird_log function init() print "initialize" shm, size_by_label, count_by_label, weird_log={}, {}, {}, {} memmap={} end function err(str, ...) str = str or "Unknown error occurred" io.stderr:write(str:format(...)) io.stderr:write("\n") end function printf(str, ...) print(str:format(...)) end local poolsize=0 local poolstart=0 local memmap={} local membuckets=1024 local bucketsize=0 local resolve_weird_log; do local weirdlog={} resolve_weird_log=function(line, is_weird) local prev = weirdlog[1] if prev and prev.ptr == line.ptr and prev.t == line.t and prev.pid ~= line.pid then if prev.action == "free" and line.action == "alloc" then --oh, a free happened in a different worker and at the same time? --the log was probably written out-of-sequence table.remove(weirdlog, 1) alloc_raw(line.ptr, line.size, line.lbl, line.t, line.pid) free_raw(prev.ptr, prev.t, prev.pid) printf("resolved weird free/alloc at %s", line.ptr) return false elseif prev.action == "alloc" and line.action == "free" then --oh, an alloc happened in a different worker and at the same time? --the log was probably written out-of-sequence table.remove(weirdlog, 1) free_raw(line.ptr, line.t, line.pid) alloc_raw(prev.ptr, prev.size, prev.lbl, prev.t, prev.pid) printf("resolved weird alloc/free at %s", line.ptr) return false end end if is_weird then table.insert(weirdlog, 1, line) return false else return true end end end local memmap_add do local bucketsize=0 memmap_add= function(starthex, size, val) if not poolsize or not poolstart then return err("poolsize or poolstart not known") end val = val or 1 local start=tonumber(starthex, 16) if not start then return err("starthex was not a hex number") end --start should be relative to pool start start=start-poolstart if not size then if shm[starthex] then size=shm[starthex].size else err("shm[%s] is nil", starthex) end end local bstart = math.floor(start/poolsize * membuckets) local bend = math.floor((start+size)/poolsize * membuckets) for i=bstart, bend do memmap[i]=(memmap[i] or 0)+val if memmap[i]<0 then err("negative memmap at bucket %s", i) memmap[i]=0 end end end end function alloc(ptr, size, label, time, pid) size=tonumber(size) local looks_weird=false if shm[ptr] ~= nil then err("BAD ALLOC AT ptr %s pid %i time %s", ptr, pid, time) looks_weird = true end if resolve_weird_log({action="alloc", ptr=ptr, size=size, lbl=label, t=time, pid=pid}, looks_weird) then alloc_raw(ptr, size, label, time, pid) end end function alloc_raw(ptr, size, label, time, pid) shm[ptr]={size=size, label=label, time=time} size_by_label[label]=(size_by_label[label] or 0) + size count_by_label[label]=(count_by_label[label] or 0) + 1 memmap_add(ptr, size) end function free(ptr, time, pid) local looks_weird=false local ref=shm[ptr] if ref == nil then err ("DOUBLE FREE AT ptr %s pid %i time %s", ptr, pid, time) looks_weird = true end if resolve_weird_log({action="free", ptr=ptr, size=nil, lbl=nil, t=time, pid=pid}, looks_weird) then free_raw(ptr, time, pid) end end function free_raw(ptr, time, pid) local ref=shm[ptr] if ref==nil then err("executed double free on ptr %s pid %i time %s", ptr, pid, time) return end memmap_add(ptr, nil, -1) size_by_label[ref.label]=size_by_label[ref.label]-ref.size count_by_label[ref.label]=(count_by_label[ref.label] or 0) - 1 shm[ptr]=nil end function formatsize(bytes) if bytes<1024 then return string.format("%ib", bytes) elseif bytes > 1024 and bytes < 1048576 then return string.format("%.3gKb", bytes/1024) else return string.format("%.3gMb", bytes/1048576) end end local alphabet={1,2,3,4,5,6,7,8,9,"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"} function summary() local compare=function(a,b) return a[2] > b[2] end local total=0; local resort={} for k,v in pairs(size_by_label) do table.insert(resort, {k, v}) end table.sort(resort, compare) for k,v in ipairs(resort) do printf("%-40s %-10s %i", v[1], formatsize(v[2]), count_by_label[v[1]]) total = total + v[2] end print (" -------- ") printf("%-40s %s", "total", formatsize(total)) --memory map local n for i=0,membuckets do n=memmap[i] if n==0 or n == nil then write("-") elseif n<#alphabet then write(alphabet[n] or "?") else write("#") end end print "" end function parse_line(str) local out_of_memory local time,errlevel, pid, msg=str:match("(%d+/%d+/%d+%s+%d+:%d+:%d+)%s+%[(%w+)%]%s+(%d+)#%d+:%s+(.+)") if msg ~= nil then local ptr, size, label, start if errlevel == "crit" then print("CRITICAL:", time, pid, msg) if msg == "ngx_slab_alloc() failed: no memory" then return true end end ptr, size, label = msg:match("shpool alloc addr (%w+) size (%d+) label (.+)") if ptr then alloc(ptr, size, label, time, pid) return ptr end ptr = msg:match("shpool free addr (%w+)") if ptr then free(ptr, time, pid) return ptr end start, size = msg:match("ngx_http_push_shpool start (%w+) size (%d+)") if size and start then poolsize=tonumber(size) poolstart = tonumber(start, 16) printf("shm start %s size %s", start, formatsize(poolsize)) end end end ---------------------------------------------------------------- --NO FUNCTIONS DEFINED BELOW THIS LINE PLEASE (except lambdas)-- --handle arguments if arg[1] == "tail" or arg[1] == "follow" then follow=true elseif arg[1] ~= nil then filename=arg[1] end init() if follow then local lasttime, now=os.time(), nil print "follow errors.log" local tailin = io.popen(string.format('tail --lines=%s -F %s 2>&1', lines_tailed, filename), 'r') for line in tailin:lines() do now=os.time() if line:match('truncated') or line:match(("‘%s’ has become inaccessible: No such file or directory"):format(filename)) then --reset init() elseif parse_line(line) == true then summary() lasttime=now elseif now - lasttime > 1 then summary() lasttime=now end end else printf("open %s", filename) local f = io.open(filename, "r") for line in f:lines() do if parse_line(line) == true then summary() end end f:close() end summary() debian/modules/nginx-http-push/tests/pub.rb0000775000000000000000000000232712705233614016204 0ustar #!/usr/bin/ruby require 'securerandom' require_relative 'pubsub.rb' require "optparse" server= "localhost:8082" msg=false loop=false repeat_sec=0.5 opt=OptionParser.new do |opts| opts.on("-s", "--server SERVER (#{server})", "server and port."){|v| server=v} opts.on("-v", "--verbose", "Blabberhttp"){Typhoeus::Config.verbose=true} opts.on("-r", "--repeat [SECONDS]", "re-send message every N seconds (#{repeat_sec})") do |v| loop=true repeat_sec=Float(v) unless v.nil? end opts.on("-m", "--message MSG", "publish this message instead of prompting"){|v| msg=v} end opt.banner="Usage: pub.rb [options] url" opt.parse! url = "http://#{server}#{ARGV.last}" puts "Publishing to #{url}." loopmsg=("\r"*20) + "sending message #" pub = Publisher.new url repeat=true i=1 while repeat do if msg if loop sleep repeat_sec print loopmsg print i i+=1 else puts "Press enter to send message." STDIN.gets end pub.post msg else if loop puts "Can't repeat with custom message. use -m option" end puts "Enter one-line message, press enter." message=STDIN.gets #doesn't work when there are parameters. wtf? pub.post message puts "" end end debian/modules/nginx-http-push/tests/nginx-pushmodule/0000775000000000000000000000000012705233614020370 5ustar debian/modules/nginx-http-push/tests/nginx-pushmodule/nginx.logrotate0000664000000000000000000000026012705233614023433 0ustar /var/log/nginx/*log /var/log/nginx/*/*log { daily create 640 http log compress postrotate [ ! -f /run/nginx.pid ] || kill -USR1 `cat /run/nginx.pid` endscript } debian/modules/nginx-http-push/tests/nginx-pushmodule/install0000664000000000000000000000030012705233614021752 0ustar #!sh post_install() { post_upgrade } post_upgrade() { rm -fv /etc/nginx/http 2>/dev/null ln -sf /usr/share/nginx/http /etc/nginx/html } post_uninstall() { rm /etc/nginx/http } debian/modules/nginx-http-push/tests/nginx-pushmodule/PKGBUILD0000664000000000000000000001100212705233614021506 0ustar #!/bin/zsh _nginx_ver=1.6.0 _nginx_ver_nopool=1.7.2 _nginx_ver_old=1.0.1 _nginx_ver_very_old=0.8.40 OPTIONS=(!strip debug docs libtool staticlibs emptydirs zipman purge !upx) if [[ -z $NO_DEBUG ]]; then CFLAGS="-ggdb -O0 -Wall" fi if [[ $NO_POOL == 1 ]]; then _nginx_ver=$_nginx_ver_nopool elif [[ $NGINX_OLDVERSION == 1 ]]; then _nginx_ver=$_nginx_ver_old elif [[ $NGINX_VERYOLDVERSION == 1 ]]; then _nginx_ver=$_nginx_ver_very_old fi PKGEXT=".pkg.tar" _user="http" _group="http" _doc_root="/usr/share/${_pkgname}/http" _sysconf_path="etc" _conf_path="${_sysconf_path}/${_pkgname}" _tmp_path="/tmp/" _pid_path="/run" _lock_path="/var/lock" _access_log="/dev/stdout" _error_log="errors.log" _pushmodule_dir="${startdir}/pushmodule" _pkgver() { pushd "$startdir/pushmodule" >/dev/null printf "%s.%s.%s.%s" "$_nginx_ver" "$(git rev-parse --abbrev-ref HEAD | sed -r 's/-/_/g')" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" popd >/dev/null } pkgname=nginx-pushmodule-dev pkgver=$(_pkgver) pkgrel=1 pkgdesc="Nginx Push Module dev version" arch=('i686' 'x86_64') install=install depends=('pcre' 'zlib' 'openssl') url="http://nginx.org" license=('custom') conflicts=('nginx' 'nginx-unstable' 'nginx-svn' 'nginx-devel' 'nginx-custom-dev' 'nginx-custom-slact') provides=('nginx' 'nginx-custom') backup=("${_conf_path}/conf/nginx.conf" "${_conf_path}/conf/koi-win" "${_conf_path}/conf/koi-utf" "${_conf_path}/conf/win-utf" "${_conf_path}/conf/mime.types" "${_conf_path}/conf/fastcgi.conf" "${_conf_path}/conf/fastcgi_params" "${_conf_path}/conf/scgi_params" "${_conf_path}/conf/uwsgi_params" "etc/logrotate.d/nginx") _user=http _group=http source=("http://nginx.org/download/nginx-${_nginx_ver}.tar.gz" "nginx.conf" "nginx.logrotate" "nginx.service" "https://raw.github.com/shrimp/no-pool-nginx/master/nginx-${_nginx_ver_nopool}-no_pool.patch") md5sums=('SKIP' '1fe7a3ca0773ce13f9f92e239a99f8b9' 'ab1eb640c978536c1dad16674d6b3c3c' '62d494d23aef31d0b867161f9fffa6eb' 'SKIP') build() { local _src_dir="${srcdir}/nginx-$_nginx_ver" ln -sf $_src_dir $srcdir/nginx local _build_dir="${_src_dir}/objs" cd $_src_dir if [[ $NO_POOL == 1 ]]; then echo "using the no-pool patch" patch -p1 < "${srcdir}/nginx-${_nginx_ver}-no_pool.patch" fi if [[ $NGX_SLAB_PATCH == 1 ]]; then echo "using the ngx_slab patch to fix large alloc/frees" patch -p1 < "${startdir}/ngx_slab.patch" fi if [[ $MUDFLAP == 1 ]]; then export CFLAGS="$CFLAGS -fmudflap" fi CONFIGURE=( --prefix=/${_conf_path} --sbin-path=/usr/bin/nginx --pid-path=${_pid_path}/nginx.pid --lock-path=${_pid_path}/nginx.lock --http-client-body-temp-path=${_tmp_path}/client_body_temp --http-proxy-temp-path=${_tmp_path}/proxy_temp --http-fastcgi-temp-path=${_tmp_path}/fastcgi_temp --http-uwsgi-temp-path=${_tmp_path}/uwsgi_temp --http-log-path=${_access_log} --error-log-path=${_error_log} --user=${_user} --group=${_group} --with-debug --add-module=${_pushmodule_dir}) if [[ -z $NGINX_VERYOLDVERSION ]]; then CONFIGURE+=( "--http-scgi-temp-path=${_tmp_path}scgi_temp" ) fi if [[ $CC == *clang* ]]; then #not a valid clang parameter CFLAGS="${CFLAGS/-fvar-tracking-assignments/}" elif [[ $CC == "cc" ]] || [[ $CC == "gcc" ]] || [[ -z $CC ]]; then CFLAGS="-fdiagnostics-color=always $CFLAGS" fi export CCACHE_CPP2=yes if ! [[ -z $CLANG_ANALYZER ]]; then scan-build -o "$CLANG_ANALYZER" ./configure ${CONFIGURE[@]} scan-build -o "$CLANG_ANALYZER" make elif ! [[ -z $CONTINUE ]]; then make $REMAKE else ./configure ${CONFIGURE[@]} make fi } package() { echo "make install >/dev/null" cd "${srcdir}/nginx-${_nginx_ver}" make DESTDIR="$pkgdir/" install >/dev/null sed -i -e "s/\pages->slab = pages; } + pool->last = pool->pages + pages; + pool->log_nomem = 1; pool->log_ctx = &pool->zero; pool->zero = '\0'; @@ -626,6 +628,8 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po if (page->slab >= pages) { if (page->slab > pages) { + page[page->slab - 1].prev = (uintptr_t) &page[pages]; + page[pages].slab = page->slab - pages; page[pages].next = page->next; page[pages].prev = page->prev; @@ -672,7 +676,8 @@ static void ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, ngx_uint_t pages) { - ngx_slab_page_t *prev; + ngx_uint_t type; + ngx_slab_page_t *prev, *join; page->slab = pages--; @@ -686,6 +691,53 @@ ngx_slab_free_pages(ngx_slab_pool_t *poo page->next->prev = page->prev; } + join = page + page->slab; + + if (join < pool->last) { + type = join->prev & NGX_SLAB_PAGE_MASK; + + if (type == NGX_SLAB_PAGE && join->next != NULL) { + pages += join->slab; + page->slab += join->slab; + + prev = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + prev->next = join->next; + join->next->prev = join->prev; + + join->slab = NGX_SLAB_PAGE_FREE; + join->next = NULL; + join->prev = NGX_SLAB_PAGE; + } + } + + if (page > pool->pages) { + join = page - 1; + type = join->prev & NGX_SLAB_PAGE_MASK; + + if (type == NGX_SLAB_PAGE && join->slab == NGX_SLAB_PAGE_FREE) { + join = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + } + + if (type == NGX_SLAB_PAGE && join->next != NULL) { + pages += join->slab; + join->slab += page->slab; + + prev = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + prev->next = join->next; + join->next->prev = join->prev; + + page->slab = NGX_SLAB_PAGE_FREE; + page->next = NULL; + page->prev = NGX_SLAB_PAGE; + + page = join; + } + } + + if (pages) { + page[pages].prev = (uintptr_t) page; + } + page->prev = (uintptr_t) &pool->free; page->next = pool->free.next; diff --git a/src/core/ngx_slab.h b/src/core/ngx_slab.h --- a/src/core/ngx_slab.h +++ b/src/core/ngx_slab.h @@ -29,6 +29,7 @@ typedef struct { size_t min_shift; ngx_slab_page_t *pages; + ngx_slab_page_t *last; ngx_slab_page_t free; u_char *start; -- debian/modules/nginx-http-push/tests/nginx-pushmodule/pushmodule0000777000000000000000000000000012705233614023123 2../../ustar debian/modules/nginx-http-push/tests/nginx.conf0000664000000000000000000000554212705233614017062 0ustar #user nobody; worker_processes 20; working_directory /tmp; worker_rlimit_core 1024M; worker_rlimit_nofile 100000; #debug_points stop; #error_log /dev/stderr debug; error_log /dev/stderr notice; #error_log err.log notice; pid /tmp/pushmodule-test-nginx.pid; daemon off; events { worker_connections 10000; accept_mutex off; } http { access_log /dev/stdout; # access_log /dev/stdout; default_type application/octet-stream; client_body_temp_path /tmp/ 1 2; sendfile on; keepalive_timeout 65; push_authorized_channels_only off; push_max_reserved_memory 32M; #cachetag server { listen 8082; # root ./; location ~ /pub/(\w+)$ { set $push_channel_id $1; push_publisher; push_min_message_buffer_length 5; push_max_message_buffer_length 20; push_message_timeout 5s; push_channel_group test; } location ~/pub/nobuffer/(\w+)$ { set $push_channel_id $1; push_publisher; push_store_messages off; push_message_timeout 60s; push_channel_group test; } location ~ /pub/2_sec_message_timeout/(\w+)$ { set $push_channel_id $1; push_publisher; push_min_message_buffer_length 5; push_max_message_buffer_length 20; push_message_timeout 2s; push_channel_group test; } location ~ /sub/broadcast/(\w+)$ { push_subscriber; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency broadcast; } location ~ /sub/first/(\w+)$ { push_subscriber; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency first; } location ~ /sub/last/(\w+)$ { push_subscriber; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency last; } location ~ /sub/intervalpoll/(\w+)$ { push_subscriber interval-poll; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency broadcast; } location ~ /sub/gzip/(\w+)$ { add_header Content-Type text/plain; gzip on; gzip_min_length 10; gzip_proxied any; gzip_types *; push_subscriber; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency broadcast; } #quick subscriber timeout location ~ /sub/timeout/(\w+)$ { push_subscriber; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency broadcast; push_subscriber_timeout 2s; } #authorized channels only -- publishers must create the channel before subscribing location ~ /sub/authorized/(\w+)$ { push_authorized_channels_only on; push_subscriber; push_channel_group test; set $push_channel_id $1; } location ~ /rewrite/(.*)$ { rewrite ^/(.*)$ $1; } } } debian/modules/nginx-http-push/tests/test-parallel.sh0000775000000000000000000000062412705233614020174 0ustar #!/bin/bash par=$1 if [[ -z "$par" ]]; then par=5 echo "No parallel count given. Assuming $par." fi if ! [[ $par =~ ^[0-9]+$ ]]; then echo "Parallel count isn't a number." > /dev/stderr exit 1 fi for ((i = 0; i < $par; i++)); do ./test.rb ${@:2} & done jobs=$(jobs -p) #echo "jobs are $jobs" killjobs() { for job_pid in $jobs; do kill $job_pid done } trap killjobs SIGINT wait $jobs debian/modules/nginx-http-push/tests/debug.sh0000775000000000000000000000050112705233614016503 0ustar #!/bin/zsh TESTDIR=`pwd` SRCDIR=$(readlink -m $TESTDIR/../src) ln -sf $TESTDIR/nginx $SRCDIR/nginx >/dev/null ln -sf $TESTDIR/nginx-pushmodule/src/nginx/src/ $SRCDIR/nginx-source >/dev/null if [[ "$1" = <-> ]]; then sudo kdbg -p $1 $SRCDIR/nginx else kdbg $SRCDIR/nginx $1 fi rm $SRCDIR/nginx $SRCDIR/nginx-sourcedebian/modules/nginx-http-push/tests/pubsub.rb0000664000000000000000000002354712705233614016722 0ustar #!/usr/bin/ruby require 'typhoeus' require 'json' require 'pry' require 'celluloid' Typhoeus::Config.memoize = false class Message attr_accessor :content_type, :message, :times_seen, :etag, :last_modified def initialize(msg, last_modified=nil, etag=nil) @times_seen=1 @message, @last_modified, @etag = msg, last_modified, etag end def id @id||="#{last_modified}:#{etag}" end def to_s @message end end class MessageStore include Enumerable attr_accessor :msgs, :quit_message def matches? (msg_store) my_messages = messages if MessageStore === msg_store other_messages = msg_store.messages else other_messages = msg_store end return false, "Message count doesn't match. ( #{my_messages.count}, #{other_messages.count})" unless my_messages.count == other_messages.count other_messages.each_with_index do |msg, i| return false, "Message #{i} doesn't match. (|#{my_messages[i].length}|, |#{msg.length}|) " if my_messages[i] != msg end true end def initialize(opt={}) @array||=opt[:noid] clear end def messages self.to_a.map{|m|m.to_s} end #remove n oldest messages def remove_old(n=1) n.times {@msgs.shift} @msgs.count end def clear @msgs= @array ? [] : {} end def to_a @array ? @msgs : @msgs.values end def pp each do |msg| puts "\"#{msg.to_s}\" (seen #{msg.times_seen} times.)" end end def each if @array @msgs.each {|msg| yield msg } else @msgs.each {|key, msg| yield msg } end end def <<(msg) if @array @msgs << msg else if (cur_msg=@msgs[msg.id]) puts "Received different messages with same message id #{msg.id}: '#{cur_msg.message}' and '#{msg.message}'" unless cur_msg.message == msg.message cur_msg.times_seen+=1 cur_msg.times_seen else @msgs[msg.id]=msg 1 end end end end class Subscriber class LongPollClient include Celluloid attr_accessor :last_modified, :etag, :hydra, :timeout def initialize(subscr, opt={}) @last_modified, @etag, @timeout = opt[:last_modified], opt[:etag], opt[:timeout] || 10 @connect_timeout = opt[:connect_timeout] @subscriber=subscr @url=subscr.url @concurrency=opt[:concurrency] || opt[:clients] || 1 @hydra= Typhoeus::Hydra.new( max_concurrency: @concurrency) @gzip=opt[:gzip] @retry_delay=opt[:retry_delay] end def response_success(response, req) #puts "received OK response at #{req.url}" #parse it msg=Message.new response.body, response.headers["Last-Modified"], response.headers["Etag"] msg.content_type=response.headers["Content-Type"] req.options[:headers]["If-None-Match"]=msg.etag req.options[:headers]["If-Modified-Since"]=msg.last_modified unless @subscriber.on_message(msg) == false @subscriber.waiting+=1 Celluloid.sleep @retry_delay if @retry_delay @hydra.queue req else @subscriber.finished+=1 end end def response_failure(response, req) #puts "received bad or no response at #{req.url}" unless @subscriber.on_failure(response) == false @subscriber.waiting+=1 Celluloid.sleep @retry_delay if @retry_delay @hydra.queue req else @subscriber.finished+=1 end end def new_request req=Typhoeus::Request.new(@url, timeout: @timeout, connecttimeout: @connect_timeout, accept_encoding: (@gzip ? "gzip" : nil) ) req.on_complete do |response| @subscriber.waiting-=1 if response.success? response_success response, req else response_failure response, req end end req end def run(was_success=nil) #puts "running #{self.class.name} hydra with #{@hydra.queued_requests.count} requests." (@concurrency - @hydra.queued_requests.count).times do @subscriber.waiting+=1 @hydra.queue new_request end @hydra.run end def poke end end class IntervalPollClient < LongPollClient def initialize(subscr, opt={}) @last_modified=nil @etag=nil super end def store_msg_id(response, req) @last_modified=response.headers["Last-Modified"] if response.headers["Last-Modified"] @etag=response.headers["Etag"] if response.headers["Etag"] req.options[:headers]["If-Modified-Since"]=@last_modified req.options[:headers]["If-None-Match"]=@etag end def response_success(response, req) store_msg_id(response, req) super response, req end def response_failure(response, req) if response.code == 304 || @subscriber.on_failure(response) != false @subscriber.waiting+=1 Celluloid.sleep @retry_delay if @retry_delay @hydra.queue req else @subscriber.finished+=1 end end def poke while @subscriber.finished < @concurrency do sleep 1 end end end attr_accessor :url, :client, :messages, :max_round_trips, :quit_message, :errors, :concurrency, :waiting, :finished, :client_class def initialize(url, concurrency=1, opt={}) @care_about_message_ids=opt[:use_message_id].nil? ? true : opt[:use_message_id] @url=url @timeout=opt[:timeout] || 30 @connect_timeout=opt[:connect_timeout] || 5 @quit_message=opt[:quit_message] @gzip=opt[:gzip] @retry_delay=opt[:retry_delay] reset #puts "Starting subscriber on #{url}" case opt[:client] when :longpoll, :long, nil @client_class=LongPollClient when :interval, :intervalpoll @client_class=IntervalPollClient when :ws, :websocket raise "websocket client not yet implemented" when :es, :eventsource raise "EventSource client not yet implemented" else raise "unknown client type #{opt[:client]}" end @concurrency=concurrency @client_class ||= opt[:client_class] || LongPollClient new_client @client_class end def new_client(client_class=LongPollClient) @client=client_class.new(self, concurrency: @concurrency, timeout: @timeout, connect_timeout: @connect_timeout, gzip: @gzip, retry_delay: @retry_delay) end def reset @errors=[] @messages=MessageStore.new :noid => !@care_about_message_ids @waiting=0 @finished=0 new_client if terminated? self end def abort @client.terminate end def errors? not no_errors? end def no_errors? @errors.empty? end def match_errors(regex) @errors.each do |err| return false unless err =~ regex end true end def run begin client.current_actor rescue Celluloid::DeadActorError return false end @client.async.run self end def terminate begin @client.terminate rescue Celluloid::DeadActorError return false end true end def terminated? begin client.current_actor unless client == nil rescue Celluloid::DeadActorError return false end true end def wait @client.poke end def on_message(msg=nil, &block) #puts "received message #{msg.to_s[0..15]}" if block_given? @on_message=block else @messages << msg return false if @quit_message == msg.to_s @on_message.call(msg) if @on_message.respond_to? :call end end def on_failure(response=nil, &block) if block_given? @on_failure=block else #puts "failed with #{response.to_s}. handler is #{@on_failure.to_s}" if response.timed_out? # aw hell no @errors << "Client response timeout." elsif response.code == 0 # Could not get an http response, something's wrong. @errors << response.return_message else # Received a non-successful http response. @errors << "HTTP request failed: #{response.return_message} (code #{response.code})" end @on_failure.call(response) if @on_failure.respond_to? :call end end end class Publisher include Celluloid attr_accessor :messages, :response, :response_code, :response_body, :nofail, :accept def initialize(url) @url= url @messages = MessageStore.new :noid => true end def submit(body, method=:POST, content_type= :'text/plain', &block) self.response=nil self.response_code=nil self.response_body=nil if Enumerable===body i=0 body.each{|b| i+=1; submit(b, method, content_type, &block)} return i end post = Typhoeus::Request.new( @url, headers: {:'Content-Type' => content_type, :'Accept' => accept}, method: method, body: body, ) msg=Message.new body msg.content_type=content_type post.on_complete do |response| self.response=response self.response_code=response.response_code self.response_body=response.response_body if response.success? #puts "published message #{msg.to_s[0..15]}" @messages << msg elsif response.timed_out? # aw hell no #puts "publisher err: timeout" raise "Response timed out." elsif response.code == 0 # Could not get an http response, something's wrong. #puts "publisher err: #{response.return_message}" raise "No HTTP response: #{response.return_message}" unless self.nofail else # Received a non-successful http response. #puts "publisher err: #{response.code.to_s}" raise "HTTP request failed: #{response.code.to_s}" unless self.nofail end block.call(self) if block end #puts "publishing to #{@url}" post.run end def get(accept_header=nil) self.accept=accept_header submit nil, :GET self.accept=nil end def delete submit nil, :DELETE end def post(body, content_type=nil, &block) submit body, :POST, content_type, &block end def put(body, content_type=nil, &block) submit body, :PUT, content_type, &block end end debian/modules/nginx-http-push/tests/nginx-cachemanager.conf0000664000000000000000000000270312705233614021452 0ustar worker_processes 4; #debug_points stop; #error_log /dev/stderr debug; error_log /dev/stderr notice; #error_log err.log notice; pid /tmp/nginx-debug.pid; events { worker_connections 90000; accept_mutex on; } http { access_log /dev/stdout; proxy_cache_path /tmp levels=1:2 keys_zone=cache:1m; server { listen 8000; location / { proxy_cache cache; } } server { listen 8082; # root ./; location ~ /pub/(\w+)$ { set $push_channel_id $1; push_publisher; push_min_message_buffer_length 5; push_max_message_buffer_length 20; push_message_timeout 5s; push_channel_group test; } location ~ /sub/broadcast/(\w+)$ { push_subscriber; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency broadcast; } location ~ /sub/first/(\w+)$ { push_subscriber; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency first; } location ~ /sub/last/(\w+)$ { push_subscriber; push_channel_group test; set $push_channel_id $1; push_subscriber_concurrency last; } #authorized channels only -- publishers must create the channel before subscribing location ~ /sub/authorized/(\w+)$ { push_authorized_channels_only on; push_subscriber; push_channel_group test; set $push_channel_id $1; } } }debian/modules/nginx-http-push/tests/examine_coredump.sh0000775000000000000000000000054012705233614020744 0ustar #!/bin/zsh target=$1 core_dir="./coredump" if [ -z $target ]; then target=$(realpath ./nginx) dump=$core_dir/last.core else dump=$core_dir/$target.core fi mkdir $core_dir 2>/dev/null echo "saving coredump for $target at $dump" sudo systemd-coredumpctl dump $target > $dump kdbg ./nginx "$dump" 2>/dev/null # rm "$dump" #keep it around for now debian/modules/nginx-http-push/tests/nginx-proxy.conf0000664000000000000000000000101712705233614020232 0ustar worker_processes 3; pid /tmp/pushmodule-test-nginx-proxy.pid; daemon off; events { worker_connections 90000; accept_mutex on; } error_log /dev/stderr notice; http { access_log /dev/null; client_body_temp_path /tmp/ 1 2; sendfile on; keepalive_timeout 65; server { listen 8083; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://localhost:8082; } } }debian/modules/nginx-http-push/tests/Gemfile0000664000000000000000000000023112705233614016351 0ustar #!/usr/bin/ruby source 'https://rubygems.org' gem 'typhoeus' gem 'json' gem 'nokogiri' gem 'pry' gem 'celluloid' gem 'minitest' gem 'minitest-reporters' debian/modules/nginx-http-push/tests/nginx.sh0000775000000000000000000000552012705233614016546 0ustar #!/bin/zsh TESTDIR=`pwd` SRCDIR=$(readlink -m $TESTDIR/../src) echo $TESTDIR $SRCDIR NGINX_CONFIG=`pwd`/nginx.conf NGINX_TEMP_CONFIG=`pwd`/.nginx.thisrun.conf NGINX_OPT=( -p `pwd`/ -c $NGINX_TEMP_CONFIG ) cp -fv $NGINX_CONFIG $NGINX_TEMP_CONFIG VALGRIND_OPT=( --trace-children=yes --track-origins=yes --read-var-info=yes ) WORKERS=5 NGINX_DAEMON="off" NGINX_CONF="" ACCESS_LOG="/dev/null" ERROR_LOG="stderr" ERRLOG_LEVEL="notice" TMPDIR="" MEM="32M" _cacheconf=" proxy_cache_path _CACHEDIR_ levels=1:2 keys_zone=cache:1m; \\n server {\\n listen 8007;\\n location / { \\n proxy_cache cache; \\n }\\n }\\n" echo $cacheconf for opt in $*; do if [[ "$opt" = <-> ]]; then WORKERS=$opt fi case $opt in leak|leakcheck) VALGRIND_OPT+=("--leak-check=full" "--show-leak-kinds=all" "--track-fds=yes");; valgrind) valgrind=1;; alleyoop) alleyoop=1;; cache) CACHE=1;; access) ACCESS_LOG="/dev/stdout";; worker|one|single) WORKERS=1 ;; debug|kdbg) WORKERS=1 NGINX_DAEMON="on" debugger=1 ;; debuglog) ERRLOG_LEVEL="debug" ;; errorlog) ERROR_LOG="errors.log" rm ./errors.log 2>/dev/null ;; lomem|lowmem|small) MEM="5M";; himem|highmem|large) MEM="256M";; verylowmem|tiny) MEM="1M";; esac done conf_replace(){ echo "$1 $2" sed "s|\($1\).*|\1 $2;|g" $NGINX_TEMP_CONFIG -i } ulimit -c unlimited if [[ ! -z $NGINX_CONF ]]; then NGINX_OPT+=( -g "$NGINX_CONF" ) fi #echo $NGINX_CONF #echo $NGINX_OPT echo "nginx $NGINX_OPT" conf_replace "access_log" $ACCESS_LOG conf_replace "error_log" "$ERROR_LOG $ERRLOG_LEVEL" conf_replace "worker_processes" $WORKERS conf_replace "daemon" $NGINX_DAEMON conf_replace "working_directory" "\"$(pwd)\"" conf_replace "push_max_reserved_memory" "$MEM" if [[ ! -z $CACHE ]]; then sed "s|^\s*#cachetag.*|${_cacheconf}|g" $NGINX_TEMP_CONFIG -i tmpdir=`pwd`"/.tmp" mkdir $tmpdir 2>/dev/null sed "s|_CACHEDIR_|\"$tmpdir\"|g" $NGINX_TEMP_CONFIG -i fi if [[ $debugger == 1 ]]; then ./nginx $NGINX_OPT sleep 0.2 master_pid=`cat /tmp/pushmodule-test-nginx.pid` child_pids=`pgrep -P $master_pid` kdbg_pids=() ln -sf $TESTDIR/nginx $SRCDIR/nginx >/dev/null ln -sf $TESTDIR/nginx-pushmodule/src/nginx/src/ $SRCDIR/nginx-source >/dev/null sudo echo "attaching kdbg..." while read -r line; do sudo kdbg -p $line $SRCDIR/nginx & kdbg_pids+="$!" done <<< $child_pids echo "kdbg at $kdbg_pids" wait $kdbg_pids kill $master_pid rm -f $SRCDIR/nginx $SRCDIR/nginx-source 2>/dev/null elif [[ $valgrind == 1 ]]; then mkdir ./coredump 2>/dev/null pushd ./coredump >/dev/null valgrind $VALGRIND_OPT ../nginx $NGINX_OPT popd >/dev/null elif [[ $alleyoop == 1 ]]; then alleyoop ./nginx $NGINX_OPT else ./nginx $NGINX_OPT fi debian/modules/nginx-http-push/tests/rebuild.sh0000775000000000000000000000247112705233614017053 0ustar #!/bin/zsh #assumes PKGBUILDy nginx located at ./nginx-pushmodule MY_PATH="`dirname \"$0\"`" MY_PATH="`( cd \"$MY_PATH\" && pwd )`" ccached_clang="ccache clang -Qunused-arguments -fcolor-diagnostics" for opt in $*; do case $opt in clang) export CC=$ccached_clang;; nopool|no-pool|nop) export NO_POOL=1;; re|remake) export REMAKE="-B" export CONTINUE=1;; c|continue|cont) export CONTINUE=1;; nomake) export NO_MAKE=1;; nodebug) export NO_DEBUG=1;; mudflap) export MUDFLAP=1 export CC=gcc ;; oldversion|old) export NGINX_OLDVERSION=1;; veryoldversion|veryold) export NGINX_VERYOLDVERSION=1;; slabpatch|slab) export NGX_SLAB_PATCH=1;; clang-analyzer|analyzer|scan|analyze) export CC="clang" export CLANG_ANALYZER=$MY_PATH/clang-analyzer mkdir $CLANG_ANALYZER 2>/dev/null ;; esac done if [[ -z $NO_MAKE ]]; then pushd ./nginx-pushmodule >/dev/null if [[ $CONTINUE == 1 ]]; then makepkg -f -e else makepkg -f fi popd >/dev/null fi if ! [[ -z $CLANG_ANALYZER ]]; then pushd $CLANG_ANALYZER >/dev/null latest_scan=`ls -c |head -n1` echo "run 'scan-view ${CLANG_ANALYZER}/${latest_scan}' for static analysis." scan-view $latest_scan 2>/dev/null popd >/dev/null fi debian/modules/nginx-http-push/src/0000775000000000000000000000000012705233614014507 5ustar debian/modules/nginx-http-push/src/ngx_http_push_module.h0000664000000000000000000000432712705233614021125 0ustar #include #include #include #include extern ngx_pool_t *ngx_http_push_pool; extern ngx_int_t ngx_http_push_worker_processes; extern ngx_module_t ngx_http_push_module; extern ngx_http_push_store_t *ngx_http_push_store; ngx_int_t ngx_http_push_respond_status_only(ngx_http_request_t *r, ngx_int_t status_code, const ngx_str_t *statusline); void ngx_http_push_clean_timeouted_subscriber(ngx_event_t *ev); ngx_int_t ngx_http_push_allow_caching(ngx_http_request_t *r); ngx_int_t ngx_http_push_subscriber_get_msg_id(ngx_http_request_t *r, ngx_http_push_msg_id_t *id); void ngx_http_push_subscriber_cleanup(ngx_http_push_subscriber_cleanup_t *data); ngx_str_t * ngx_http_push_subscriber_get_etag(ngx_http_request_t * r); ngx_table_elt_t * ngx_http_push_add_response_header(ngx_http_request_t *r, const ngx_str_t *header_name, const ngx_str_t *header_value); ngx_chain_t * ngx_http_push_create_output_chain(ngx_buf_t *buf, ngx_pool_t *pool, ngx_log_t *log); ngx_int_t ngx_http_push_prepare_response_to_subscriber_request(ngx_http_request_t *r, ngx_chain_t *chain, ngx_str_t *content_type, ngx_str_t *etag, time_t last_modified); ngx_int_t ngx_push_longpoll_subscriber_enqueue(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *subscriber, ngx_int_t subscriber_timeout); ngx_int_t ngx_push_longpoll_subscriber_dequeue(ngx_http_push_subscriber_t *subscriber); ngx_int_t ngx_http_push_alloc_for_subscriber_response(ngx_pool_t *pool, ngx_int_t shared, ngx_http_push_msg_t *msg, ngx_chain_t **chain, ngx_str_t **content_type, ngx_str_t **etag, time_t *last_modified); ngx_int_t ngx_http_push_subscriber_handler(ngx_http_request_t *r); ngx_int_t ngx_http_push_publisher_handler(ngx_http_request_t *r); ngx_int_t ngx_http_push_respond_to_subscribers(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *sentinel, ngx_http_push_msg_t *msg, ngx_int_t status_code, const ngx_str_t *status_line); ngx_int_t ngx_http_push_respond_status_only(ngx_http_request_t *r, ngx_int_t status_code, const ngx_str_t *statusline); ngx_int_t ngx_http_push_subscriber_get_etag_int(ngx_http_request_t * r); void ngx_http_push_copy_preallocated_buffer(ngx_buf_t *buf, ngx_buf_t *cbuf); debian/modules/nginx-http-push/src/store/0000775000000000000000000000000012705233614015643 5ustar debian/modules/nginx-http-push/src/store/rbtree_util.h0000664000000000000000000000207412705233614020337 0ustar void ngx_http_push_rbtree_insert(ngx_rbtree_node_t *temp,ngx_rbtree_node_t *node,ngx_rbtree_node_t *sentinel); void ngx_http_push_rbtree_walker(ngx_rbtree_t *tree,ngx_int_t(*apply)(ngx_http_push_channel_t *channel),ngx_rbtree_node_t *node); void ngx_rbtree_generic_insert(ngx_rbtree_node_t *temp,ngx_rbtree_node_t *node,ngx_rbtree_node_t *sentinel,int(*compare)(const ngx_rbtree_node_t *left,const ngx_rbtree_node_t *right)); ngx_http_push_channel_t *ngx_http_push_get_channel(ngx_str_t *id,time_t timeout,ngx_shm_zone_t *shm_zoneg); ngx_http_push_channel_t *ngx_http_push_find_channel(ngx_str_t *id,time_t timeout,ngx_shm_zone_t *shm_zone); ngx_int_t ngx_http_push_delete_channel_locked(ngx_http_push_channel_t *trash,ngx_shm_zone_t *shm_zone); ngx_http_push_channel_t *ngx_http_push_clean_channel_locked(ngx_http_push_channel_t *channel); #define ngx_http_push_walk_rbtree(apply, shm_zone) \ ngx_http_push_rbtree_walker(&((ngx_http_push_shm_data_t *) shm_zone->data)->tree, apply, ((ngx_http_push_shm_data_t *) shm_zone->data)->tree.root) debian/modules/nginx-http-push/src/store/ngx_http_push_module_ipc.h0000664000000000000000000000047212705233614023111 0ustar ngx_int_t ngx_http_push_alert_worker(ngx_pid_t pid,ngx_int_t slot); ngx_int_t ngx_http_push_ipc_init_worker(ngx_cycle_t *cycle); void ngx_http_push_ipc_exit_worker(ngx_cycle_t *cycle); ngx_int_t ngx_http_push_shutdown_ipc(ngx_cycle_t *cycle); ngx_int_t ngx_http_push_init_ipc(ngx_cycle_t *cycle,ngx_int_t workers);debian/modules/nginx-http-push/src/store/ngx_http_push_store.h0000775000000000000000000000635512705233614022136 0ustar typedef struct { //init ngx_int_t (*init_module)(ngx_cycle_t *cycle); ngx_int_t (*init_worker)(ngx_cycle_t *cycle); ngx_int_t (*init_postconfig)(ngx_conf_t *cf); void (*create_main_conf)(ngx_conf_t *cf, ngx_http_push_main_conf_t *mcf); //quit void (*exit_worker)(ngx_cycle_t *cycle); void (*exit_master)(ngx_cycle_t *cycle); //async-friendly functions with callbacks ngx_http_push_msg_t * (*get_message) (ngx_str_t *channel_id, ngx_http_push_msg_id_t *msg_id, ngx_int_t *msg_search_outcome, ngx_http_request_t *r, ngx_int_t (*callback)(ngx_http_push_msg_t *msg, ngx_int_t msg_search_outcome, ngx_http_request_t *r)); ngx_int_t (*subscribe) (ngx_str_t *channel_id, ngx_http_push_msg_id_t *msg_id, ngx_http_request_t *r, ngx_int_t (*callback)(ngx_int_t status, ngx_http_request_t *r)); ngx_int_t (*publish) (ngx_str_t *channel_id, ngx_http_request_t *r, ngx_int_t (*callback)(ngx_int_t status, ngx_http_push_channel_t *ch, ngx_http_request_t *r)); //channel actions ngx_http_push_channel_t *(*get_channel)(ngx_str_t *id, time_t channel_timeout, ngx_int_t (*callback)(ngx_http_push_channel_t *channel)); ngx_http_push_channel_t *(*find_channel)(ngx_str_t *id, time_t channel_timeout, ngx_int_t (*callback)(ngx_http_push_channel_t *channel)); ngx_int_t (*delete_channel)(ngx_str_t *channel_id); ngx_http_push_msg_t *(*get_channel_message)(ngx_http_push_channel_t *channel, ngx_http_push_msg_id_t *msgid, ngx_int_t *msg_search_outcome, ngx_http_push_loc_conf_t *cf); void (*reserve_message)(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg); void (*release_message)(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg); //channel properties ngx_int_t (*channel_subscribers)(ngx_http_push_channel_t * channel); ngx_int_t (*channel_worker_subscribers)(ngx_http_push_subscriber_t * worker_sentinel); ngx_http_push_subscriber_t *(*next_subscriber)(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *sentinel, ngx_http_push_subscriber_t *cur, int release_previous); ngx_int_t (*release_subscriber_sentinel)(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *sentinel); void (*lock)(void); //legacy shared-memory store helpers void (*unlock)(void); void * (*alloc_locked)(size_t size, char * label); void (*free_locked)(void *ptr); //message actions and properties ngx_http_push_msg_t * (*create_message)(ngx_http_push_channel_t *channel, ngx_http_request_t *r); ngx_int_t (*delete_message)(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_int_t force); ngx_int_t (*delete_message_locked)(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_int_t force); ngx_int_t (*enqueue_message)(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_http_push_loc_conf_t *cf); ngx_str_t * (*message_etag)(ngx_http_push_msg_t *msg, ngx_pool_t *pool); ngx_str_t * (*message_content_type)(ngx_http_push_msg_t *msg, ngx_pool_t *pool); //ipc ngx_int_t (*send_worker_message)(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *subscriber_sentinel, ngx_pid_t pid, ngx_int_t worker_slot, ngx_http_push_msg_t *msg, ngx_int_t status_code); void (*receive_worker_message)(void); } ngx_http_push_store_t; debian/modules/nginx-http-push/src/store/ngx_rwlock.h0000664000000000000000000000036312705233614020173 0ustar void ngx_rwlock_init(ngx_rwlock_t *lock); void ngx_rwlock_release_write(ngx_rwlock_t *lock); void ngx_rwlock_reserve_write(ngx_rwlock_t *lock); void ngx_rwlock_release_read(ngx_rwlock_t *lock); void ngx_rwlock_reserve_read(ngx_rwlock_t *lock);debian/modules/nginx-http-push/src/store/rbtree_util.c0000664000000000000000000001650212705233614020333 0ustar #include #include "rbtree_util.h" ngx_http_push_channel_t * ngx_http_push_clean_channel_locked(ngx_http_push_channel_t * channel) { ngx_queue_t *sentinel = &channel->message_queue->queue; time_t now = ngx_time(); ngx_http_push_msg_t *msg=NULL; while(!ngx_queue_empty(sentinel)){ msg = ngx_queue_data(ngx_queue_head(sentinel), ngx_http_push_msg_t, queue); if (msg!=NULL && msg->expires != 0 && now > msg->expires) { ngx_http_push_store->delete_message_locked(channel, msg, 0); } else { //definitely a message left to send return NULL; } } //at this point, the queue is empty return (channel->subscribers==0 && (channel->expires <= now)) ? channel : NULL; //if no waiting requests and channel expired, return this channel to be deleted } static ngx_int_t ngx_http_push_delete_node_locked(ngx_rbtree_t *tree, ngx_rbtree_node_t *trash) { //assume the shm zone is already locked if(trash != NULL){ //take out the trash ngx_rbtree_delete(tree, trash); //delete the worker-subscriber queue ngx_queue_t *sentinel = (ngx_queue_t *)((ngx_http_push_channel_t *)trash)->workers_with_subscribers; ngx_queue_t *cur = ngx_queue_head(sentinel); ngx_queue_t *next; while(cur!=sentinel) { next = ngx_queue_next(cur); ngx_http_push_store->free_locked(cur); cur = next; } ngx_http_push_store->free_locked(trash); ngx_http_push_store->free_locked(sentinel); return NGX_OK; } return NGX_DECLINED; } ngx_int_t ngx_http_push_delete_channel_locked(ngx_http_push_channel_t *trash, ngx_shm_zone_t *shm_zone) { ngx_int_t res; res = ngx_http_push_delete_node_locked(&((ngx_http_push_shm_data_t *) shm_zone->data)->tree, (ngx_rbtree_node_t *)trash); if(res==NGX_OK) { ((ngx_http_push_shm_data_t *) shm_zone->data)->channels--; return NGX_OK; } return res; } ngx_http_push_channel_t * ngx_http_push_find_channel(ngx_str_t *id, time_t timeout, ngx_shm_zone_t *shm_zone) { ngx_rbtree_t *tree = &((ngx_http_push_shm_data_t *) shm_zone->data)->tree; uint32_t hash; ngx_rbtree_node_t *node, *sentinel; ngx_int_t rc; ngx_http_push_channel_t *up = NULL; ngx_http_push_channel_t *trash[] = { NULL, NULL, NULL }; ngx_uint_t i, trashed=0; if (tree==NULL) { return NULL; } hash = ngx_crc32_short(id->data, id->len); node = tree->root; sentinel = tree->sentinel; while (node != sentinel) { //every search is responsible for deleting a couple of empty, if it comes across them if (trashed < (sizeof(trash) / sizeof(*trash))) { if((trash[trashed]=ngx_http_push_clean_channel_locked((ngx_http_push_channel_t *) node))!=NULL) { trashed++; } } if (hash < node->key) { node = node->left; continue; } if (hash > node->key) { node = node->right; continue; } /* hash == node->key */ do { up = (ngx_http_push_channel_t *) node; rc = ngx_memn2cmp(id->data, up->id.data, id->len, up->id.len); if (rc == 0) { //found for(i=0; iexpires = ngx_time() + timeout; ngx_http_push_clean_channel_locked(up); return up; } node = (rc < 0) ? node->left : node->right; } while (node != sentinel && hash == node->key); break; } //not found for(i=0; idata)->tree; if((up = ngx_http_push_store->alloc_locked(sizeof(*up) + id->len + sizeof(ngx_http_push_msg_t), "channel"))==NULL) { return NULL; } if((worker_queue_sentinel=ngx_http_push_store->alloc_locked(sizeof(*worker_queue_sentinel), "channel worker queue sentinel"))==NULL) { ngx_http_push_store->free_locked(up); ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate worker queue sentinel"); return NULL; } ngx_queue_init(&worker_queue_sentinel->queue); up->id.data = (u_char *) (up+1); //contiguous piggy up->message_queue = (ngx_http_push_msg_t *) (up->id.data + id->len); up->id.len = (u_char) id->len; ngx_memcpy(up->id.data, id->data, up->id.len); up->node.key = ngx_crc32_short(id->data, id->len); ngx_rbtree_insert(tree, (ngx_rbtree_node_t *) up); //initialize queues ngx_queue_init(&up->message_queue->queue); up->messages=0; up->workers_with_subscribers=worker_queue_sentinel; up->subscribers=0; up->last_seen=ngx_time(); up->expires = ngx_time() + timeout; ((ngx_http_push_shm_data_t *) shm_zone->data)->channels++; return up; } void ngx_rbtree_generic_insert( ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel, int (*compare)(const ngx_rbtree_node_t *left, const ngx_rbtree_node_t *right)) { for ( ;; ) { if (node->key < temp->key) { if (temp->left == sentinel) { temp->left = node; break; } temp = temp->left; } else if (node->key > temp->key) { if (temp->right == sentinel) { temp->right = node; break; } temp = temp->right; } else { /* node->key == temp->key */ if (compare(node, temp) < 0) { if (temp->left == sentinel) { temp->left = node; break; } temp = temp->left; } else { if (temp->right == sentinel) { temp->right = node; break; } temp = temp->right; } } } node->parent = temp; node->left = sentinel; node->right = sentinel; ngx_rbt_red(node); } void ngx_http_push_rbtree_walker(ngx_rbtree_t *tree, ngx_int_t (*apply)(ngx_http_push_channel_t * channel), ngx_rbtree_node_t *node) { ngx_rbtree_node_t *sentinel = tree->sentinel; if(node!=sentinel) { apply((ngx_http_push_channel_t *)node); if(node->left!=NULL) { ngx_http_push_rbtree_walker(tree, apply, node->left); } if(node->right!=NULL) { ngx_http_push_rbtree_walker(tree, apply, node->right); } } } static int ngx_http_push_compare_rbtree_node(const ngx_rbtree_node_t *v_left, const ngx_rbtree_node_t *v_right) { ngx_http_push_channel_t *left = (ngx_http_push_channel_t *) v_left, *right = (ngx_http_push_channel_t *) v_right; return ngx_memn2cmp(left->id.data, right->id.data, left->id.len, right->id.len); } void ngx_http_push_rbtree_insert(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) { ngx_rbtree_generic_insert(temp, node, sentinel, ngx_http_push_compare_rbtree_node); } debian/modules/nginx-http-push/src/store/ngx_rwlock.c0000664000000000000000000001121012705233614020157 0ustar #include #include "ngx_rwlock.h" #define NGX_RWLOCK_SPIN 2048 #define NGX_RWLOCK_WRITE -1 #define DISABLE_RWLOCK 1 //just use a regular mutex for everything //#define DEBUG_NGX_RWLOCK 1 void ngx_rwlock_init(ngx_rwlock_t *lock) { lock->mutex=1; lock->lock=0; lock->write_pid=0; lock->mutex=0; } static void rwl_lock_mutex(ngx_rwlock_t *lock) { #if (NGX_HAVE_ATOMIC_OPS) ngx_atomic_t *mutex = &lock->mutex; ngx_uint_t i, n; for(;;) { if(*mutex == 0 && ngx_atomic_cmp_set(mutex, 0, ngx_pid)) { return; } if(ngx_ncpu > 1) { for(n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) { for(i = 0; i < n; i++) { ngx_cpu_pause(); } #if (DEBUG_NGX_RWLOCK) ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "rwlock %p mutex wait", lock); #endif if(*mutex == 0 && ngx_atomic_cmp_set(mutex, 0, ngx_pid)) { return; } } } ngx_sched_yield(); } #else #if (NGX_THREADS) #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined ! #endif #endif } static void rwl_unlock_mutex(ngx_rwlock_t *lock) { #if (NGX_HAVE_ATOMIC_OPS) ngx_atomic_cmp_set(&lock->mutex, ngx_pid, 0); #else #if (NGX_THREADS) #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined ! #endif #endif } #define NGX_RWLOCK_MUTEX_COND(lock, cond, stmt) \ if(cond) { \ rwl_lock_mutex(lock); \ if(cond) { \ stmt; \ rwl_unlock_mutex(lock); \ return; \ } \ rwl_unlock_mutex(lock); \ } void ngx_rwlock_reserve_read(ngx_rwlock_t *lock) { #if (NGX_HAVE_ATOMIC_OPS) ngx_uint_t i, n; #if (DISABLE_RWLOCK == 1) rwl_lock_mutex(lock); return; #endif for(;;) { NGX_RWLOCK_MUTEX_COND(lock, (lock->lock != NGX_RWLOCK_WRITE), lock->lock++) #if (DEBUG_NGX_RWLOCK == 1) ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "rwlock %p reserve read read (%i)", lock, lock->lock); #endif if(ngx_ncpu > 1) { for(n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) { for(i = 0; i < n; i++) { ngx_cpu_pause(); } #if (DEBUG_NGX_RWLOCK == 1) ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "rwlock %p read lock wait", lock); #endif NGX_RWLOCK_MUTEX_COND(lock, (lock->lock != NGX_RWLOCK_WRITE), lock->lock++) } } ngx_sched_yield(); } #else #if (NGX_THREADS) #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined ! #endif #endif } void ngx_rwlock_release_read(ngx_rwlock_t *lock) { #if (DISABLE_RWLOCK == 1) rwl_unlock_mutex(lock); #else NGX_RWLOCK_MUTEX_COND(lock, lock->lock != NGX_RWLOCK_WRITE && lock->lock != 0, lock->lock--) #endif } int ngx_rwlock_write_check(ngx_rwlock_t *lock) { if(lock->lock==0) { rwl_lock_mutex(lock); if(lock->lock==0) { lock->lock=NGX_RWLOCK_WRITE; lock->write_pid=ngx_pid; rwl_unlock_mutex(lock); return 1; } rwl_unlock_mutex(lock); } return 0; } void ngx_rwlock_reserve_write(ngx_rwlock_t * lock) { #if (NGX_HAVE_ATOMIC_OPS) ngx_uint_t i, n; #if (DISABLE_RWLOCK == 1) rwl_lock_mutex(lock); return; #endif for(;;) { if(ngx_rwlock_write_check(lock)) return; if(ngx_ncpu > 1) { for(n = 1; n < NGX_RWLOCK_SPIN; n <<= 1) { for(i = 0; i < n; i++) { ngx_cpu_pause(); } #if (DEBUG_NGX_RWLOCK == 1) ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "rwlock %p write lock wait (reserved by %ui)", lock, lock->write_pid); #endif if(ngx_rwlock_write_check(lock)) return; } } ngx_sched_yield(); } #else #if (NGX_THREADS) #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined ! #endif #endif } void ngx_rwlock_release_write(ngx_rwlock_t *lock) { #if (DISABLE_RWLOCK == 1) rwl_unlock_mutex(lock); return; #endif if(lock->lock == NGX_RWLOCK_WRITE) { rwl_lock_mutex(lock); if(lock->lock == NGX_RWLOCK_WRITE) { lock->lock=0; if(lock->write_pid != ngx_pid) { ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "rwlock %p releasing someone else's (pid %ui) write lock.", lock, lock->write_pid); } lock->write_pid = 0; rwl_unlock_mutex(lock); return; } rwl_unlock_mutex(lock); } else { ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "rwlock %p tried to release nonexistent write lock, lock=%i.", lock, lock->lock); } }debian/modules/nginx-http-push/src/store/ngx_http_push_module_ipc.c0000664000000000000000000001364712705233614023114 0ustar //worker processes of the world, unite. #include #include #include static void ngx_http_push_channel_handler(ngx_event_t *ev); #define NGX_CMD_HTTP_PUSH_CHECK_MESSAGES 49 static ngx_socket_t ngx_http_push_socketpairs[NGX_MAX_PROCESSES][2]; ngx_int_t ngx_http_push_init_ipc(ngx_cycle_t *cycle, ngx_int_t workers) { //initialize socketpairs for workers in advance. static int invalid_sockets_initialized = 0; int i, s = 0, on = 1; ngx_int_t last_expected_process = ngx_last_process; if(!invalid_sockets_initialized) { for(i=0; i< NGX_MAX_PROCESSES; i++) { ngx_http_push_socketpairs[i][0]=NGX_INVALID_FILE; ngx_http_push_socketpairs[i][1]=NGX_INVALID_FILE; } invalid_sockets_initialized=1; } /* here's the deal: we have no control over fork()ing, nginx's internal * socketpairs are unusable for our purposes (as of nginx 0.8 -- check the * code to see why), and the module initialization callbacks occur before * any workers are spawned. Rather than futzing around with existing * socketpairs, we populate our own socketpairs array. * Trouble is, ngx_spawn_process() creates them one-by-one, and we need to * do it all at once. So we must guess all the workers' ngx_process_slots in * advance. Meaning the spawning logic must be copied to the T. * ... with some allowances for already-opened sockets... */ for(i=0; i < workers; i++) { //copypasta from os/unix/ngx_process.c (ngx_spawn_process) while (s < last_expected_process && ngx_processes[s].pid != -1) { //find empty existing slot s++; } ngx_socket_t *socks = ngx_http_push_socketpairs[s]; if(socks[0] == NGX_INVALID_FILE || socks[1] == NGX_INVALID_FILE) { //copypasta from os/unix/ngx_process.c (ngx_spawn_process) if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "socketpair() failed on socketpair while initializing push module"); return NGX_ERROR; } if (ngx_nonblocking(socks[0]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed on socketpair while initializing push module"); ngx_close_channel(socks, cycle->log); return NGX_ERROR; } if (ngx_nonblocking(socks[1]) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_nonblocking_n " failed on socketpair while initializing push module"); ngx_close_channel(socks, cycle->log); return NGX_ERROR; } if (ioctl(socks[0], FIOASYNC, &on) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "ioctl(FIOASYNC) failed on socketpair while initializing push module"); ngx_close_channel(socks, cycle->log); return NGX_ERROR; } if (fcntl(socks[0], F_SETOWN, ngx_pid) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(F_SETOWN) failed on socketpair while initializing push module"); ngx_close_channel(socks, cycle->log); return NGX_ERROR; } if (fcntl(socks[0], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed on socketpair while initializing push module"); ngx_close_channel(socks, cycle->log); return NGX_ERROR; } if (fcntl(socks[1], F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) failed while initializing push module"); ngx_close_channel(socks, cycle->log); return NGX_ERROR; } } s++; //NEXT!! } return NGX_OK; } ngx_int_t ngx_http_push_shutdown_ipc(ngx_cycle_t *cycle) { int i; for (i=0; ilog); } } return NGX_OK; } void ngx_http_push_ipc_exit_worker(ngx_cycle_t *cycle) { ngx_http_push_shutdown_ipc(cycle); } ngx_int_t ngx_http_push_ipc_init_worker(ngx_cycle_t *cycle) { if (ngx_add_channel_event(cycle, ngx_http_push_socketpairs[ngx_process_slot][1], NGX_READ_EVENT, ngx_http_push_channel_handler) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "failed to register channel handler while initializing push module worker"); return NGX_ERROR; } return NGX_OK; } static void ngx_http_push_channel_handler(ngx_event_t *ev) { //copypasta from os/unix/ngx_process_cycle.c (ngx_channel_handler) ngx_int_t n; ngx_channel_t ch; ngx_connection_t *c; if (ev->timedout) { ev->timedout = 0; return; } c = ev->data; while(1) { n = ngx_read_channel(c->fd, &ch, sizeof(ch), ev->log); if (n == NGX_ERROR) { if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { ngx_del_conn(c, 0); } ngx_close_connection(c); return; } if ((ngx_event_flags & NGX_USE_EVENTPORT_EVENT) && (ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR)) { return; } if (n == NGX_AGAIN) { return; } //ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "push module: channel command: %d", ch.command); if (ch.command==NGX_CMD_HTTP_PUSH_CHECK_MESSAGES) { ngx_http_push_store->receive_worker_message(); } } } ngx_int_t ngx_http_push_alert_worker(ngx_pid_t pid, ngx_int_t slot) { //seems ch doesn't need to have fd set. odd, but roll with it. pid and process slot also unnecessary. static ngx_channel_t ch = {NGX_CMD_HTTP_PUSH_CHECK_MESSAGES, 0, 0, -1}; return ngx_write_channel(ngx_http_push_socketpairs[slot][0], &ch, sizeof(ngx_channel_t), ngx_cycle->log); } debian/modules/nginx-http-push/src/store/memory/0000775000000000000000000000000012705233614017153 5ustar debian/modules/nginx-http-push/src/store/memory/store.h0000664000000000000000000000007112705233614020456 0ustar extern ngx_http_push_store_t ngx_http_push_store_memory;debian/modules/nginx-http-push/src/store/memory/store.c0000775000000000000000000014013312705233614020460 0ustar #include #include "store.h" #include #include #include #define NGX_HTTP_PUSH_BROADCAST_CHECK(val, fail, r, errormessage) \ if (val == fail) { \ ngx_log_error(NGX_LOG_ERR, (r)->connection->log, 0, errormessage); \ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); \ return NULL; \ } #define NGX_HTTP_PUSH_BROADCAST_CHECK_LOCKED(val, fail, r, errormessage, shpool) \ if (val == fail) { \ ngx_shmtx_unlock(&(shpool)->mutex); \ ngx_log_error(NGX_LOG_ERR, (r)->connection->log, 0, errormessage); \ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); \ return NULL; \ } #define NGX_HTTP_BUF_ALLOC_SIZE(buf) \ (sizeof(*buf) + \ (((buf)->temporary || (buf)->memory) ? ngx_buf_size(buf) : 0) + \ (((buf)->file!=NULL) ? (sizeof(*(buf)->file) + (buf)->file->name.len + 1) : 0)) #define ENQUEUED_DBG "msg %p enqueued. ref:%i, p:%p n:%p" #define CREATED_DBG "msg %p created ref:%i, p:%p n:%p" #define FREED_DBG "msg %p freed. ref:%i, p:%p n:%p" #define RESERVED_DBG "msg %p reserved. ref:%i, p:%p n:%p" #define RELEASED_DBG "msg %p released. ref:%i, p:%p n:%p" //#define DEBUG_SHM_ALLOC 1 static ngx_http_push_channel_queue_t channel_gc_sentinel; static ngx_slab_pool_t *ngx_http_push_shpool = NULL; static ngx_shm_zone_t *ngx_http_push_shm_zone = NULL; static ngx_int_t ngx_http_push_store_send_worker_message(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *subscriber_sentinel, ngx_pid_t pid, ngx_int_t worker_slot, ngx_http_push_msg_t *msg, ngx_int_t status_code); static ngx_int_t ngx_http_push_channel_collector(ngx_http_push_channel_t * channel) { if((ngx_http_push_clean_channel_locked(channel))!=NULL) { //we're up for deletion ngx_http_push_channel_queue_t *trashy; if((trashy = ngx_alloc(sizeof(*trashy), ngx_cycle->log))!=NULL) { //yeah, i'm allocating memory during garbage collection. sue me. trashy->channel=channel; ngx_queue_insert_tail(&channel_gc_sentinel.queue, &trashy->queue); return NGX_OK; } return NGX_ERROR; } return NGX_OK; } static void ngx_http_push_store_lock_shmem(void){ ngx_shmtx_lock(&ngx_http_push_shpool->mutex); } static void ngx_http_push_store_unlock_shmem(void){ ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); } //garbage-collecting slab allocator static void * ngx_http_push_slab_alloc_locked(size_t size, char *label) { void *p; if((p = ngx_slab_alloc_locked(ngx_http_push_shpool, size))==NULL) { ngx_http_push_channel_queue_t *ccur, *cnext; ngx_uint_t collected = 0; //failed. emergency garbage sweep, then. //collect channels ngx_queue_init(&channel_gc_sentinel.queue); ngx_http_push_walk_rbtree(ngx_http_push_channel_collector, ngx_http_push_shm_zone); for(ccur=(ngx_http_push_channel_queue_t *)ngx_queue_next(&channel_gc_sentinel.queue); ccur != &channel_gc_sentinel; ccur=cnext) { cnext = (ngx_http_push_channel_queue_t *)ngx_queue_next(&ccur->queue); ngx_http_push_delete_channel_locked(ccur->channel, ngx_http_push_shm_zone); ngx_free(ccur); collected++; } //todo: collect worker messages maybe ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "push module: out of shared memory. emergency garbage collection deleted %ui unused channels.", collected); p = ngx_slab_alloc_locked(ngx_http_push_shpool, size); } #if (DEBUG_SHM_ALLOC == 1) if (p != NULL) { if(label==NULL) label="none"; ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "shpool alloc addr %p size %ui label %s", p, size, label); } #endif return p; } static void * ngx_http_push_slab_alloc(size_t size, char *label) { void * p; ngx_http_push_store_lock_shmem(); p= ngx_http_push_slab_alloc_locked(size, label); ngx_http_push_store_unlock_shmem(); return p; } static void ngx_http_push_slab_free_locked(void *ptr) { ngx_slab_free_locked(ngx_http_push_shpool, ptr); #if (DEBUG_SHM_ALLOC == 1) ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "shpool free addr %p", ptr); #endif } /* static void ngx_http_push_slab_free(void *ptr) { ngx_http_push_store_lock_shmem(); ngx_http_push_slab_free_locked(ptr); ngx_http_push_store_unlock_shmem(); }*/ //shpool is assumed to be locked. static ngx_http_push_msg_t *ngx_http_push_get_latest_message_locked(ngx_http_push_channel_t * channel) { ngx_queue_t *sentinel = &channel->message_queue->queue; if(ngx_queue_empty(sentinel)) { return NULL; } ngx_queue_t *qmsg = ngx_queue_last(sentinel); return ngx_queue_data(qmsg, ngx_http_push_msg_t, queue); } //shpool must be locked. No memory is freed. O(1) static ngx_http_push_msg_t *ngx_http_push_get_oldest_message_locked(ngx_http_push_channel_t * channel) { ngx_queue_t *sentinel = &channel->message_queue->queue; if(ngx_queue_empty(sentinel)) { return NULL; } ngx_queue_t *qmsg = ngx_queue_head(sentinel); return ngx_queue_data(qmsg, ngx_http_push_msg_t, queue); } static void ngx_http_push_store_reserve_message_locked(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg) { if(msg == NULL) { return; } msg->refcount++; //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, RESERVED_DBG, msg, msg->refcount, msg->queue.prev, msg->queue.next); //we need a refcount because channel messages MAY be dequed before they are used up. It thus falls on the IPC stuff to free it. } static void ngx_http_push_store_reserve_message_num_locked(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_int_t reservations) { if(msg == NULL) { return; } msg->refcount+=reservations; //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, RESERVED_DBG, msg, msg->refcount, msg->queue.prev, msg->queue.next); //we need a refcount because channel messages MAY be dequed before they are used up. It thus falls on the IPC stuff to free it. } static void ngx_http_push_store_reserve_message(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg) { ngx_shmtx_lock(&ngx_http_push_shpool->mutex); ngx_http_push_store_reserve_message_locked(channel, msg); ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); //we need a refcount because channel messages MAY be dequed before they are used up. It thus falls on the IPC stuff to free it. } //free memory for a message. static ngx_inline void ngx_http_push_free_message_locked(ngx_http_push_msg_t *msg, ngx_slab_pool_t *shpool) { if(msg->buf->file!=NULL) { // i'd like to release the shpool lock here while i do stuff to this file, but that // might unlock during channel rbtree traversal, which is Bad News. if(msg->buf->file->fd!=NGX_INVALID_FILE) { ngx_close_file(msg->buf->file->fd); } ngx_delete_file(msg->buf->file->name.data); //should I care about deletion errors? doubt it. } ngx_http_push_slab_free_locked(msg->buf); //separate block, remember? ngx_http_push_slab_free_locked(msg); //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, FREED_DBG, msg, msg->refcount, msg->queue.prev, msg->queue.next); if(msg->refcount < 0) { //something worth exploring went wrong raise(SIGSEGV); } ((ngx_http_push_shm_data_t *) ngx_http_push_shm_zone->data)->messages--; } // remove a message from queue and free all associated memory. assumes shpool is already locked. static ngx_int_t ngx_http_push_delete_message_locked(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_int_t force) { if (msg==NULL) { return NGX_OK; } if(channel!=NULL) { ngx_queue_remove(&msg->queue); channel->messages--; } if(msg->refcount<=0 || force) { //nobody needs this message, or we were forced at integer-point to delete ngx_http_push_free_message_locked(msg, ngx_http_push_shpool); } return NGX_OK; } static void ngx_http_push_store_release_message_locked(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg) { if(msg == NULL) { return; } msg->refcount--; //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, RELEASED_DBG, msg, msg->refcount, msg->queue.prev, msg->queue.next); if(msg->queue.next==NULL && msg->refcount<=0) { //message had been dequeued and nobody needs it anymore ngx_http_push_free_message_locked(msg, ngx_http_push_shpool); } if(channel != NULL && channel->messages > msg->delete_oldest_received_min_messages && ngx_http_push_get_oldest_message_locked(channel) == msg) { ngx_http_push_delete_message_locked(channel, msg, 0); } } static void ngx_http_push_store_release_message(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg) { ngx_shmtx_lock(&ngx_http_push_shpool->mutex); ngx_http_push_store_release_message_locked(channel, msg); ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); } static ngx_int_t ngx_http_push_delete_message(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_int_t force) { ngx_int_t ret; ngx_shmtx_lock(&ngx_http_push_shpool->mutex); ret = ngx_http_push_delete_message_locked(channel, msg, force); ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); return ret; } /** find message with entity tags matching those of the request r. * @param r subscriber request */ static ngx_http_push_msg_t * ngx_http_push_find_message_locked(ngx_http_push_channel_t *channel, ngx_http_push_msg_id_t *msgid, ngx_int_t *status) { //TODO: consider using an RBTree for message storage. ngx_queue_t *sentinel = &channel->message_queue->queue; ngx_queue_t *cur = ngx_queue_head(sentinel); ngx_http_push_msg_t *msg; time_t time = msgid->time; ngx_int_t tag = msgid->tag; //channel's message buffer empty? if(channel->messages==0) { *status=NGX_HTTP_PUSH_MESSAGE_EXPECTED; //wait. return NULL; } // do we want a future message? msg = ngx_queue_data(sentinel->prev, ngx_http_push_msg_t, queue); if(time <= msg->message_time) { //that's an empty check (Sentinel's values are zero) if(time == msg->message_time) { if(tag >= msg->message_tag) { *status=NGX_HTTP_PUSH_MESSAGE_EXPECTED; return NULL; } } } else { *status=NGX_HTTP_PUSH_MESSAGE_EXPECTED; return NULL; } while(cur!=sentinel) { msg = ngx_queue_data(cur, ngx_http_push_msg_t, queue); if (time < msg->message_time) { *status = NGX_HTTP_PUSH_MESSAGE_FOUND; return msg; } else if(time == msg->message_time) { while (tag >= msg->message_tag && time == msg->message_time && ngx_queue_next(cur)!=sentinel) { cur=ngx_queue_next(cur); msg = ngx_queue_data(cur, ngx_http_push_msg_t, queue); } if(time == msg->message_time && tag < msg->message_tag) { *status = NGX_HTTP_PUSH_MESSAGE_FOUND; return msg; } continue; } cur=ngx_queue_next(cur); } *status = NGX_HTTP_PUSH_MESSAGE_EXPIRED; //message too old and was not found. return NULL; } static ngx_http_push_channel_t * ngx_http_push_store_find_channel(ngx_str_t *id, time_t channel_timeout, ngx_int_t (*callback)(ngx_http_push_channel_t *channel)) { //get the channel and check channel authorization while we're at it. ngx_http_push_channel_t *channel; ngx_shmtx_lock(&ngx_http_push_shpool->mutex); channel = ngx_http_push_find_channel(id, channel_timeout, ngx_http_push_shm_zone); ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); if(callback!=NULL) { callback(channel); } return channel; } //temporary cheat static ngx_int_t ngx_http_push_store_publish_raw(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_int_t status_code, const ngx_str_t *status_line) { //subscribers are queued up in a local pool. Queue heads, however, are located //in shared memory, identified by pid. ngx_shmtx_lock(&ngx_http_push_shpool->mutex); ngx_http_push_pid_queue_t *sentinel = channel->workers_with_subscribers; ngx_http_push_subscriber_t *subscriber_sentinels[NGX_MAX_PROCESSES]; ngx_http_push_pid_queue_t *pid_queues[NGX_MAX_PROCESSES]; ngx_int_t sub_sentinel_count=0; ngx_http_push_pid_queue_t *cur; ngx_int_t i, received; received = channel->subscribers > 0 ? NGX_HTTP_PUSH_MESSAGE_RECEIVED : NGX_HTTP_PUSH_MESSAGE_QUEUED; //we need to reserve the message for all the workers in advance for(cur=(ngx_http_push_pid_queue_t *)ngx_queue_next(&sentinel->queue); cur != sentinel; cur=(ngx_http_push_pid_queue_t *)ngx_queue_next(&cur->queue)) { if(cur->subscriber_sentinel != NULL) { pid_queues[sub_sentinel_count] = cur; subscriber_sentinels[sub_sentinel_count] = cur->subscriber_sentinel; /* * each time all of a worker's subscribers are removed, so is the sentinel. * this is done to make garbage collection easier. Assuming we want to avoid * placing the sentinel in shared memory (for now -- it's a little tricky * to debug), the owner of the worker pool must be the one to free said sentinel. * But channels may be deleted by different worker processes, and it seems unwieldy * (for now) to do IPC just to delete one stinkin' sentinel. Hence a new sentinel * is used every time the subscriber queue is emptied. */ cur->subscriber_sentinel = NULL; //think about it it terms of garbage collection. it'll make sense. sort of. sub_sentinel_count++; } } if(sub_sentinel_count > 0) { ngx_http_push_store_reserve_message_num_locked(channel, msg, sub_sentinel_count); } ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); ngx_http_push_subscriber_t *subscriber_sentinel=NULL; for(i=0; i < sub_sentinel_count; i++) { ngx_shmtx_lock(&ngx_http_push_shpool->mutex); subscriber_sentinel = subscriber_sentinels[i]; pid_t worker_pid = pid_queues[i]->pid; ngx_int_t worker_slot = pid_queues[i]->slot; ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); //if(msg != NULL) // ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "publish msg %p (ref: %i) for worker %i (slot %i)", msg, msg->refcount, worker_pid, worker_slot); if(subscriber_sentinel != NULL) { if(worker_pid == ngx_pid) { //my subscribers ngx_http_push_respond_to_subscribers(channel, subscriber_sentinel, msg, status_code, status_line); } else { //some other worker's subscribers //interprocess communication breakdown if(ngx_http_push_store_send_worker_message(channel, subscriber_sentinel, worker_pid, worker_slot, msg, status_code) != NGX_ERROR) { ngx_http_push_alert_worker(worker_pid, worker_slot); } else { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: error communicating with some other worker process"); } } } else { //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "subscriber sentinel is NULL"); } } return received; } static ngx_int_t ngx_http_push_store_delete_channel(ngx_str_t *channel_id) { ngx_http_push_channel_t *channel; ngx_http_push_msg_t *msg, *sentinel; ngx_http_push_store_lock_shmem(); channel = ngx_http_push_find_channel(channel_id, NGX_HTTP_PUSH_DEFAULT_CHANNEL_TIMEOUT, ngx_http_push_shm_zone); if (channel == NULL) { ngx_http_push_store_unlock_shmem(); return NGX_OK; } sentinel = channel->message_queue; msg = sentinel; while((msg=(ngx_http_push_msg_t *)ngx_queue_next(&msg->queue))!=sentinel) { //force-delete all the messages ngx_http_push_delete_message_locked(NULL, msg, 1); } channel->messages=0; //410 gone ngx_http_push_store_unlock_shmem(); ngx_http_push_store_publish_raw(channel, NULL, NGX_HTTP_GONE, &NGX_HTTP_PUSH_HTTP_STATUS_410); ngx_http_push_store_lock_shmem(); ngx_http_push_delete_channel_locked(channel, ngx_http_push_shm_zone); ngx_http_push_store_unlock_shmem(); return NGX_OK; } static ngx_http_push_channel_t * ngx_http_push_store_get_channel(ngx_str_t *id, time_t channel_timeout, ngx_int_t (*callback)(ngx_http_push_channel_t *channel)) { //get the channel and check channel authorization while we're at it. ngx_http_push_channel_t *channel; ngx_shmtx_lock(&ngx_http_push_shpool->mutex); channel = ngx_http_push_get_channel(id, channel_timeout, ngx_http_push_shm_zone); ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); if(channel==NULL) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate memory for new channel"); } if(callback!=NULL) { callback(channel); } return channel; } static ngx_http_push_msg_t * ngx_http_push_store_get_channel_message(ngx_http_push_channel_t *channel, ngx_http_push_msg_id_t *msgid, ngx_int_t *msg_search_outcome, ngx_http_push_loc_conf_t *cf) { ngx_http_push_msg_t *msg; ngx_shmtx_lock(&ngx_http_push_shpool->mutex); msg = ngx_http_push_find_message_locked(channel, msgid, msg_search_outcome); if(*msg_search_outcome == NGX_HTTP_PUSH_MESSAGE_FOUND) { ngx_http_push_store_reserve_message_locked(channel, msg); } channel->last_seen = ngx_time(); channel->expires = ngx_time() + cf->channel_timeout; ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); return msg; } static ngx_int_t default_get_message_callback(ngx_http_push_msg_t *msg, ngx_int_t msg_search_outcome, ngx_http_request_t *r) { return NGX_OK; } static ngx_http_push_msg_t * ngx_http_push_store_get_message(ngx_str_t *channel_id, ngx_http_push_msg_id_t *msg_id, ngx_int_t *msg_search_outcome, ngx_http_request_t *r, ngx_int_t (*callback)(ngx_http_push_msg_t *msg, ngx_int_t msg_search_outcome, ngx_http_request_t *r)) { ngx_http_push_channel_t *channel; ngx_http_push_msg_t *msg; if(callback==NULL) { callback=&default_get_message_callback; } ngx_http_push_store_lock_shmem(); channel = ngx_http_push_get_channel(channel_id, NGX_HTTP_PUSH_DEFAULT_CHANNEL_TIMEOUT, ngx_http_push_shm_zone); ngx_http_push_store_unlock_shmem(); if (channel == NULL) { return NULL; } msg = ngx_http_push_store_get_channel_message(channel, msg_id, msg_search_outcome, ngx_http_get_module_loc_conf(r, ngx_http_push_module)); callback(msg, *msg_search_outcome, r); return msg; } // shared memory zone initializer static ngx_int_t ngx_http_push_init_shm_zone(ngx_shm_zone_t * shm_zone, void *data) { if(data) { /* zone already initialized */ shm_zone->data = data; return NGX_OK; } ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; ngx_rbtree_node_t *sentinel; ngx_http_push_shm_data_t *d; ngx_http_push_shpool = shpool; //we'll be using this a bit. #if (DEBUG_SHM_ALLOC == 1) ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "ngx_http_push_shpool start %p size %i", shpool->start, (u_char *)shpool->end - (u_char *)shpool->start); #endif if ((d = (ngx_http_push_shm_data_t *)ngx_http_push_slab_alloc(sizeof(*d), "shm data")) == NULL) { //shm_data return NGX_ERROR; } d->channels=0; d->messages=0; shm_zone->data = d; d->ipc=NULL; //initialize rbtree if ((sentinel = ngx_http_push_slab_alloc(sizeof(*sentinel), "channel rbtree sentinel"))==NULL) { return NGX_ERROR; } ngx_rbtree_init(&d->tree, sentinel, ngx_http_push_rbtree_insert); return NGX_OK; } //shared memory static ngx_str_t ngx_push_shm_name = ngx_string("push_module"); //shared memory segment name static ngx_int_t ngx_http_push_set_up_shm(ngx_conf_t *cf, size_t shm_size) { ngx_http_push_shm_zone = ngx_shared_memory_add(cf, &ngx_push_shm_name, shm_size, &ngx_http_push_module); if (ngx_http_push_shm_zone == NULL) { return NGX_ERROR; } ngx_http_push_shm_zone->init = ngx_http_push_init_shm_zone; ngx_http_push_shm_zone->data = (void *) 1; return NGX_OK; } //initialization static ngx_int_t ngx_http_push_store_init_module(ngx_cycle_t *cycle) { ngx_core_conf_t *ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_http_push_worker_processes = ccf->worker_processes; //initialize our little IPC return ngx_http_push_init_ipc(cycle, ngx_http_push_worker_processes); } //will be called once per worker static ngx_int_t ngx_http_push_store_init_ipc_shm(ngx_int_t workers) { ngx_slab_pool_t *shpool = (ngx_slab_pool_t *) ngx_http_push_shm_zone->shm.addr; ngx_http_push_shm_data_t *d = (ngx_http_push_shm_data_t *) ngx_http_push_shm_zone->data; ngx_http_push_worker_msg_sentinel_t *worker_messages=NULL; ngx_shmtx_lock(&shpool->mutex); if(d->ipc==NULL) { //ipc uninitialized. get it done! if((worker_messages = ngx_http_push_slab_alloc_locked(sizeof(*worker_messages)*NGX_MAX_PROCESSES, "IPC worker message sentinel array"))==NULL) { ngx_shmtx_unlock(&shpool->mutex); return NGX_ERROR; } d->ipc=worker_messages; } else { worker_messages=d->ipc; } ngx_queue_init(&worker_messages[ngx_process_slot].queue); ngx_rwlock_init(&worker_messages[ngx_process_slot].lock); ngx_shmtx_unlock(&shpool->mutex); return NGX_OK; } static ngx_int_t ngx_http_push_store_init_worker(ngx_cycle_t *cycle) { ngx_core_conf_t *ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if(ngx_http_push_store_init_ipc_shm(ccf->worker_processes) == NGX_OK) { return ngx_http_push_ipc_init_worker(cycle); } else { return NGX_ERROR; } } static ngx_int_t ngx_http_push_store_init_postconfig(ngx_conf_t *cf) { ngx_http_push_main_conf_t *conf = ngx_http_conf_get_module_main_conf(cf, ngx_http_push_module); //initialize shared memory size_t shm_size; if(conf->shm_size==NGX_CONF_UNSET_SIZE) { conf->shm_size=NGX_HTTP_PUSH_DEFAULT_SHM_SIZE; } shm_size = ngx_align(conf->shm_size, ngx_pagesize); if (shm_size < 8 * ngx_pagesize) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The push_max_reserved_memory value must be at least %udKiB", (8 * ngx_pagesize) >> 10); shm_size = 8 * ngx_pagesize; } if(ngx_http_push_shm_zone && ngx_http_push_shm_zone->shm.size != shm_size) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "Cannot change memory area size without restart, ignoring change"); } ngx_conf_log_error(NGX_LOG_INFO, cf, 0, "Using %udKiB of shared memory for push module", shm_size >> 10); return ngx_http_push_set_up_shm(cf, shm_size); } static void ngx_http_push_store_create_main_conf(ngx_conf_t *cf, ngx_http_push_main_conf_t *mcf) { mcf->shm_size=NGX_CONF_UNSET_SIZE; } //great justice appears to be at hand static ngx_int_t ngx_http_push_movezig_channel_locked(ngx_http_push_channel_t * channel) { ngx_queue_t *sentinel = &channel->message_queue->queue; ngx_http_push_msg_t *msg=NULL; while(!ngx_queue_empty(sentinel)) { msg = ngx_queue_data(ngx_queue_head(sentinel), ngx_http_push_msg_t, queue); ngx_http_push_delete_message_locked(channel, msg, 1); } return NGX_OK; } static ngx_int_t ngx_http_push_store_channel_subscribers(ngx_http_push_channel_t * channel) { ngx_int_t subs; ngx_shmtx_lock(&ngx_http_push_shpool->mutex); subs = channel->subscribers; ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); return subs; } static ngx_int_t ngx_http_push_store_channel_worker_subscribers(ngx_http_push_subscriber_t * worker_sentinel) { ngx_http_push_subscriber_t *cur; ngx_int_t count=0; cur=(ngx_http_push_subscriber_t *)ngx_queue_head(&worker_sentinel->queue); while(cur!=worker_sentinel) { count++; cur=(ngx_http_push_subscriber_t *)ngx_queue_next(&cur->queue); } return count; } static ngx_http_push_subscriber_t *ngx_http_push_store_channel_next_subscriber(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *sentinel, ngx_http_push_subscriber_t *cur, int release_previous) { ngx_http_push_subscriber_t *next; if(cur==NULL) { next=(ngx_http_push_subscriber_t *)ngx_queue_head(&sentinel->queue); } else{ next=(ngx_http_push_subscriber_t *)ngx_queue_next(&cur->queue); if(release_previous==1 && cur!=sentinel) { //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "freeing subscriber cursor at %p.", cur); ngx_pfree(ngx_http_push_pool, cur); } } return next!=sentinel ? next : NULL; } static ngx_int_t ngx_http_push_store_channel_release_subscriber_sentinel(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *sentinel) { //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "freeing subscriber sentinel at %p.", sentinel); ngx_pfree(ngx_http_push_pool, sentinel); return NGX_OK; } static void ngx_http_push_store_exit_worker(ngx_cycle_t *cycle) { ngx_http_push_ipc_exit_worker(cycle); } static void ngx_http_push_store_exit_master(ngx_cycle_t *cycle) { //destroy channel tree in shared memory ngx_http_push_walk_rbtree(ngx_http_push_movezig_channel_locked, ngx_http_push_shm_zone); //deinitialize IPC ngx_http_push_shutdown_ipc(cycle); } static ngx_http_push_subscriber_t * ngx_http_push_store_subscribe_raw(ngx_http_push_channel_t *channel, ngx_http_request_t *r) { ngx_http_push_pid_queue_t *sentinel, *cur, *found; ngx_http_push_subscriber_t *subscriber; ngx_http_push_subscriber_t *subscriber_sentinel; //ngx_http_push_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_module); //subscribers are queued up in a local pool. Queue sentinels are separate and also local, but not in the pool. ngx_shmtx_lock(&ngx_http_push_shpool->mutex); sentinel = channel->workers_with_subscribers; cur = (ngx_http_push_pid_queue_t *)ngx_queue_head(&sentinel->queue); found = NULL; while(cur!=sentinel) { if(cur->pid==ngx_pid) { found = cur; break; } cur = (ngx_http_push_pid_queue_t *)ngx_queue_next(&cur->queue); } if(found == NULL) { //found nothing if((found=ngx_http_push_slab_alloc_locked(sizeof(*found), "worker subscriber sentinel"))==NULL) { ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: unable to allocate worker subscriber queue marker in shared memory"); return NULL; } //initialize ngx_queue_insert_tail(&sentinel->queue, &found->queue); found->pid=ngx_pid; found->slot=ngx_process_slot; found->subscriber_sentinel=NULL; } if((subscriber = ngx_palloc(ngx_http_push_pool, sizeof(*subscriber)))==NULL) { //unable to allocate request queue element ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: unable to allocate subscriber worker's memory pool"); return NULL; } channel->subscribers++; // do this only when we know everything went okay. //figure out the subscriber sentinel subscriber_sentinel = ((ngx_http_push_pid_queue_t *)found)->subscriber_sentinel; //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "reserve subscriber sentinel at %p", subscriber_sentinel); if(subscriber_sentinel==NULL) { //it's perfectly normal for the sentinel to be NULL. if((subscriber_sentinel=ngx_palloc(ngx_http_push_pool, sizeof(*subscriber_sentinel)))==NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: unable to allocate channel subscriber sentinel"); return NULL; } ngx_queue_init(&subscriber_sentinel->queue); ((ngx_http_push_pid_queue_t *)found)->subscriber_sentinel=subscriber_sentinel; } //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "add to subscriber sentinel at %p", subscriber_sentinel); ngx_queue_insert_tail(&subscriber_sentinel->queue, &subscriber->queue); ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); subscriber->request = r; return subscriber; } static ngx_int_t ngx_http_push_handle_subscriber_concurrency(ngx_http_push_channel_t *channel, ngx_http_request_t *r, ngx_http_push_loc_conf_t *cf) { ngx_int_t max_subscribers = cf->max_channel_subscribers; ngx_int_t current_subscribers = ngx_http_push_store->channel_subscribers(channel) ; if(current_subscribers==0) { //empty channels are always okay. return NGX_OK; } if(max_subscribers!=0 && current_subscribers >= max_subscribers) { //max_channel_subscribers setting ngx_http_push_respond_status_only(r, NGX_HTTP_FORBIDDEN, NULL); return NGX_DECLINED; } //nonzero number of subscribers present switch(cf->subscriber_concurrency) { case NGX_HTTP_PUSH_SUBSCRIBER_CONCURRENCY_BROADCAST: return NGX_OK; case NGX_HTTP_PUSH_SUBSCRIBER_CONCURRENCY_LASTIN: //send "everyone" a 409 Conflict response. //in most reasonable cases, there'll be at most one subscriber on the //channel. However, since settings are bound to locations and not //specific channels, this assumption need not hold. Hence this broadcast. ngx_http_push_store_publish_raw(channel, NULL, NGX_HTTP_NOT_FOUND, &NGX_HTTP_PUSH_HTTP_STATUS_409); return NGX_OK; case NGX_HTTP_PUSH_SUBSCRIBER_CONCURRENCY_FIRSTIN: ngx_http_push_respond_status_only(r, NGX_HTTP_NOT_FOUND, &NGX_HTTP_PUSH_HTTP_STATUS_409); return NGX_DECLINED; default: return NGX_ERROR; } } static ngx_int_t default_subscribe_callback(ngx_int_t status, ngx_http_request_t *r) { return status; } static ngx_int_t ngx_http_push_store_subscribe(ngx_str_t *channel_id, ngx_http_push_msg_id_t *msg_id, ngx_http_request_t *r, ngx_int_t (*callback)(ngx_int_t status, ngx_http_request_t *r)) { ngx_http_push_channel_t *channel; ngx_http_push_msg_t *msg; ngx_int_t msg_search_outcome; ngx_http_push_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_module); if(callback == NULL) { callback=&default_subscribe_callback; } if (cf->authorize_channel==1) { channel = ngx_http_push_store_find_channel(channel_id, cf->channel_timeout, NULL); }else{ channel = ngx_http_push_store_get_channel(channel_id, cf->channel_timeout, NULL); } if (channel==NULL) { //unable to allocate channel OR channel not found if(cf->authorize_channel) { return callback(NGX_HTTP_FORBIDDEN, r); } else { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate shared memory for channel"); return callback(NGX_HTTP_INTERNAL_SERVER_ERROR, r); } } switch(ngx_http_push_handle_subscriber_concurrency(channel, r, cf)) { case NGX_DECLINED: //this request was declined for some reason. //status codes and whatnot should have already been written. just get out of here quickly. return callback(NGX_OK, r); case NGX_ERROR: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: error handling subscriber concurrency setting"); return callback(NGX_ERROR, r); } msg = ngx_http_push_store->get_channel_message(channel, msg_id, &msg_search_outcome, cf); if (cf->ignore_queue_on_no_cache && !ngx_http_push_allow_caching(r)) { msg_search_outcome = NGX_HTTP_PUSH_MESSAGE_EXPECTED; msg = NULL; } switch(msg_search_outcome) { //for message-found: ngx_str_t *etag; ngx_str_t *content_type; ngx_chain_t *chain; time_t last_modified; ngx_http_push_subscriber_t *subscriber; case NGX_HTTP_PUSH_MESSAGE_EXPECTED: // ♫ It's gonna be the future soon ♫ if ((subscriber = ngx_http_push_store_subscribe_raw(channel, r))==NULL) { return callback(NGX_HTTP_INTERNAL_SERVER_ERROR, r); } if(ngx_push_longpoll_subscriber_enqueue(channel, subscriber, cf->subscriber_timeout) == NGX_OK) { return callback(NGX_DONE, r); } else { return callback(NGX_ERROR, r); } case NGX_HTTP_PUSH_MESSAGE_EXPIRED: //subscriber wants an expired message //TODO: maybe respond with entity-identifiers for oldest available message? return callback(NGX_HTTP_NO_CONTENT, r); case NGX_HTTP_PUSH_MESSAGE_FOUND: ngx_http_push_alloc_for_subscriber_response(r->pool, 0, msg, &chain, &content_type, &etag, &last_modified); ngx_int_t ret=ngx_http_push_prepare_response_to_subscriber_request(r, chain, content_type, etag, last_modified); ngx_http_push_store->release_message(channel, msg); return callback(ret, r); default: //we shouldn't be here. return callback(NGX_HTTP_INTERNAL_SERVER_ERROR, r); } } static ngx_str_t * ngx_http_push_store_etag_from_message(ngx_http_push_msg_t *msg, ngx_pool_t *pool){ ngx_str_t *etag; ngx_shmtx_lock(&ngx_http_push_shpool->mutex); if(pool!=NULL && (etag = ngx_palloc(pool, sizeof(*etag) + NGX_INT_T_LEN))==NULL) { return NULL; } else if(pool==NULL && (etag = ngx_alloc(sizeof(*etag) + NGX_INT_T_LEN, ngx_cycle->log))==NULL) { return NULL; } etag->data = (u_char *)(etag+1); etag->len = ngx_sprintf(etag->data,"%ui", msg->message_tag)- etag->data; ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); return etag; } static ngx_str_t * ngx_http_push_store_content_type_from_message(ngx_http_push_msg_t *msg, ngx_pool_t *pool){ ngx_str_t *content_type; ngx_shmtx_lock(&ngx_http_push_shpool->mutex); if(pool != NULL && (content_type = ngx_palloc(pool, sizeof(*content_type) + msg->content_type.len))==NULL) { return NULL; } else if(pool == NULL && (content_type = ngx_alloc(sizeof(*content_type) + msg->content_type.len, ngx_cycle->log))==NULL) { return NULL; } content_type->data = (u_char *)(content_type+1); content_type->len = msg->content_type.len; ngx_memcpy(content_type->data, msg->content_type.data, content_type->len); ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); return content_type; } // this function adapted from push stream module. thanks Wandenberg Peixoto and Rogério Carvalho Schneider static ngx_buf_t * ngx_http_push_request_body_to_single_buffer(ngx_http_request_t *r) { ngx_buf_t *buf = NULL; ngx_chain_t *chain; ssize_t n; off_t len; chain = r->request_body->bufs; if (chain->next == NULL) { return chain->buf; } if (chain->buf->in_file) { if (ngx_buf_in_memory(chain->buf)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: can't handle a buffer in a temp file and in memory "); } if (chain->next != NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: error reading request body with multiple "); } return chain->buf; } buf = ngx_create_temp_buf(r->pool, r->headers_in.content_length_n + 1); if (buf != NULL) { ngx_memset(buf->start, '\0', r->headers_in.content_length_n + 1); while ((chain != NULL) && (chain->buf != NULL)) { len = ngx_buf_size(chain->buf); // if buffer is equal to content length all the content is in this buffer if (len >= r->headers_in.content_length_n) { buf->start = buf->pos; buf->last = buf->pos; len = r->headers_in.content_length_n; } if (chain->buf->in_file) { n = ngx_read_file(chain->buf->file, buf->start, len, 0); if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: cannot read file with request body"); return NULL; } buf->last = buf->last + len; ngx_delete_file(chain->buf->file->name.data); chain->buf->file->fd = NGX_INVALID_FILE; } else { buf->last = ngx_copy(buf->start, chain->buf->pos, len); } chain = chain->next; buf->start = buf->last; } } return buf; } static ngx_http_push_msg_t * ngx_http_push_store_create_message(ngx_http_push_channel_t *channel, ngx_http_request_t *r) { ngx_buf_t *buf = NULL, *buf_copy; size_t content_type_len; ngx_http_push_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_module); ngx_http_push_msg_t *msg, *previous_msg; //first off, we'll want to extract the body buffer //note: this works mostly because of r->request_body_in_single_buf = 1; //which, i suppose, makes this module a little slower than it could be. //this block is a little hacky. might be a thorn for forward-compatibility. if(r->headers_in.content_length_n == -1 || r->headers_in.content_length_n == 0) { buf = ngx_create_temp_buf(r->pool, 0); //this buffer will get copied to shared memory in a few lines, //so it does't matter what pool we make it in. } else if(r->request_body->bufs!=NULL) { buf = ngx_http_push_request_body_to_single_buffer(r); } else { ngx_log_error(NGX_LOG_ERR, (r)->connection->log, 0, "push module: unexpected publisher message request body buffer location. please report this to the push module developers."); return NULL; } NGX_HTTP_PUSH_BROADCAST_CHECK(buf, NULL, r, "push module: can't find or allocate publisher request body buffer"); content_type_len = (r->headers_in.content_type!=NULL ? r->headers_in.content_type->value.len : 0); ngx_shmtx_lock(&ngx_http_push_shpool->mutex); //create a buffer copy in shared mem msg = ngx_http_push_slab_alloc_locked(sizeof(*msg) + content_type_len, "message + content_type"); NGX_HTTP_PUSH_BROADCAST_CHECK_LOCKED(msg, NULL, r, "push module: unable to allocate message in shared memory", ngx_http_push_shpool); previous_msg=ngx_http_push_get_latest_message_locked(channel); //need this for entity-tags generation buf_copy = ngx_http_push_slab_alloc_locked(NGX_HTTP_BUF_ALLOC_SIZE(buf), "message buffer copy"); NGX_HTTP_PUSH_BROADCAST_CHECK_LOCKED(buf_copy, NULL, r, "push module: unable to allocate buffer in shared memory", ngx_http_push_shpool) //magic nullcheck ngx_http_push_copy_preallocated_buffer(buf, buf_copy); msg->buf=buf_copy; //Stamp the new message with entity tags msg->message_time=ngx_time(); //ESSENTIAL TODO: make sure this ends up producing GMT time msg->message_tag=(previous_msg!=NULL && msg->message_time == previous_msg->message_time) ? (previous_msg->message_tag + 1) : 0; //store the content-type if(content_type_len>0) { msg->content_type.len=r->headers_in.content_type->value.len; msg->content_type.data=(u_char *) (msg+1); //we had reserved a contiguous chunk, myes? ngx_memcpy(msg->content_type.data, r->headers_in.content_type->value.data, msg->content_type.len); } else { msg->content_type.len=0; msg->content_type.data=NULL; } //queue stuff ought to be NULL msg->queue.prev=NULL; msg->queue.next=NULL; msg->refcount=0; //set message expiration time time_t message_timeout = cf->buffer_timeout; msg->expires = (message_timeout==0 ? 0 : (ngx_time() + message_timeout)); msg->delete_oldest_received_min_messages = cf->delete_oldest_received_message ? (ngx_uint_t) cf->min_messages : NGX_MAX_UINT32_VALUE; //NGX_MAX_UINT32_VALUE to disable, otherwise = min_message_buffer_size of the publisher location from whence the message came ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, CREATED_DBG, msg, msg->refcount, msg->queue.prev, msg->queue.next); return msg; } static ngx_int_t ngx_http_push_store_enqueue_message(ngx_http_push_channel_t *channel, ngx_http_push_msg_t *msg, ngx_http_push_loc_conf_t *cf) { ngx_shmtx_lock(&ngx_http_push_shpool->mutex); ngx_queue_insert_tail(&channel->message_queue->queue, &msg->queue); channel->messages++; //now see if the queue is too big if(channel->messages > (ngx_uint_t) cf->max_messages) { //exceeeds max queue size. don't force it, someone might still be using this message. ngx_http_push_delete_message_locked(channel, ngx_http_push_get_oldest_message_locked(channel), 0); } if(channel->messages > (ngx_uint_t) cf->min_messages) { //exceeeds min queue size. maybe delete the oldest message //no, don't do anything for now. This feature is badly implemented and I think I'll deprecate it. } ngx_shmtx_unlock(&ngx_http_push_shpool->mutex); //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, ENQUEUED_DBG, msg, msg->refcount, msg->queue.prev, msg->queue.next); return NGX_OK; } static ngx_int_t default_publish_callback(ngx_int_t status, ngx_http_push_channel_t *ch, ngx_http_request_t *r) { return status; } static ngx_int_t ngx_http_push_store_publish_message(ngx_str_t *channel_id, ngx_http_request_t *r, ngx_int_t (*callback)(ngx_int_t status, ngx_http_push_channel_t *ch, ngx_http_request_t *r)) { ngx_http_push_channel_t *channel; ngx_http_push_msg_t *msg; ngx_http_push_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_module); ngx_int_t result=0; if(callback==NULL) { callback=&default_publish_callback; } if((channel=ngx_http_push_store_get_channel(channel_id, cf->channel_timeout, NULL))==NULL) { //always returns a channel, unless no memory left return callback(NGX_ERROR, NULL, r); //ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); } if((msg = ngx_http_push_store_create_message(channel, r))==NULL) { return callback(NGX_ERROR, channel, r); //ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); } if(cf->max_messages > 0) { //channel buffers exist ngx_http_push_store_enqueue_message(channel, msg, cf); } else if(cf->max_messages == 0) { ngx_http_push_store_reserve_message(NULL, msg); } result= ngx_http_push_store_publish_raw(channel, msg, 0, NULL); return callback(result, channel, r); } static ngx_int_t ngx_http_push_store_send_worker_message(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *subscriber_sentinel, ngx_pid_t pid, ngx_int_t worker_slot, ngx_http_push_msg_t *msg, ngx_int_t status_code) { ngx_http_push_worker_msg_sentinel_t *worker_messages = ((ngx_http_push_shm_data_t *)ngx_http_push_shm_zone->data)->ipc; ngx_http_push_worker_msg_sentinel_t *sentinel = &worker_messages[worker_slot]; ngx_http_push_worker_msg_t *newmessage; if((newmessage=ngx_http_push_slab_alloc(sizeof(*newmessage), "IPC worker message"))==NULL) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate worker message"); return NGX_ERROR; } newmessage->msg = msg; newmessage->status_code = status_code; newmessage->pid = pid; newmessage->subscriber_sentinel = subscriber_sentinel; newmessage->channel = channel; ngx_http_push_store_lock_shmem(); ngx_queue_insert_tail(&sentinel->queue, &newmessage->queue); ngx_http_push_store_unlock_shmem(); return NGX_OK; } static void ngx_http_push_store_receive_worker_message(void) { ngx_http_push_worker_msg_t *prev_worker_msg, *worker_msg; ngx_http_push_worker_msg_sentinel_t *sentinel; const ngx_str_t *status_line = NULL; ngx_http_push_channel_t *channel; ngx_http_push_subscriber_t *subscriber_sentinel; ngx_int_t worker_msg_pid; ngx_int_t status_code; ngx_http_push_msg_t *msg; sentinel = &(((ngx_http_push_shm_data_t *)ngx_http_push_shm_zone->data)->ipc)[ngx_process_slot]; ngx_http_push_store_lock_shmem(); worker_msg = (ngx_http_push_worker_msg_t *)ngx_queue_next(&sentinel->queue); ngx_http_push_store_unlock_shmem(); while((void *)worker_msg != (void *)sentinel) { ngx_http_push_store_lock_shmem(); worker_msg_pid = worker_msg->pid; ngx_http_push_store_unlock_shmem(); if(worker_msg_pid == ngx_pid) { //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "process_worker_message processing proper worker_msg "); //everything is okay. ngx_http_push_store_lock_shmem(); status_code = worker_msg->status_code; msg = worker_msg->msg; channel = worker_msg->channel; subscriber_sentinel = worker_msg->subscriber_sentinel; ngx_http_push_store_unlock_shmem(); if(msg==NULL) { //just a status line, is all //status code only. switch(status_code) { case NGX_HTTP_CONFLICT: status_line=&NGX_HTTP_PUSH_HTTP_STATUS_409; break; case NGX_HTTP_GONE: status_line=&NGX_HTTP_PUSH_HTTP_STATUS_410; break; case 0: ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: worker message contains neither a channel message nor a status code"); //let's let the subscribers know that something went wrong and they might've missed a message status_code = NGX_HTTP_INTERNAL_SERVER_ERROR; //intentional fall-through default: status_line=NULL; } } ngx_http_push_respond_to_subscribers(channel, subscriber_sentinel, msg, status_code, status_line); } else { //that's quite bad you see. a previous worker died with an undelivered message. //but all its subscribers' connections presumably got canned, too. so it's not so bad after all. //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "process_worker_message processing INVALID worker_msg "); ngx_http_push_store_lock_shmem(); ngx_http_push_pid_queue_t *channel_worker_sentinel = worker_msg->channel->workers_with_subscribers; ngx_http_push_pid_queue_t *channel_worker_cur = channel_worker_sentinel; ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: worker %i intercepted a message intended for another worker process (%i) that probably died", ngx_pid, worker_msg->pid); //delete that invalid sucker. while((channel_worker_cur=(ngx_http_push_pid_queue_t *)ngx_queue_next(&channel_worker_cur->queue))!=channel_worker_sentinel) { if(channel_worker_cur->pid == worker_msg->pid) { ngx_queue_remove(&channel_worker_cur->queue); ngx_http_push_slab_free_locked(channel_worker_cur); break; } } ngx_http_push_store_unlock_shmem(); } //It may be worth it to memzero worker_msg for debugging purposes. prev_worker_msg = worker_msg; ngx_http_push_store_lock_shmem(); worker_msg = (ngx_http_push_worker_msg_t *)ngx_queue_next(&worker_msg->queue); ngx_http_push_slab_free_locked(prev_worker_msg); ngx_http_push_store_unlock_shmem(); } ngx_http_push_store_lock_shmem(); ngx_queue_init(&sentinel->queue); //reset the worker message sentinel ngx_http_push_store_unlock_shmem(); //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "process_worker_message finished"); return; } ngx_http_push_store_t ngx_http_push_store_memory = { //init &ngx_http_push_store_init_module, &ngx_http_push_store_init_worker, &ngx_http_push_store_init_postconfig, &ngx_http_push_store_create_main_conf, //shutdown &ngx_http_push_store_exit_worker, &ngx_http_push_store_exit_master, //async-friendly functions with callbacks &ngx_http_push_store_get_message, //+callback &ngx_http_push_store_subscribe, //+callback &ngx_http_push_store_publish_message, //+callback //channel stuff, &ngx_http_push_store_get_channel, //creates channel if not found, +callback &ngx_http_push_store_find_channel, //returns channel or NULL if not found, +callback &ngx_http_push_store_delete_channel, &ngx_http_push_store_get_channel_message, &ngx_http_push_store_reserve_message, &ngx_http_push_store_release_message, //channel properties &ngx_http_push_store_channel_subscribers, &ngx_http_push_store_channel_worker_subscribers, &ngx_http_push_store_channel_next_subscriber, &ngx_http_push_store_channel_release_subscriber_sentinel, //legacy shared-memory store helpers &ngx_http_push_store_lock_shmem, &ngx_http_push_store_unlock_shmem, &ngx_http_push_slab_alloc_locked, &ngx_http_push_slab_free_locked, //message stuff &ngx_http_push_store_create_message, &ngx_http_push_delete_message, &ngx_http_push_delete_message_locked, &ngx_http_push_store_enqueue_message, &ngx_http_push_store_etag_from_message, &ngx_http_push_store_content_type_from_message, //interprocess communication &ngx_http_push_store_send_worker_message, &ngx_http_push_store_receive_worker_message }; debian/modules/nginx-http-push/src/ngx_http_push_module_setup.c0000664000000000000000000003322112705233614022333 0ustar ngx_module_t ngx_http_push_module; static ngx_int_t ngx_http_push_init_module(ngx_cycle_t *cycle) { ngx_core_conf_t *ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_http_push_worker_processes = ccf->worker_processes; //initialize subscriber queues //pool, please if((ngx_http_push_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, cycle->log))==NULL) { //I trust the cycle pool size to be a well-tuned one. return NGX_ERROR; } //initialize storage engine return ngx_http_push_store->init_module(cycle); } static ngx_int_t ngx_http_push_init_worker(ngx_cycle_t *cycle) { if (ngx_process != NGX_PROCESS_WORKER) { //not a worker, stop initializing stuff. return NGX_OK; } if(ngx_http_push_store->init_worker(cycle)!=NGX_OK) { return NGX_ERROR; } return NGX_OK; } static ngx_int_t ngx_http_push_postconfig(ngx_conf_t *cf) { return ngx_http_push_store->init_postconfig(cf); } //main config static void * ngx_http_push_create_main_conf(ngx_conf_t *cf) { ngx_http_push_main_conf_t *mcf = ngx_pcalloc(cf->pool, sizeof(*mcf)); if(mcf == NULL) { return NGX_CONF_ERROR; } ngx_http_push_store->create_main_conf(cf, mcf); return mcf; } //location config stuff static void *ngx_http_push_create_loc_conf(ngx_conf_t *cf) { ngx_http_push_loc_conf_t *lcf = ngx_pcalloc(cf->pool, sizeof(*lcf)); if(lcf == NULL) { return NGX_CONF_ERROR; } lcf->buffer_timeout=NGX_CONF_UNSET; lcf->max_messages=NGX_CONF_UNSET; lcf->min_messages=NGX_CONF_UNSET; lcf->subscriber_concurrency=NGX_CONF_UNSET; lcf->subscriber_poll_mechanism=NGX_CONF_UNSET; lcf->subscriber_timeout=NGX_CONF_UNSET; lcf->authorize_channel=NGX_CONF_UNSET; lcf->delete_oldest_received_message=NGX_CONF_UNSET; lcf->max_channel_id_length=NGX_CONF_UNSET; lcf->max_channel_subscribers=NGX_CONF_UNSET; lcf->ignore_queue_on_no_cache=NGX_CONF_UNSET; lcf->channel_timeout=NGX_CONF_UNSET; lcf->channel_group.data=NULL; return lcf; } static char * ngx_http_push_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_push_loc_conf_t *prev = parent, *conf = child; ngx_conf_merge_sec_value(conf->buffer_timeout, prev->buffer_timeout, NGX_HTTP_PUSH_DEFAULT_BUFFER_TIMEOUT); ngx_conf_merge_value(conf->max_messages, prev->max_messages, NGX_HTTP_PUSH_DEFAULT_MAX_MESSAGES); ngx_conf_merge_value(conf->min_messages, prev->min_messages, NGX_HTTP_PUSH_DEFAULT_MIN_MESSAGES); ngx_conf_merge_value(conf->subscriber_concurrency, prev->subscriber_concurrency, NGX_HTTP_PUSH_SUBSCRIBER_CONCURRENCY_BROADCAST); ngx_conf_merge_value(conf->subscriber_poll_mechanism, prev->subscriber_poll_mechanism, NGX_HTTP_PUSH_MECHANISM_LONGPOLL); ngx_conf_merge_sec_value(conf->subscriber_timeout, prev->subscriber_timeout, NGX_HTTP_PUSH_DEFAULT_SUBSCRIBER_TIMEOUT); ngx_conf_merge_value(conf->authorize_channel, prev->authorize_channel, 0); ngx_conf_merge_value(conf->delete_oldest_received_message, prev->delete_oldest_received_message, 0); ngx_conf_merge_value(conf->max_channel_id_length, prev->max_channel_id_length, NGX_HTTP_PUSH_MAX_CHANNEL_ID_LENGTH); ngx_conf_merge_value(conf->max_channel_subscribers, prev->max_channel_subscribers, 0); ngx_conf_merge_value(conf->ignore_queue_on_no_cache, prev->ignore_queue_on_no_cache, 0); ngx_conf_merge_value(conf->channel_timeout, prev->channel_timeout, NGX_HTTP_PUSH_DEFAULT_CHANNEL_TIMEOUT); ngx_conf_merge_str_value(conf->channel_group, prev->channel_group, ""); //sanity checks if(conf->max_messages < conf->min_messages) { //min/max buffer size makes sense? ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push_max_message_buffer_length cannot be smaller than push_min_message_buffer_length."); return NGX_CONF_ERROR; } return NGX_CONF_OK; } static ngx_str_t ngx_http_push_channel_id = ngx_string("push_channel_id"); //channel id variable //publisher and subscriber handlers now. static char *ngx_http_push_setup_handler(ngx_conf_t *cf, void * conf, ngx_int_t (*handler)(ngx_http_request_t *)) { ngx_http_core_loc_conf_t *clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); ngx_http_push_loc_conf_t *plcf = conf; clcf->handler = handler; clcf->if_modified_since = NGX_HTTP_IMS_OFF; plcf->index = ngx_http_get_variable_index(cf, &ngx_http_push_channel_id); if (plcf->index == NGX_ERROR) { return NGX_CONF_ERROR; } return NGX_CONF_OK; } typedef struct { char *str; ngx_int_t val; } ngx_http_push_strval_t; static ngx_int_t ngx_http_push_strval(ngx_str_t string, ngx_http_push_strval_t strval[], ngx_int_t strval_len, ngx_int_t *val) { ngx_int_t i; for(i=0; ioffset); if (*field != NGX_CONF_UNSET) { return "is duplicate"; } ngx_str_t value = (((ngx_str_t *) cf->args->elts)[1]); if(ngx_http_push_strval(value, concurrency, 3, field)!=NGX_OK) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "invalid push_subscriber_concurrency value: %V", &value); return NGX_CONF_ERROR; } return NGX_CONF_OK; } static char *ngx_http_push_publisher(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { return ngx_http_push_setup_handler(cf, conf, &ngx_http_push_publisher_handler); } static char *ngx_http_push_subscriber(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { static ngx_http_push_strval_t mech[] = { { "interval-poll", NGX_HTTP_PUSH_MECHANISM_INTERVALPOLL }, { "long-poll" , NGX_HTTP_PUSH_MECHANISM_LONGPOLL } }; ngx_int_t *field = (ngx_int_t *) ((char *) conf + cmd->offset); if (*field != NGX_CONF_UNSET) { return "is duplicate"; } if(cf->args->nelts==1) { //no argument given *field = NGX_HTTP_PUSH_MECHANISM_LONGPOLL; //default } else { ngx_str_t value = (((ngx_str_t *) cf->args->elts)[1]); if(ngx_http_push_strval(value, mech, 2, field)!=NGX_OK) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "invalid push_subscriber value: %V", &value); return NGX_CONF_ERROR; } } return ngx_http_push_setup_handler(cf, conf, &ngx_http_push_subscriber_handler); } static void ngx_http_push_exit_worker(ngx_cycle_t *cycle) { ngx_http_push_store->exit_worker(cycle); } static void ngx_http_push_exit_master(ngx_cycle_t *cycle) { ngx_http_push_store->exit_master(cycle); } static char *ngx_http_push_set_message_buffer_length(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_int_t *min, *max; ngx_str_t *value; ngx_int_t intval; min = (ngx_int_t *) (p + offsetof(ngx_http_push_loc_conf_t, min_messages)); max = (ngx_int_t *) (p + offsetof(ngx_http_push_loc_conf_t, max_messages)); if(*min != NGX_CONF_UNSET || *max != NGX_CONF_UNSET) { return "is duplicate"; } value = cf->args->elts; if((intval = ngx_atoi(value[1].data, value[1].len))==NGX_ERROR) { return "invalid number"; } *min = intval; *max = intval; return NGX_CONF_OK; } static char *ngx_http_push_store_messages_directive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *val = cf->args->elts; if (ngx_strcasecmp(val[1].data, (u_char *) "off") == 0) { ngx_int_t *min, *max; min = (ngx_int_t *) (p + offsetof(ngx_http_push_loc_conf_t, min_messages)); max = (ngx_int_t *) (p + offsetof(ngx_http_push_loc_conf_t, max_messages)); *min=0; *max=0; } return NGX_CONF_OK; } static ngx_command_t ngx_http_push_commands[] = { { ngx_string("push_message_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, buffer_timeout), NULL }, { ngx_string("push_max_reserved_memory"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, NGX_HTTP_MAIN_CONF_OFFSET, offsetof(ngx_http_push_main_conf_t, shm_size), NULL }, { ngx_string("push_min_message_buffer_length"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, min_messages), NULL }, { ngx_string("push_max_message_buffer_length"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, max_messages), NULL }, { ngx_string("push_message_buffer_length"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_http_push_set_message_buffer_length, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, { ngx_string("push_delete_oldest_received_message"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, delete_oldest_received_message), NULL }, { ngx_string("push_publisher"), NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, ngx_http_push_publisher, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, { ngx_string("push_subscriber"), NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1, ngx_http_push_subscriber, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, subscriber_poll_mechanism), NULL }, { ngx_string("push_subscriber_concurrency"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_http_push_set_subscriber_concurrency, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, subscriber_concurrency), NULL }, { ngx_string("push_subscriber_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, subscriber_timeout), NULL }, { ngx_string("push_authorized_channels_only"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, authorize_channel), NULL }, { ngx_string("push_store_messages"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_http_push_store_messages_directive, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, { ngx_string("push_channel_group"), NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, channel_group), NULL }, { ngx_string("push_max_channel_id_length"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, max_channel_id_length), NULL }, { ngx_string("push_max_channel_subscribers"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, max_channel_subscribers), NULL }, { ngx_string("push_ignore_queue_on_no_cache"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, ignore_queue_on_no_cache), NULL }, { ngx_string("push_channel_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_sec_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_push_loc_conf_t, channel_timeout), NULL }, ngx_null_command }; static ngx_http_module_t ngx_http_push_module_ctx = { NULL, /* preconfiguration */ ngx_http_push_postconfig, /* postconfiguration */ ngx_http_push_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_push_create_loc_conf, /* create location configuration */ ngx_http_push_merge_loc_conf, /* merge location configuration */ }; ngx_module_t ngx_http_push_module = { NGX_MODULE_V1, &ngx_http_push_module_ctx, /* module context */ ngx_http_push_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ ngx_http_push_init_module, /* init module */ ngx_http_push_init_worker, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ ngx_http_push_exit_worker, /* exit process */ ngx_http_push_exit_master, /* exit master */ NGX_MODULE_V1_PADDING }; debian/modules/nginx-http-push/src/ngx_http_push_module.c0000775000000000000000000007402612705233614021126 0ustar /* * Copyright 2009 Leo Ponomarev. */ #include #include #include ngx_int_t ngx_http_push_worker_processes; ngx_pool_t *ngx_http_push_pool; ngx_module_t ngx_http_push_module; ngx_http_push_store_t *ngx_http_push_store = &ngx_http_push_store_memory; ngx_int_t ngx_http_push_respond_status_only(ngx_http_request_t *r, ngx_int_t status_code, const ngx_str_t *statusline) { r->headers_out.status=status_code; if(statusline!=NULL) { r->headers_out.status_line.len =statusline->len; r->headers_out.status_line.data=statusline->data; } r->headers_out.content_length_n = 0; r->header_only = 1; return ngx_http_send_header(r); } void ngx_http_push_clean_timeouted_subscriber(ngx_event_t *ev) { ngx_http_push_subscriber_t *subscriber = NULL; ngx_http_request_t *r = NULL; subscriber = ev->data; r = subscriber->request; if (r->connection->destroyed) { return; } ngx_int_t rc = ngx_http_push_respond_status_only(r, NGX_HTTP_NOT_MODIFIED, NULL); ngx_http_finalize_request(r, rc); //the subscriber and channel counter will be freed by the pool cleanup callback } void ngx_http_push_subscriber_del_timer(ngx_http_push_subscriber_t *sb) { if (sb->event.timer_set) { ngx_del_timer(&sb->event); } } void ngx_http_push_subscriber_clear_ctx(ngx_http_push_subscriber_t *sb) { ngx_http_push_subscriber_del_timer(sb); sb->clndata->subscriber = NULL; sb->clndata->channel = NULL; } #define NGX_HTTP_BUF_ALLOC_SIZE(buf) \ (sizeof(*buf) + \ (((buf)->temporary || (buf)->memory) ? ngx_buf_size(buf) : 0) + \ (((buf)->file!=NULL) ? (sizeof(*(buf)->file) + (buf)->file->name.len + 1) : 0)) //buffer is _copied_ ngx_chain_t * ngx_http_push_create_output_chain(ngx_buf_t *buf, ngx_pool_t *pool, ngx_log_t *log) { ngx_chain_t *out; ngx_file_t *file; if((out = ngx_pcalloc(pool, sizeof(*out)))==NULL) { return NULL; } ngx_buf_t *buf_copy; if((buf_copy = ngx_pcalloc(pool, NGX_HTTP_BUF_ALLOC_SIZE(buf)))==NULL) { return NULL; } ngx_http_push_copy_preallocated_buffer(buf, buf_copy); if (buf->file!=NULL) { file = buf_copy->file; file->log=log; if(file->fd==NGX_INVALID_FILE) { file->fd=ngx_open_file(file->name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, NGX_FILE_OWNER_ACCESS); } if(file->fd==NGX_INVALID_FILE) { return NULL; } } buf_copy->last_buf = 1; out->buf = buf_copy; out->next = NULL; return out; } #define NGX_HTTP_PUSH_NO_CHANNEL_ID_MESSAGE "No channel id provided." static ngx_str_t * ngx_http_push_get_channel_id(ngx_http_request_t *r, ngx_http_push_loc_conf_t *cf) { ngx_http_variable_value_t *vv = ngx_http_get_indexed_variable(r, cf->index); ngx_str_t *group = &cf->channel_group; size_t group_len = group->len; size_t var_len; size_t len; ngx_str_t *id; if (vv == NULL || vv->not_found || vv->len == 0) { ngx_buf_t *buf = ngx_create_temp_buf(r->pool, sizeof(NGX_HTTP_PUSH_NO_CHANNEL_ID_MESSAGE)); ngx_chain_t *chain; if(buf==NULL) { return NULL; } buf->pos=(u_char *)NGX_HTTP_PUSH_NO_CHANNEL_ID_MESSAGE; buf->last=buf->pos + sizeof(NGX_HTTP_PUSH_NO_CHANNEL_ID_MESSAGE)-1; chain = ngx_http_push_create_output_chain(buf, r->pool, r->connection->log); buf->last_buf=1; r->headers_out.content_length_n=ngx_buf_size(buf); r->headers_out.status=NGX_HTTP_NOT_FOUND; r->headers_out.content_type.len = sizeof("text/plain") - 1; r->headers_out.content_type.data = (u_char *) "text/plain"; r->headers_out.content_type_len = r->headers_out.content_type.len; ngx_http_send_header(r); ngx_http_output_filter(r, chain); ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push module: the $push_channel_id variable is required but is not set"); return NULL; } //maximum length limiter for channel id var_len = vv->len <= cf->max_channel_id_length ? vv->len : cf->max_channel_id_length; len = group_len + 1 + var_len; if((id = ngx_palloc(r->pool, sizeof(*id) + len))==NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: unable to allocate memory for $push_channel_id string"); return NULL; } id->len=len; id->data=(u_char *)(id+1); ngx_memcpy(id->data, group->data, group_len); id->data[group_len]='/'; ngx_memcpy(id->data + group_len + 1, vv->data, var_len); return id; } ngx_table_elt_t * ngx_http_push_add_response_header(ngx_http_request_t *r, const ngx_str_t *header_name, const ngx_str_t *header_value) { ngx_table_elt_t *h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return NULL; } h->hash = 1; h->key.len = header_name->len; h->key.data = header_name->data; h->value.len = header_value->len; h->value.data = header_value->data; return h; } static ngx_str_t * ngx_http_push_find_in_header_value(ngx_http_request_t * r, ngx_str_t header_name) { ngx_uint_t i; ngx_list_part_t *part = &r->headers_in.headers.part; ngx_table_elt_t *header= part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].key.len == header_name.len && ngx_strncasecmp(header[i].key.data, header_name.data, header[i].key.len) == 0) { return &header[i].value; } } return NULL; } ngx_int_t ngx_http_push_allow_caching(ngx_http_request_t * r) { ngx_str_t *tmp_header; ngx_str_t header_checks[2] = { NGX_HTTP_PUSH_HEADER_CACHE_CONTROL, NGX_HTTP_PUSH_HEADER_PRAGMA }; ngx_int_t i = 0; for(; i < 2; i++) { tmp_header = ngx_http_push_find_in_header_value(r, header_checks[i]); if (tmp_header != NULL) { return !!ngx_strncasecmp(tmp_header->data, NGX_HTTP_PUSH_CACHE_CONTROL_VALUE.data, tmp_header->len); } } return 1; } void ngx_http_push_subscriber_cleanup(ngx_http_push_subscriber_cleanup_t *data) { if(data->subscriber!=NULL) { //still queued up ngx_http_push_subscriber_t* sb = data->subscriber; ngx_http_push_subscriber_del_timer(sb); ngx_queue_remove(&data->subscriber->queue); ngx_pfree(ngx_http_push_pool, data->subscriber); //was there an error? oh whatever. } if (data->rchain != NULL) { ngx_pfree(data->rpool, data->rchain->buf); ngx_pfree(data->rpool, data->rchain); data->rchain=NULL; } if(data->buf_use_count != NULL && --(*data->buf_use_count) <= 0) { ngx_buf_t *buf; ngx_pfree(ngx_http_push_pool, data->buf_use_count); buf=data->buf; if(buf->file) { ngx_close_file(buf->file->fd); } ngx_pfree(ngx_http_push_pool, buf); } if(data->channel!=NULL) { //we're expected to decrement the subscriber count ngx_http_push_store->lock(); data->channel->subscribers--; ngx_http_push_store->unlock(); } } ngx_str_t * ngx_http_push_subscriber_get_etag(ngx_http_request_t * r) { ngx_uint_t i; ngx_list_part_t *part = &r->headers_in.headers.part; ngx_table_elt_t *header= part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].key.len == NGX_HTTP_PUSH_HEADER_IF_NONE_MATCH.len && ngx_strncasecmp(header[i].key.data, NGX_HTTP_PUSH_HEADER_IF_NONE_MATCH.data, header[i].key.len) == 0) { return &header[i].value; } } return NULL; } ngx_int_t ngx_http_push_subscriber_get_msg_id(ngx_http_request_t *r, ngx_http_push_msg_id_t *id) { ngx_str_t *if_none_match = ngx_http_push_subscriber_get_etag(r); ngx_int_t tag=0; id->time=(r->headers_in.if_modified_since == NULL) ? 0 : ngx_http_parse_time(r->headers_in.if_modified_since->value.data, r->headers_in.if_modified_since->value.len); if(if_none_match==NULL || (if_none_match!=NULL && (tag = ngx_atoi(if_none_match->data, if_none_match->len))==NGX_ERROR)) { tag=0; } id->tag=ngx_abs(tag); return NGX_OK; } //allocates nothing ngx_int_t ngx_http_push_prepare_response_to_subscriber_request(ngx_http_request_t *r, ngx_chain_t *chain, ngx_str_t *content_type, ngx_str_t *etag, time_t last_modified) { ngx_int_t res; if (content_type!=NULL) { r->headers_out.content_type.len=content_type->len; r->headers_out.content_type.data = content_type->data; r->headers_out.content_type_len = r->headers_out.content_type.len; } if(last_modified) { //if-modified-since header r->headers_out.last_modified_time=last_modified; } if(etag!=NULL) { //etag, if we need one if ((ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ETAG, etag))==NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } //Vary header needed for proper HTTP caching. ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_VARY, &NGX_HTTP_PUSH_VARY_HEADER_VALUE); r->headers_out.status=NGX_HTTP_OK; //we know the entity length, and we're using just one buffer. so no chunking please. r->headers_out.content_length_n=ngx_buf_size(chain->buf); if((res = ngx_http_send_header(r)) >= NGX_HTTP_SPECIAL_RESPONSE) { return res; } return ngx_http_output_filter(r, chain); } //allocates message and responds to subscriber ngx_int_t ngx_http_push_alloc_for_subscriber_response(ngx_pool_t *pool, ngx_int_t shared, ngx_http_push_msg_t *msg, ngx_chain_t **chain, ngx_str_t **content_type, ngx_str_t **etag, time_t *last_modified) { if(etag != NULL && (*etag = ngx_http_push_store->message_etag(msg, pool))==NULL) { //oh, nevermind... ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate memory for Etag header"); return NGX_ERROR; } if(content_type != NULL && (*content_type= ngx_http_push_store->message_content_type(msg, pool))==NULL) { //oh, nevermind... ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate memory for Content Type header"); if(pool == NULL) { ngx_free(*etag); } else { ngx_pfree(pool, *etag); } return NGX_ERROR; } //preallocate output chain. yes, same one for every waiting subscriber if(chain != NULL && (*chain = ngx_http_push_create_output_chain(msg->buf, pool, ngx_cycle->log))==NULL) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate buffer chain while responding to subscriber request"); if(pool == NULL) { ngx_free(*etag); ngx_free(*content_type); } else { ngx_pfree(pool, *etag); ngx_pfree(pool, *content_type); } return NGX_ERROR; } if(last_modified != NULL) { *last_modified = msg->message_time; } ngx_http_push_store->unlock(); if(pool!=NULL && shared == 0 && ((*chain)->buf->file!=NULL)) { //close file when we're done with it ngx_pool_cleanup_t *cln; ngx_pool_cleanup_file_t *clnf; if((cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t)))==NULL) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate buffer chain pool cleanup while responding to subscriber request"); ngx_pfree(pool, *etag); ngx_pfree(pool, *content_type); ngx_pfree(pool, *chain); return NGX_ERROR; } cln->handler = ngx_pool_cleanup_file; clnf = cln->data; clnf->fd = (*chain)->buf->file->fd; clnf->name = (*chain)->buf->file->name.data; clnf->log = ngx_cycle->log; } return NGX_OK; } static void ngx_http_push_match_channel_info_subtype(size_t off, u_char *cur, size_t rem, u_char **priority, const ngx_str_t **format, ngx_str_t *content_type) { static ngx_http_push_content_subtype_t subtypes[] = { { "json" , 4, &NGX_HTTP_PUSH_CHANNEL_INFO_JSON }, { "yaml" , 4, &NGX_HTTP_PUSH_CHANNEL_INFO_YAML }, { "xml" , 3, &NGX_HTTP_PUSH_CHANNEL_INFO_XML }, { "x-json", 6, &NGX_HTTP_PUSH_CHANNEL_INFO_JSON }, { "x-yaml", 6, &NGX_HTTP_PUSH_CHANNEL_INFO_YAML } }; u_char *start = cur + off; ngx_uint_t i; for(i=0; i<(sizeof(subtypes)/sizeof(ngx_http_push_content_subtype_t)); i++) { if(ngx_strncmp(start, subtypes[i].subtype, remstart) { *format = subtypes[i].format; *priority = start; content_type->data=cur; content_type->len= off + 1 + subtypes[i].len; } } } } //print information about a channel static ngx_int_t ngx_http_push_channel_info(ngx_http_request_t *r, ngx_uint_t messages, ngx_uint_t subscribers, time_t last_seen) { ngx_buf_t *b; ngx_uint_t len; ngx_str_t content_type = ngx_string("text/plain"); const ngx_str_t *format = &NGX_HTTP_PUSH_CHANNEL_INFO_PLAIN; time_t time_elapsed = ngx_time() - last_seen; if(r->headers_in.accept) { //lame content-negotiation (without regard for qvalues) u_char *accept = r->headers_in.accept->value.data; size_t len = r->headers_in.accept->value.len; size_t rem; u_char *cur = accept; u_char *priority=&accept[len-1]; for(rem=len; (cur = ngx_strnstr(cur, "text/", rem))!=NULL; cur += sizeof("text/")-1) { rem=len - ((size_t)(cur-accept)+sizeof("text/")-1); if(ngx_strncmp(cur+sizeof("text/")-1, "plain", rem<5 ? rem : 5)==0) { if(priority) { format = &NGX_HTTP_PUSH_CHANNEL_INFO_PLAIN; priority = cur+sizeof("text/")-1; //content-type is already set by default } } ngx_http_push_match_channel_info_subtype(sizeof("text/")-1, cur, rem, &priority, &format, &content_type); } cur = accept; for(rem=len; (cur = ngx_strnstr(cur, "application/", rem))!=NULL; cur += sizeof("application/")-1) { rem=len - ((size_t)(cur-accept)+sizeof("application/")-1); ngx_http_push_match_channel_info_subtype(sizeof("application/")-1, cur, rem, &priority, &format, &content_type); } } r->headers_out.content_type.len = content_type.len; r->headers_out.content_type.data = content_type.data; r->headers_out.content_type_len = r->headers_out.content_type.len; len = format->len - 8 - 1 + 3*NGX_INT_T_LEN; //minus 8 sprintf if ((b = ngx_create_temp_buf(r->pool, len)) == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->last = ngx_sprintf(b->last, (char *)format->data, messages, last_seen==0 ? -1 : (ngx_int_t) time_elapsed ,subscribers); //lastly, set the content-length, because if the status code isn't 200, nginx may not do so automatically r->headers_out.content_length_n = ngx_buf_size(b); if (ngx_http_send_header(r) > NGX_HTTP_SPECIAL_RESPONSE) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } return ngx_http_output_filter(r, ngx_http_push_create_output_chain(b, r->pool, r->connection->log)); } #define NGX_HTTP_PUSH_MAKE_CONTENT_TYPE(content_type, content_type_len, msg, pool) \ if(((content_type) = ngx_palloc(pool, sizeof(*content_type)+content_type_len))!=NULL) { \ (content_type)->len=content_type_len; \ (content_type)->data=(u_char *)((content_type)+1); \ ngx_memcpy(content_type->data, (msg)->content_type.data, content_type_len); \ } #define NGX_HTTP_PUSH_OPTIONS_OK_MESSAGE "Go ahead" ngx_int_t ngx_push_longpoll_subscriber_enqueue(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *subscriber, ngx_int_t subscriber_timeout) { ngx_http_cleanup_t *cln; ngx_http_push_subscriber_cleanup_t *clndata; ngx_http_request_t *r = subscriber->request; //attach a cleaner to remove the request from the channel and handle shared buffer deallocation. if ((cln=ngx_http_cleanup_add(r, sizeof(*clndata))) == NULL) { //make sure we can. return NGX_ERROR; } cln->handler = (ngx_http_cleanup_pt) ngx_http_push_subscriber_cleanup; clndata = (ngx_http_push_subscriber_cleanup_t *) cln->data; clndata->channel=channel; clndata->subscriber=subscriber; clndata->buf_use_count=0; clndata->buf=NULL; clndata->rchain=NULL; clndata->rpool=NULL; subscriber->clndata=clndata; //set up subscriber timeout event ngx_memzero(&subscriber->event, sizeof(subscriber->event)); if (subscriber_timeout > 0) { subscriber->event.handler = ngx_http_push_clean_timeouted_subscriber; subscriber->event.data = subscriber; subscriber->event.log = r->connection->log; ngx_add_timer(&subscriber->event, subscriber_timeout * 1000); } r->read_event_handler = ngx_http_test_reading; r->write_event_handler = ngx_http_request_empty_handler; r->main->count++; //this is the right way to hold and finalize the request... maybe //r->keepalive = 1; //stayin' alive!! return NGX_OK; } /* ngx_int_t ngx_push_longpoll_subscriber_dequeue(ngx_http_push_subscriber_t *subscriber) { return NGX_OK; } */ static ngx_int_t ngx_http_push_response_channel_ptr_info(ngx_http_push_channel_t *channel, ngx_http_request_t *r, ngx_int_t status_code) { time_t last_seen = 0; ngx_uint_t subscribers = 0; ngx_uint_t messages = 0; if(channel!=NULL) { ngx_http_push_store->lock(); subscribers = channel->subscribers; last_seen = channel->last_seen; messages = channel->messages; ngx_http_push_store->unlock(); r->headers_out.status = status_code == (ngx_int_t) NULL ? NGX_HTTP_OK : status_code; if (status_code == NGX_HTTP_CREATED) { r->headers_out.status_line.len =sizeof("201 Created")- 1; r->headers_out.status_line.data=(u_char *) "201 Created"; } else if (status_code == NGX_HTTP_ACCEPTED) { r->headers_out.status_line.len =sizeof("202 Accepted")- 1; r->headers_out.status_line.data=(u_char *) "202 Accepted"; } ngx_http_push_channel_info(r, messages, subscribers, last_seen); } else { //404! r->headers_out.status=NGX_HTTP_NOT_FOUND; //just the headers, please. we don't care to describe the situation or //respond with an html page r->headers_out.content_length_n=0; r->header_only = 1; ngx_http_send_header(r); } return NGX_OK; } static ngx_int_t ngx_http_push_response_channel_info(ngx_str_t *channel_id, ngx_http_request_t *r, ngx_int_t status_code) { ngx_http_push_channel_t *channel; ngx_http_push_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_module); channel = channel_id == NULL ? NULL : ngx_http_push_store->find_channel(channel_id, cf->channel_timeout, NULL); return ngx_http_push_response_channel_ptr_info(channel, r, status_code); } static ngx_int_t subscribe_longpoll_callback(ngx_int_t status, ngx_http_request_t *r) { ngx_http_finalize_request(r, status); return NGX_OK; } static ngx_int_t subscribe_intervalpoll_callback(ngx_http_push_msg_t *msg, ngx_int_t msg_search_outcome, ngx_http_request_t *r) { ngx_chain_t *chain; ngx_str_t *content_type, *etag; time_t last_modified; switch(msg_search_outcome) { case NGX_HTTP_PUSH_MESSAGE_EXPECTED: //interval-polling subscriber requests get a 304 with their entity tags preserved. if (r->headers_in.if_modified_since != NULL) { r->headers_out.last_modified_time=ngx_http_parse_time(r->headers_in.if_modified_since->value.data, r->headers_in.if_modified_since->value.len); } if ((etag=ngx_http_push_subscriber_get_etag(r)) != NULL) { ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ETAG, etag); } ngx_http_finalize_request(r, NGX_HTTP_NOT_MODIFIED); return NGX_OK; case NGX_HTTP_PUSH_MESSAGE_FOUND: ngx_http_push_alloc_for_subscriber_response(r->pool, 0, msg, &chain, &content_type, &etag, &last_modified); ngx_http_push_prepare_response_to_subscriber_request(r, chain, content_type, etag, last_modified); ngx_http_push_store->release_message(NULL, msg); ngx_http_finalize_request(r, NGX_OK); return NGX_OK; default: ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } } ngx_int_t ngx_http_push_subscriber_handler(ngx_http_request_t *r) { ngx_http_push_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_module); ngx_str_t *channel_id; ngx_http_push_msg_id_t msg_id; if((channel_id=ngx_http_push_get_channel_id(r, cf)) == NULL) { return r->headers_out.status ? NGX_OK : NGX_HTTP_INTERNAL_SERVER_ERROR; } switch(r->method) { case NGX_HTTP_GET: ngx_http_push_subscriber_get_msg_id(r, &msg_id); r->main->count++; //let it linger until callback switch(cf->subscriber_poll_mechanism) { ngx_int_t msg_search_outcome; //for NGX_HTTP_PUSH_MECHANISM_LONGPOLL case NGX_HTTP_PUSH_MECHANISM_INTERVALPOLL: ngx_http_push_store->get_message(channel_id, &msg_id, &msg_search_outcome, r, &subscribe_intervalpoll_callback); break; case NGX_HTTP_PUSH_MECHANISM_LONGPOLL: ngx_http_push_store->subscribe(channel_id, &msg_id, r, &subscribe_longpoll_callback); break; } return NGX_DONE; case NGX_HTTP_OPTIONS: ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, &NGX_HTTP_PUSH_ANYSTRING); ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_HEADERS, &NGX_HTTP_PUSH_ACCESS_CONTROL_ALLOWED_SUBSCRIBER_HEADERS); ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_METHODS, &NGX_HTTP_PUSH_ALLOW_GET_OPTIONS); r->headers_out.content_length_n = 0; r->header_only = 1; r->headers_out.status=NGX_HTTP_OK; ngx_http_send_header(r); return NGX_OK; default: ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ALLOW, &NGX_HTTP_PUSH_ALLOW_GET_OPTIONS); //valid HTTP for the win return NGX_HTTP_NOT_ALLOWED; } } static ngx_int_t publish_callback(ngx_int_t status, ngx_http_push_channel_t *ch, ngx_http_request_t *r) { switch(status) { case NGX_HTTP_PUSH_MESSAGE_QUEUED: //message was queued successfully, but there were no subscribers to receive it. ngx_http_finalize_request(r, ngx_http_push_response_channel_ptr_info(ch, r, NGX_HTTP_ACCEPTED)); return NGX_OK; case NGX_HTTP_PUSH_MESSAGE_RECEIVED: //message was queued successfully, and it was already sent to at least one subscriber ngx_http_finalize_request(r, ngx_http_push_response_channel_ptr_info(ch, r, NGX_HTTP_CREATED)); return NGX_OK; case NGX_ERROR: //WTF? ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: error broadcasting message to workers"); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; default: //for debugging, mostly. I don't expect this branch to behit during regular operation ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: TOTALLY UNEXPECTED error broadcasting message to workers"); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } } static void ngx_http_push_publisher_body_handler(ngx_http_request_t * r) { ngx_str_t *channel_id; ngx_http_push_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_module); ngx_uint_t method = r->method; if((channel_id = ngx_http_push_get_channel_id(r, cf))==NULL) { ngx_http_finalize_request(r, r->headers_out.status ? NGX_OK : NGX_HTTP_INTERNAL_SERVER_ERROR); return; } switch(method) { case NGX_HTTP_POST: case NGX_HTTP_PUT: ngx_http_push_store->publish(channel_id, r, &publish_callback); break; case NGX_HTTP_DELETE: ngx_http_finalize_request(r, ngx_http_push_response_channel_info(channel_id, r, NGX_HTTP_OK)); ngx_http_push_store->delete_channel(channel_id); break; case NGX_HTTP_GET: ngx_http_finalize_request(r, ngx_http_push_response_channel_info(channel_id, r, NGX_HTTP_OK)); break; case NGX_HTTP_OPTIONS: ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, &NGX_HTTP_PUSH_ANYSTRING); ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_HEADERS, &NGX_HTTP_PUSH_ACCESS_CONTROL_ALLOWED_PUBLISHER_HEADERS); ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_METHODS, &NGX_HTTP_PUSH_ALLOW_GET_POST_PUT_DELETE_OPTIONS); r->header_only = 1; r->headers_out.content_length_n = 0; r->headers_out.status=NGX_HTTP_OK; ngx_http_send_header(r); ngx_http_finalize_request(r, NGX_HTTP_OK); break; default: //some other weird request method ngx_http_push_add_response_header(r, &NGX_HTTP_PUSH_HEADER_ALLOW, &NGX_HTTP_PUSH_ALLOW_GET_POST_PUT_DELETE_OPTIONS); ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED); break; } } ngx_int_t ngx_http_push_respond_to_subscribers(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *sentinel, ngx_http_push_msg_t *msg, ngx_int_t status_code, const ngx_str_t *status_line) { //copy everything we need first ngx_str_t *content_type=NULL; ngx_str_t *etag=NULL; time_t last_modified; ngx_chain_t *chain=NULL; ngx_http_request_t *r; ngx_buf_t *buffer; ngx_chain_t *rchain; ngx_buf_t *rbuffer; ngx_int_t *buf_use_count; ngx_http_push_subscriber_cleanup_t *clndata; ngx_http_push_subscriber_t *cur=NULL; ngx_int_t responded_subscribers=0; if(sentinel==NULL) { //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "respond_to_subscribers with sentinel==NULL"); return NGX_OK; } if(msg!=NULL) { if(ngx_http_push_alloc_for_subscriber_response(ngx_http_push_pool, 1, msg, &chain, &content_type, &etag, &last_modified)==NGX_ERROR) { ngx_http_push_store->release_message(channel, msg); return NGX_ERROR; } buffer = chain->buf; buffer->recycled = 1; buf_use_count = ngx_pcalloc(ngx_http_push_pool, sizeof(*buf_use_count)); *buf_use_count = ngx_http_push_store->channel_worker_subscribers(sentinel); } while((cur=ngx_http_push_store->next_subscriber(channel, sentinel, cur, 1))!=NULL) { //in this block, nothing in shared memory should be dereferenced. r=cur->request; if(msg!=NULL) { //chain and buffer for this request rchain = ngx_pcalloc(r->pool, sizeof(*rchain)); rchain->next = NULL; rbuffer = ngx_pcalloc(r->pool, sizeof(*rbuffer)); rchain->buf = rbuffer; ngx_memcpy(rbuffer, buffer, sizeof(*buffer)); //request buffer cleanup clndata = cur->clndata; clndata->buf = buffer; clndata->buf_use_count = buf_use_count; clndata->rchain = rchain; clndata->rpool = r->pool; if (rbuffer->in_file && (fcntl(rbuffer->file->fd, F_GETFD) == -1)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push module: buffer in invalid file descriptor"); } //cleanup oughtn't dequeue anything. or decrement the subscriber count, for that matter ngx_http_push_subscriber_clear_ctx(cur); ngx_http_finalize_request(r, ngx_http_push_prepare_response_to_subscriber_request(r, rchain, content_type, etag, last_modified)); //BAM! } else { ngx_http_push_subscriber_clear_ctx(cur); ngx_http_finalize_request(r, ngx_http_push_respond_status_only(r, status_code, status_line)); } responded_subscribers++; } if(msg!=NULL) { ngx_http_push_store->release_message(channel, msg); ngx_pfree(ngx_http_push_pool, etag); ngx_pfree(ngx_http_push_pool, content_type); ngx_pfree(ngx_http_push_pool, chain); } //ngx_log_error(NGX_LOG_WARN, ngx_cycle->log, 0, "respond_to_subscribers with msg %p finished", msg); ngx_http_push_store->lock(); channel->subscribers-=responded_subscribers; //is the message still needed? ngx_http_push_store->unlock(); ngx_http_push_store->release_subscriber_sentinel(channel, sentinel); return NGX_OK; } ngx_int_t ngx_http_push_publisher_handler(ngx_http_request_t * r) { ngx_int_t rc; /* Instruct ngx_http_read_subscriber_request_body to store the request body entirely in a memory buffer or in a file */ r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; r->request_body_in_clean_file = 0; r->request_body_file_log_level = 0; rc = ngx_http_read_client_request_body(r, ngx_http_push_publisher_body_handler); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_DONE; } void ngx_http_push_copy_preallocated_buffer(ngx_buf_t *buf, ngx_buf_t *cbuf) { if (cbuf!=NULL) { ngx_memcpy(cbuf, buf, sizeof(*buf)); //overkill? if(buf->temporary || buf->memory) { //we don't want to copy mmpapped memory, so no ngx_buf_in_momory(buf) cbuf->pos = (u_char *) (cbuf+1); cbuf->last = cbuf->pos + ngx_buf_size(buf); cbuf->start=cbuf->pos; cbuf->end = cbuf->start + ngx_buf_size(buf); ngx_memcpy(cbuf->pos, buf->pos, ngx_buf_size(buf)); cbuf->memory=ngx_buf_in_memory_only(buf) ? 1 : 0; } if (buf->file!=NULL) { cbuf->file = (ngx_file_t *) (cbuf+1) + ((buf->temporary || buf->memory) ? ngx_buf_size(buf) : 0); cbuf->file->fd=NGX_INVALID_FILE; cbuf->file->log=NULL; cbuf->file->offset=buf->file->offset; cbuf->file->sys_offset=buf->file->sys_offset; cbuf->file->name.len=buf->file->name.len; cbuf->file->name.data=(u_char *) (cbuf->file+1); ngx_memcpy(cbuf->file->name.data, buf->file->name.data, buf->file->name.len); } } } debian/modules/nginx-http-push/src/ngx_http_push_types.h0000664000000000000000000001053612705233614021003 0ustar //on with the declarations typedef struct { size_t shm_size; } ngx_http_push_main_conf_t; typedef struct { ngx_atomic_int_t lock; ngx_atomic_t mutex; ngx_int_t write_pid; } ngx_rwlock_t; typedef struct { time_t time; //tag message by time ngx_int_t tag; //used in conjunction with message_time if more than one message have the same time. } ngx_http_push_msg_id_t; //message queue typedef struct { ngx_queue_t queue; //this MUST be first. ngx_str_t content_type; // ngx_str_t charset; ngx_buf_t *buf; time_t expires; ngx_uint_t delete_oldest_received_min_messages; //NGX_MAX_UINT32_VALUE for 'never' time_t message_time; //tag message by time ngx_int_t message_tag; //used in conjunction with message_time if more than one message have the same time. ngx_int_t refcount; } ngx_http_push_msg_t; typedef struct ngx_http_push_subscriber_cleanup_s ngx_http_push_subscriber_cleanup_t; //subscriber request queue typedef struct { ngx_queue_t queue; //this MUST be first. ngx_http_request_t *request; ngx_http_push_subscriber_cleanup_t *clndata; ngx_event_t event; } ngx_http_push_subscriber_t; typedef struct { ngx_queue_t queue; pid_t pid; ngx_int_t slot; ngx_http_push_subscriber_t *subscriber_sentinel; } ngx_http_push_pid_queue_t; //our typecast-friendly rbtree node (channel) typedef struct { ngx_rbtree_node_t node; //this MUST be first. ngx_str_t id; ngx_http_push_msg_t *message_queue; ngx_uint_t messages; ngx_http_push_pid_queue_t *workers_with_subscribers; ngx_uint_t subscribers; time_t last_seen; time_t expires; } ngx_http_push_channel_t; //cleaning supplies struct ngx_http_push_subscriber_cleanup_s { ngx_http_push_subscriber_t *subscriber; ngx_http_push_channel_t *channel; ngx_int_t *buf_use_count; ngx_buf_t *buf; ngx_chain_t *rchain; ngx_pool_t *rpool; }; //garbage collecting goodness typedef struct { ngx_queue_t queue; ngx_http_push_channel_t *channel; } ngx_http_push_channel_queue_t; //messages to worker processes typedef struct { ngx_queue_t queue; ngx_http_push_msg_t *msg; //->shared memory ngx_int_t status_code; ngx_pid_t pid; ngx_http_push_channel_t *channel; //->shared memory ngx_http_push_subscriber_t *subscriber_sentinel; //->a worker's local pool } ngx_http_push_worker_msg_t; typedef struct { ngx_queue_t queue; ngx_rwlock_t lock; } ngx_http_push_worker_msg_sentinel_t; //shared memory typedef struct { ngx_rbtree_t tree; ngx_uint_t channels; //# of channels being used ngx_uint_t messages; //# of channels being used ngx_http_push_worker_msg_sentinel_t *ipc; //interprocess stuff } ngx_http_push_shm_data_t; typedef struct { ngx_int_t index; time_t buffer_timeout; ngx_int_t min_messages; ngx_int_t max_messages; ngx_int_t subscriber_concurrency; ngx_int_t subscriber_poll_mechanism; time_t subscriber_timeout; ngx_int_t authorize_channel; ngx_int_t delete_oldest_received_message; ngx_str_t channel_group; ngx_int_t max_channel_id_length; ngx_int_t max_channel_subscribers; ngx_int_t ignore_queue_on_no_cache; time_t channel_timeout; } ngx_http_push_loc_conf_t; typedef struct { char *subtype; size_t len; const ngx_str_t *format; } ngx_http_push_content_subtype_t; debian/modules/nginx-http-push/src/ngx_http_push_defs.h0000664000000000000000000000520312705233614020553 0ustar #define NGX_HTTP_PUSH_DEFAULT_SHM_SIZE 33554432 //32 megs #define NGX_HTTP_PUSH_DEFAULT_BUFFER_TIMEOUT 3600 #define NGX_HTTP_PUSH_DEFAULT_SUBSCRIBER_TIMEOUT 0 //default: never timeout //(liucougar: this is a bit confusing, but it is what's the default behavior before this option is introducecd) #define NGX_HTTP_PUSH_DEFAULT_CHANNEL_TIMEOUT 5 //default: timeout in 5 seconds #define NGX_HTTP_PUSH_DEFAULT_MIN_MESSAGES 1 #define NGX_HTTP_PUSH_DEFAULT_MAX_MESSAGES 10 #define NGX_HTTP_PUSH_SUBSCRIBER_CONCURRENCY_LASTIN 0 #define NGX_HTTP_PUSH_SUBSCRIBER_CONCURRENCY_FIRSTIN 1 #define NGX_HTTP_PUSH_SUBSCRIBER_CONCURRENCY_BROADCAST 2 #define NGX_HTTP_PUSH_MECHANISM_LONGPOLL 0 #define NGX_HTTP_PUSH_MECHANISM_INTERVALPOLL 1 #define NGX_HTTP_PUSH_MIN_MESSAGE_RECIPIENTS 0 #define NGX_HTTP_PUSH_MAX_CHANNEL_ID_LENGTH 1024 //bytes #ifndef NGX_HTTP_CONFLICT #define NGX_HTTP_CONFLICT 409 #endif #ifndef NGX_HTTP_GONE #define NGX_HTTP_GONE 410 #endif #ifndef NGX_HTTP_CREATED #define NGX_HTTP_CREATED 201 #endif #ifndef NGX_HTTP_ACCEPTED #define NGX_HTTP_ACCEPTED 202 #endif #define NGX_HTTP_PUSH_MESSAGE_RECEIVED 9000 #define NGX_HTTP_PUSH_MESSAGE_QUEUED 9001 #define NGX_HTTP_PUSH_MESSAGE_FOUND 1000 #define NGX_HTTP_PUSH_MESSAGE_EXPECTED 1001 #define NGX_HTTP_PUSH_MESSAGE_EXPIRED 1002 extern const ngx_str_t NGX_HTTP_PUSH_HEADER_ETAG; extern const ngx_str_t NGX_HTTP_PUSH_HEADER_IF_NONE_MATCH; extern const ngx_str_t NGX_HTTP_PUSH_HEADER_VARY; extern const ngx_str_t NGX_HTTP_PUSH_HEADER_ALLOW; extern const ngx_str_t NGX_HTTP_PUSH_HEADER_CACHE_CONTROL; extern const ngx_str_t NGX_HTTP_PUSH_HEADER_PRAGMA; extern const ngx_str_t NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_METHODS; extern const ngx_str_t NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_HEADERS; extern const ngx_str_t NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN; //header values extern const ngx_str_t NGX_HTTP_PUSH_CACHE_CONTROL_VALUE; //status strings extern const ngx_str_t NGX_HTTP_PUSH_HTTP_STATUS_409; extern const ngx_str_t NGX_HTTP_PUSH_HTTP_STATUS_410; //other stuff extern const ngx_str_t NGX_HTTP_PUSH_ANYSTRING; extern const ngx_str_t NGX_HTTP_PUSH_ACCESS_CONTROL_ALLOWED_PUBLISHER_HEADERS; extern const ngx_str_t NGX_HTTP_PUSH_ACCESS_CONTROL_ALLOWED_SUBSCRIBER_HEADERS; extern const ngx_str_t NGX_HTTP_PUSH_ALLOW_GET_POST_PUT_DELETE_OPTIONS; extern const ngx_str_t NGX_HTTP_PUSH_ALLOW_GET_OPTIONS; extern const ngx_str_t NGX_HTTP_PUSH_VARY_HEADER_VALUE; extern const ngx_str_t NGX_HTTP_PUSH_CHANNEL_INFO_PLAIN; extern const ngx_str_t NGX_HTTP_PUSH_CHANNEL_INFO_JSON; extern const ngx_str_t NGX_HTTP_PUSH_CHANNEL_INFO_XML; extern const ngx_str_t NGX_HTTP_PUSH_CHANNEL_INFO_YAML;debian/modules/nginx-http-push/src/ngx_http_push_defs.c0000664000000000000000000000466512705233614020561 0ustar #include #include "ngx_http_push_defs.h" //string constants //headers const ngx_str_t NGX_HTTP_PUSH_HEADER_ETAG = ngx_string("Etag"); const ngx_str_t NGX_HTTP_PUSH_HEADER_IF_NONE_MATCH = ngx_string("If-None-Match"); const ngx_str_t NGX_HTTP_PUSH_HEADER_VARY = ngx_string("Vary"); const ngx_str_t NGX_HTTP_PUSH_HEADER_ALLOW = ngx_string("Allow"); const ngx_str_t NGX_HTTP_PUSH_HEADER_CACHE_CONTROL = ngx_string("Cache-Control"); const ngx_str_t NGX_HTTP_PUSH_HEADER_PRAGMA = ngx_string("Pragma"); const ngx_str_t NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_HEADERS = ngx_string("Access-Control-Allow-Headers"); const ngx_str_t NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_METHODS = ngx_string("Access-Control-Allow-Methods"); const ngx_str_t NGX_HTTP_PUSH_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN = ngx_string("Access-Control-Allow-Origin"); //header values const ngx_str_t NGX_HTTP_PUSH_CACHE_CONTROL_VALUE = ngx_string("no-cache"); //status strings const ngx_str_t NGX_HTTP_PUSH_HTTP_STATUS_409 = ngx_string("409 Conflict"); const ngx_str_t NGX_HTTP_PUSH_HTTP_STATUS_410 = ngx_string("410 Gone"); //other stuff const ngx_str_t NGX_HTTP_PUSH_ANYSTRING= ngx_string("*"); const ngx_str_t NGX_HTTP_PUSH_ACCESS_CONTROL_ALLOWED_PUBLISHER_HEADERS = ngx_string("Content-Type, Origin"); const ngx_str_t NGX_HTTP_PUSH_ACCESS_CONTROL_ALLOWED_SUBSCRIBER_HEADERS = ngx_string("If-None-Match, If-Modified-Since, Origin"); const ngx_str_t NGX_HTTP_PUSH_ALLOW_GET_POST_PUT_DELETE_OPTIONS= ngx_string("GET, POST, PUT, DELETE, OPTIONS"); const ngx_str_t NGX_HTTP_PUSH_ALLOW_GET_OPTIONS= ngx_string("GET, OPTIONS"); const ngx_str_t NGX_HTTP_PUSH_VARY_HEADER_VALUE = ngx_string("If-None-Match, If-Modified-Since"); const ngx_str_t NGX_HTTP_PUSH_CHANNEL_INFO_PLAIN = ngx_string( "queued messages: %ui" CRLF "last requested: %d sec. ago (-1=never)" CRLF "active subscribers: %ui" "\0"); const ngx_str_t NGX_HTTP_PUSH_CHANNEL_INFO_JSON = ngx_string( "{\"messages\": %ui, " "\"requested\": %d, " "\"subscribers\": %ui }" "\0"); const ngx_str_t NGX_HTTP_PUSH_CHANNEL_INFO_XML = ngx_string( "" CRLF "" CRLF " %ui" CRLF " %d" CRLF " %ui" CRLF "" "\0"); const ngx_str_t NGX_HTTP_PUSH_CHANNEL_INFO_YAML = ngx_string( "---" CRLF "messages: %ui" CRLF "requested: %d" CRLF "subscribers: %ui" CRLF CRLF "\0"); debian/modules/nginx-http-push/LICENCE0000664000000000000000000000212212705233614014702 0ustar This work is distributed under the MIT Licence. Copyright (c) 2009 Leo Ponomarev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. debian/modules/README.Modules-versions0000664000000000000000000000254212705233614015003 0ustar README for Modules versions --------------------------- This file lists third party modules built with nginx in Debian, homepage and version. headers-more-nginx-module Homepage: https://github.com/agentzh/headers-more-nginx-module Version: v0.25 nginx-development-kit Homepage: https://github.com/simpl/ngx_devel_kit/ Version: v0.2.19 nginx-auth-pam Homepage: https://github.com/stogh/ngx_http_auth_pam_module Version: 1.4 nginx-echo Homepage: https://github.com/agentzh/echo-nginx-module Version: v0.57 nginx-lua Homepage: https://github.com/openresty/lua-nginx-module Version: v0.10.0 nginx-upstream-fair Homepage: https://github.com/gnosek/nginx-upstream-fair Version: a18b409 nginx-push Homepage: https://github.com/slact/nginx_http_push_module Version: 0.73 nginx-upload-progress Homepage: https://github.com/masterzen/nginx-upload-progress-module rm -r debian/nginx-upload-progress/test Version: v0.9.1 nginx-cache-purge Homepage: https://github.com/FRiCKLE/ngx_cache_purge/ Version: 2.3 nginx-dav-ext-module Homepage: https://github.com/arut/nginx-dav-ext-module Version: v0.0.3 ngx-fancyindex Homepage: https://github.com/aperezdc/ngx-fancyindex Version: v0.3.5 ngx_http_substitutions_filter_module Homepage: https://github.com/yaoweibin/ngx_http_substitutions_filter_module Version: v0.6.4 debian/modules/ngx-fancyindex/0000775000000000000000000000000012705233614013565 5ustar debian/modules/ngx-fancyindex/HACKING.md0000664000000000000000000000162512705233614015157 0ustar # Fancy Index module Hacking HOW-TO ## How to modify the template The template is in the `template.html` file. Note that comment markers are used to control how the `template.awk` Awk script generates the C header which gets ultimately included in the compiled object code. Comment markers have the `` format. Here `identifier` must be a valid C identifier. All the text following the marker until the next marker will be flattened into a C string. If the identifier is `NONE` (capitalized) the text from that marker up to the next marker will be discarded. ## Regenerating the C header You will need Awk. I hope any decent implementation will do, but the GNU one is known to work flawlessly. Just do: $ awk -f template.awk template.html > template.h If your copy of `awk` is not the GNU implementation, you will need to install it and use `gawk` instead in the command line above. debian/modules/ngx-fancyindex/ngx_http_fancyindex_module.c0000664000000000000000000012110612705233614021342 0ustar /* * ngx_http_fancyindex_module.c * Copyright © 2007-2013 Adrian Perez * * Module used for fancy indexing of directories. Features and differences * with the stock nginx autoindex module: * * - Output is a table instead of a
 element with embedded  links.
 *  - Header and footer may be added to every generated directory listing.
 *  - Default header and/or footer are generated if custom ones are not
 *    configured. Files used for header and footer can only be local path
 *    names (i.e. you cannot insert the result of a subrequest.)
 *  - Proper HTML is generated: it should validate both as XHTML 1.0 Strict
 *    and HTML 4.01.
 *
 * Base functionality heavy based upon the stock nginx autoindex module,
 * which in turn was made by Igor Sysoev, like the majority of nginx.
 *
 * Distributed under terms of the BSD license.
 */

#include 
#include 
#include 
#include 

#include "template.h"

#if defined(__GNUC__) && (__GNUC__ >= 3)
# define ngx_force_inline __attribute__((__always_inline__))
#else /* !__GNUC__ */
# define ngx_force_inline
#endif /* __GNUC__ */



/**
 * Configuration structure for the fancyindex module. The configuration
 * commands defined in the module do fill in the members of this structure.
 */
typedef struct {
    ngx_flag_t enable;       /**< Module is enabled. */
    ngx_uint_t default_sort; /**< Default sort criterion. */
    ngx_flag_t localtime;    /**< File mtime dates are sent in local time. */
    ngx_flag_t exact_size;   /**< Sizes are sent always in bytes. */
    ngx_uint_t name_length;  /**< Maximum length of file names in bytes. */

    ngx_str_t  header;       /**< File name for header, or empty if none. */
    ngx_str_t  footer;       /**< File name for footer, or empty if none. */
    ngx_str_t  css_href;     /**< Link to a CSS stylesheet, or empty if none. */

    ngx_array_t *ignore;     /**< List of files to ignore in listings. */
} ngx_http_fancyindex_loc_conf_t;

#define NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME       0
#define NGX_HTTP_FANCYINDEX_SORT_CRITERION_SIZE       1
#define NGX_HTTP_FANCYINDEX_SORT_CRITERION_DATE       2
#define NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME_DESC  3
#define NGX_HTTP_FANCYINDEX_SORT_CRITERION_SIZE_DESC  4
#define NGX_HTTP_FANCYINDEX_SORT_CRITERION_DATE_DESC  5

static ngx_conf_enum_t ngx_http_fancyindex_sort_criteria[] = {
    { ngx_string("name"), NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME },
    { ngx_string("size"), NGX_HTTP_FANCYINDEX_SORT_CRITERION_SIZE },
    { ngx_string("date"), NGX_HTTP_FANCYINDEX_SORT_CRITERION_DATE },
    { ngx_string("name_desc"), NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME_DESC },
    { ngx_string("size_desc"), NGX_HTTP_FANCYINDEX_SORT_CRITERION_SIZE_DESC },
    { ngx_string("date_desc"), NGX_HTTP_FANCYINDEX_SORT_CRITERION_DATE_DESC },
    { ngx_null_string, 0 }
};


#define NGX_HTTP_FANCYINDEX_PREALLOCATE  50


/**
 * Calculates the length of a NULL-terminated string. It is ugly having to
 * remember to substract 1 from the sizeof result.
 */
#define ngx_sizeof_ssz(_s)  (sizeof(_s) - 1)


/**
 * Copy a static zero-terminated string. Useful to output template
 * string pieces into a temporary buffer.
 */
#define ngx_cpymem_ssz(_p, _t) \
	(ngx_cpymem((_p), (_t), sizeof(_t) - 1))

/**
 * Copy a ngx_str_t.
 */
#define ngx_cpymem_str(_p, _s) \
	(ngx_cpymem((_p), (_s).data, (_s).len))

/**
 * Check whether a particular bit is set in a particular value.
 */
#define ngx_has_flag(_where, _what) \
	(((_where) & (_what)) == (_what))




typedef struct {
    ngx_str_t      name;
    size_t         utf_len;
    ngx_uint_t     escape;
    ngx_uint_t     dir;
    time_t         mtime;
    off_t          size;
} ngx_http_fancyindex_entry_t;



static int ngx_libc_cdecl
    ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two);
static int ngx_libc_cdecl
    ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two);
static int ngx_libc_cdecl
    ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two);
static int ngx_libc_cdecl
    ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two);
static int ngx_libc_cdecl
    ngx_http_fancyindex_cmp_entries_size_asc(const void *one, const void *two);
static int ngx_libc_cdecl
    ngx_http_fancyindex_cmp_entries_mtime_asc(const void *one, const void *two);

static ngx_int_t ngx_http_fancyindex_error(ngx_http_request_t *r,
    ngx_dir_t *dir, ngx_str_t *name);

static ngx_int_t ngx_http_fancyindex_init(ngx_conf_t *cf);

static void *ngx_http_fancyindex_create_loc_conf(ngx_conf_t *cf);

static char *ngx_http_fancyindex_merge_loc_conf(ngx_conf_t *cf,
    void *parent, void *child);

static char *ngx_http_fancyindex_ignore(ngx_conf_t    *cf,
                                        ngx_command_t *cmd,
                                        void          *conf);

static uintptr_t
    ngx_fancyindex_escape_uri(u_char *dst, u_char*src, size_t size);

/*
 * These are used only once per handler invocation. We can tell GCC to
 * inline them always, if possible (see how ngx_force_inline is defined
 * above).
 */
static ngx_inline ngx_buf_t*
    make_header_buf(ngx_http_request_t *r, const ngx_str_t css_href)
    ngx_force_inline;

static ngx_inline ngx_buf_t*
    make_footer_buf(ngx_http_request_t *r)
    ngx_force_inline;



static ngx_command_t  ngx_http_fancyindex_commands[] = {

    { ngx_string("fancyindex"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_fancyindex_loc_conf_t, enable),
      NULL },

    { ngx_string("fancyindex_default_sort"),
      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_fancyindex_loc_conf_t, default_sort),
      &ngx_http_fancyindex_sort_criteria },

    { ngx_string("fancyindex_localtime"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_fancyindex_loc_conf_t, localtime),
      NULL },

    { ngx_string("fancyindex_exact_size"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_fancyindex_loc_conf_t, exact_size),
      NULL },

    { ngx_string("fancyindex_name_length"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_num_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_fancyindex_loc_conf_t, name_length),
      NULL },

    { ngx_string("fancyindex_header"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_str_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_fancyindex_loc_conf_t, header),
      NULL },

    { ngx_string("fancyindex_footer"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_str_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_fancyindex_loc_conf_t, footer),
      NULL },

    { ngx_string("fancyindex_css_href"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
      ngx_conf_set_str_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_fancyindex_loc_conf_t, css_href),
      NULL },

    { ngx_string("fancyindex_ignore"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
      ngx_http_fancyindex_ignore,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },

    ngx_null_command
};


static ngx_http_module_t  ngx_http_fancyindex_module_ctx = {
    NULL,                                  /* preconfiguration */
    ngx_http_fancyindex_init,              /* postconfiguration */

    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */

    NULL,                                  /* create server configuration */
    NULL,                                  /* merge server configuration */

    ngx_http_fancyindex_create_loc_conf,   /* create location configration */
    ngx_http_fancyindex_merge_loc_conf     /* merge location configration */
};


ngx_module_t  ngx_http_fancyindex_module = {
    NGX_MODULE_V1,
    &ngx_http_fancyindex_module_ctx,       /* module context */
    ngx_http_fancyindex_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 const ngx_str_t css_href_pre =
    ngx_string("\n");


static uintptr_t
ngx_fancyindex_escape_uri(u_char *dst, u_char *src, size_t size)
{
    /*
     * The ngx_escape_uri() function will not escape colons or the
     * ? character, which signals the beginning of the query string.
     * So we handle those characters ourselves.
     *
     * TODO: Get rid of this once ngx_escape_uri() works as expected!
     */

    u_int escapes = 0;
    u_char *psrc = src;
    size_t psize = size;

    while (psize--) {
        switch (*psrc++) {
            case ':':
            case '?':
                escapes++;
                break;
        }
    }

    if (dst == NULL) {
        return escapes + ngx_escape_uri(NULL, src, size, NGX_ESCAPE_HTML);
    }
    else if (escapes == 0) {
        /* No need to do extra escaping, avoid the temporary buffer */
        return ngx_escape_uri(dst, src, size, NGX_ESCAPE_HTML);
    }
    else {
        uintptr_t uescapes = ngx_escape_uri(NULL, src, size, NGX_ESCAPE_HTML);
        size_t bufsz = size + 2 * uescapes;

        /*
         * GCC and CLANG both support stack-allocated variable length
         * arrays. Take advantage of that to avoid a malloc-free cycle.
         */
#if defined(__GNUC__) || defined(__clang__)
        u_char cbuf[bufsz];
        u_char *buf = cbuf;
#else  /* __GNUC__ || __clang__ */
        u_char *buf = (u_char*) malloc(sizeof(u_char) * bufsz);
#endif /* __GNUC__ || __clang__ */

        ngx_escape_uri(buf, src, size, NGX_ESCAPE_HTML);

        while (bufsz--) {
            switch (*buf) {
                case ':':
                    *dst++ = '%';
                    *dst++ = '3';
                    *dst++ = 'A';
                    break;
                case '?':
                    *dst++ = '%';
                    *dst++ = '3';
                    *dst++ = 'F';
                    break;
                default:
                    *dst++ = *buf;
            }
            buf++;
        }

#if !defined(__GNUC__) && !defined(__clang__)
        free(buf);
#endif /* !__GNUC__ && !__clang__ */

        return escapes + uescapes;
    }
}


static ngx_inline ngx_buf_t*
make_header_buf(ngx_http_request_t *r, const ngx_str_t css_href)
{
    size_t blen = r->uri.len
        + ngx_sizeof_ssz(t01_head1)
        + ngx_sizeof_ssz(t02_head2)
        + ngx_sizeof_ssz(t03_head3)
        + ngx_sizeof_ssz(t04_body1)
        ;

    if (css_href.len) {
        blen += css_href_pre.len \
              + css_href.len \
              + css_href_post.len
              ;
    }

    ngx_buf_t *b = ngx_create_temp_buf(r->pool, blen);

    if (b == NULL) goto bailout;

    b->last = ngx_cpymem_ssz(b->last, t01_head1);

    if (css_href.len) {
        b->last = ngx_cpymem_str(b->last, css_href_pre);
        b->last = ngx_cpymem_str(b->last, css_href);
        b->last = ngx_cpymem_str(b->last, css_href_post);
    }

    b->last = ngx_cpymem_ssz(b->last, t02_head2);
    b->last = ngx_cpymem_str(b->last, r->uri);
    b->last = ngx_cpymem_ssz(b->last, t03_head3);
    b->last = ngx_cpymem_ssz(b->last, t04_body1);

bailout:
    return b;
}



static ngx_inline ngx_buf_t*
make_footer_buf(ngx_http_request_t *r)
{
    /*
     * TODO: Make this buffer static (i.e. readonly and reusable from
     * one request to another.
     */
    ngx_buf_t *b = ngx_create_temp_buf(r->pool, ngx_sizeof_ssz(t08_foot1));

    if (b == NULL) goto bailout;

    b->last = ngx_cpymem_ssz(b->last, t08_foot1);

bailout:
    return b;
}



static ngx_inline ngx_int_t
make_content_buf(
        ngx_http_request_t *r, ngx_buf_t **pb,
        ngx_http_fancyindex_loc_conf_t *alcf)
{
    ngx_http_fancyindex_entry_t *entry;

    int (*sort_cmp_func) (const void*, const void*);
    const char  *sort_url_args = "";

    off_t        length;
    size_t       len, root, copy, allocated;
    u_char      *filename, *last, scale;
    ngx_tm_t     tm;
    ngx_array_t  entries;
    ngx_time_t  *tp;
    ngx_uint_t   i;
    ngx_int_t    size;
    ngx_str_t    path;
    ngx_dir_t    dir;
    ngx_buf_t   *b;

    static char *months[] = {
        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
    };

    /*
     * NGX_DIR_MASK_LEN is lesser than NGX_HTTP_FANCYINDEX_PREALLOCATE
     */
    if ((last = ngx_http_map_uri_to_path(r, &path, &root,
                    NGX_HTTP_FANCYINDEX_PREALLOCATE)) == NULL)
        return NGX_HTTP_INTERNAL_SERVER_ERROR;

    allocated = path.len;
    path.len  = last - path.data - 1;
    path.data[path.len] = '\0';

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http fancyindex: \"%s\"", path.data);

    if (ngx_open_dir(&path, &dir) == NGX_ERROR) {
        ngx_int_t rc, err = ngx_errno;
        ngx_uint_t level;

        if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) {
            level = NGX_LOG_ERR;
            rc = NGX_HTTP_NOT_FOUND;
        } else if (err == NGX_EACCES) {
            level = NGX_LOG_ERR;
            rc = NGX_HTTP_FORBIDDEN;
        } else {
            level = NGX_LOG_CRIT;
            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        ngx_log_error(level, r->connection->log, err,
                ngx_open_dir_n " \"%s\" failed", path.data);

        return rc;
    }

#if (NGX_SUPPRESS_WARN)
    /* MSVC thinks 'entries' may be used without having been initialized */
    ngx_memzero(&entries, sizeof(ngx_array_t));
#endif /* NGX_SUPPRESS_WARN */


    if (ngx_array_init(&entries, r->pool, 40,
                sizeof(ngx_http_fancyindex_entry_t)) != NGX_OK)
        return ngx_http_fancyindex_error(r, &dir, &path);

    filename = path.data;
    filename[path.len] = '/';

    /* Read directory entries and their associated information. */
    for (;;) {
        ngx_set_errno(0);

        if (ngx_read_dir(&dir) == NGX_ERROR) {
            ngx_int_t err = ngx_errno;

            if (err != NGX_ENOMOREFILES) {
                ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
                        ngx_read_dir_n " \"%V\" failed", &path);
                return ngx_http_fancyindex_error(r, &dir, &path);
            }
            break;
        }

        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "http fancyindex file: \"%s\"", ngx_de_name(&dir));

        len = ngx_de_namelen(&dir);

        if (ngx_de_name(&dir)[0] == '.')
            continue;

#if NGX_PCRE
        {
            ngx_str_t str = { len, ngx_de_name(&dir) };

            if (alcf->ignore && ngx_regex_exec_array(alcf->ignore, &str,
                                                     r->connection->log)
                != NGX_DECLINED)
            {
                continue;
            }
        }
#else /* !NGX_PCRE */
        if (alcf->ignore) {
            u_int match_found = 0;
            ngx_str_t *s = alcf->ignore->elts;

            for (i = 0; i < alcf->ignore->nelts; i++, s++) {
                if (ngx_strcmp(ngx_de_name(&dir), s->data) == 0) {
                    match_found = 1;
                    break;
                }
            }

            if (match_found) {
                continue;
            }
        }
#endif /* NGX_PCRE */

        if (!dir.valid_info) {
            /* 1 byte for '/' and 1 byte for terminating '\0' */
            if (path.len + 1 + len + 1 > allocated) {
                allocated = path.len + 1 + len + 1
                          + NGX_HTTP_FANCYINDEX_PREALLOCATE;

                if ((filename = ngx_palloc(r->pool, allocated)) == NULL)
                    return ngx_http_fancyindex_error(r, &dir, &path);

                last = ngx_cpystrn(filename, path.data, path.len + 1);
                *last++ = '/';
            }

            ngx_cpystrn(last, ngx_de_name(&dir), len + 1);

            if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) {
                ngx_int_t err = ngx_errno;

                if (err != NGX_ENOENT) {
                    ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
                            ngx_de_info_n " \"%s\" failed", filename);
                    continue;
                }

                if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) {
                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                            ngx_de_link_info_n " \"%s\" failed", filename);
                    return ngx_http_fancyindex_error(r, &dir, &path);
                }
            }
        }

        if ((entry = ngx_array_push(&entries)) == NULL)
            return ngx_http_fancyindex_error(r, &dir, &path);

        entry->name.len  = len;
        entry->name.data = ngx_palloc(r->pool, len + 1);
        if (entry->name.data == NULL)
            return ngx_http_fancyindex_error(r, &dir, &path);

        ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);
        entry->escape = 2 * ngx_fancyindex_escape_uri(NULL,
                                                      ngx_de_name(&dir),
                                                      len);

        entry->dir     = ngx_de_is_dir(&dir);
        entry->mtime   = ngx_de_mtime(&dir);
        entry->size    = ngx_de_size(&dir);
        entry->utf_len = (r->headers_out.charset.len == 5 &&
                ngx_strncasecmp(r->headers_out.charset.data, (u_char*) "utf-8", 5) == 0)
            ?  ngx_utf8_length(entry->name.data, entry->name.len)
            : len;
    }

    if (ngx_close_dir(&dir) == NGX_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                ngx_close_dir_n " \"%s\" failed", &path);
    }

    /*
     * Calculate needed buffer length.
     */
    len = r->uri.len
        + ngx_sizeof_ssz(t05_body2)
        + ngx_sizeof_ssz(t06_list1)
        + ngx_sizeof_ssz(t_parentdir_entry)
        + ngx_sizeof_ssz(t07_list2)
        ;

    entry = entries.elts;
    for (i = 0; i < entries.nelts; i++) {
        /*
         * Genearated table rows are as follows, unneeded whitespace
         * is stripped out:
         *
         *   
         *     fname
         *     sizedate
         *   
         */
        len += ngx_sizeof_ssz("")
            + entry[i].name.len + entry[i].utf_len
            + alcf->name_length + ngx_sizeof_ssz(">")
            + ngx_sizeof_ssz("")
            + 20 /* File size */
            + ngx_sizeof_ssz("")
            + ngx_sizeof_ssz(" 28-Sep-1970 12:00 ")
            + ngx_sizeof_ssz("\n")
            + 2 /* CR LF */
            ;
    }

    if ((b = ngx_create_temp_buf(r->pool, len)) == NULL)
        return NGX_HTTP_INTERNAL_SERVER_ERROR;

    /*
     * Determine the sorting criteria. URL arguments look like:
     *
     *    C=x[&O=y]
     *
     * Where x={M,S,N} and y={A,D}
     */
    if ((r->args.len == 3 || (r->args.len == 7 && r->args.data[3] == '&')) &&
        r->args.data[0] == 'C' && r->args.data[1] == '=')
    {
        /* Determine whether the direction of the sorting */
        ngx_int_t sort_descending = r->args.len == 7
                                 && r->args.data[4] == 'O'
                                 && r->args.data[5] == '='
                                 && r->args.data[6] == 'D';

        /* Pick the sorting criteria */
        switch (r->args.data[2]) {
            case 'M': /* Sort by mtime */
                if (sort_descending) {
                    sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime_desc;
                    if (alcf->default_sort != NGX_HTTP_FANCYINDEX_SORT_CRITERION_DATE_DESC)
                        sort_url_args = "?C=M&O=D";
                }
                else {
                    sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime_asc;
                    if (alcf->default_sort != NGX_HTTP_FANCYINDEX_SORT_CRITERION_DATE)
                        sort_url_args = "?C=M&O=A";
                }
                break;
            case 'S': /* Sort by size */
                if (sort_descending) {
                    sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_desc;
                    if (alcf->default_sort != NGX_HTTP_FANCYINDEX_SORT_CRITERION_SIZE_DESC)
                        sort_url_args = "?C=S&O=D";
                }
                else {
                    sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_asc;
                        if (alcf->default_sort != NGX_HTTP_FANCYINDEX_SORT_CRITERION_SIZE)
                    sort_url_args = "?C=S&O=A";
                }
                break;
            case 'N': /* Sort by name */
            default:
                if (sort_descending) {
                    sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_desc;
                    if (alcf->default_sort != NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME_DESC)
                        sort_url_args = "?C=N&O=D";
                }
                else {
                    sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc;
                    if (alcf->default_sort != NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME)
                        sort_url_args = "?C=N&O=A";
                }
                break;
        }
    }
    else {
        switch (alcf->default_sort) {
            case NGX_HTTP_FANCYINDEX_SORT_CRITERION_DATE_DESC:
                sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime_desc;
                break;
            case NGX_HTTP_FANCYINDEX_SORT_CRITERION_DATE:
                sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime_asc;
                break;
            case NGX_HTTP_FANCYINDEX_SORT_CRITERION_SIZE_DESC:
                sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_desc;
                break;
            case NGX_HTTP_FANCYINDEX_SORT_CRITERION_SIZE:
                sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_asc;
                break;
            case NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME_DESC:
                sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_desc;
                break;
            case NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME:
            default:
                sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc;
                break;
        }
    }

    /* Sort entries, if needed */
    if (entries.nelts > 1) {
        ngx_qsort(entry, (size_t) entries.nelts,
                  sizeof(ngx_http_fancyindex_entry_t),
                  sort_cmp_func);
    }

    b->last = ngx_cpymem_str(b->last, r->uri);
    b->last = ngx_cpymem_ssz(b->last, t05_body2);
    b->last = ngx_cpymem_ssz(b->last, t06_list1);

    tp = ngx_timeofday();

    /* "Parent dir" entry, always first */
    b->last = ngx_cpymem_ssz(b->last,
                             ""
                             "last = ngx_cpymem(b->last,
                             sort_url_args,
                             ngx_sizeof_ssz("?C=N&O=A"));
    }
    b->last = ngx_cpymem_ssz(b->last,
                             "\">Parent directory/"
                             "-"
                             "-"
                             "");

    /* Entries for directories and files */
    for (i = 0; i < entries.nelts; i++) {
        b->last = ngx_cpymem_ssz(b->last, "last,
                                      entry[i].name.data,
                                      entry[i].name.len);

            b->last += entry[i].name.len + entry[i].escape;

        } else {
            b->last = ngx_cpymem_str(b->last, entry[i].name);
        }

        if (entry[i].dir) {
            *b->last++ = '/';
            if (*sort_url_args) {
                b->last = ngx_cpymem(b->last,
                                     sort_url_args,
                                     ngx_sizeof_ssz("?C=x&O=y"));
            }
        }

        *b->last++ = '"';
        *b->last++ = '>';

        len = entry[i].utf_len;

        if (entry[i].name.len - len) {
            if (len > alcf->name_length) {
                copy = alcf->name_length - 3 + 1;
            } else {
                copy = alcf->name_length + 1;
            }

            b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
                                          copy, entry[i].name.len);
            last = b->last;

        } else {
            b->last = ngx_cpystrn(b->last, entry[i].name.data,
                                  alcf->name_length + 1);
            last = b->last - 3;
        }

        if (len > alcf->name_length) {
            b->last = ngx_cpymem_ssz(last, "..>");

        } else {
            if (entry[i].dir && alcf->name_length - len > 0) {
                *b->last++ = '/';
                len++;
            }

            b->last = ngx_cpymem_ssz(b->last, "");
        }

        if (alcf->exact_size) {
            if (entry[i].dir) {
                *b->last++ = '-';
            } else {
                b->last = ngx_sprintf(b->last, "%19O", entry[i].size);
            }

        } else {
            if (entry[i].dir) {
                *b->last++ = '-';
            } else {
                length = entry[i].size;

                if (length > 1024 * 1024 * 1024 - 1) {
                    size = (ngx_int_t) (length / (1024 * 1024 * 1024));
                    if ((length % (1024 * 1024 * 1024))
                                                > (1024 * 1024 * 1024 / 2 - 1))
                    {
                        size++;
                    }
                    scale = 'G';

                } else if (length > 1024 * 1024 - 1) {
                    size = (ngx_int_t) (length / (1024 * 1024));
                    if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) {
                        size++;
                    }
                    scale = 'M';

                } else if (length > 9999) {
                    size = (ngx_int_t) (length / 1024);
                    if (length % 1024 > 511) {
                        size++;
                    }
                    scale = 'K';

                } else {
                    size = (ngx_int_t) length;
                    scale = '\0';
                }

                if (scale) {
                    b->last = ngx_sprintf(b->last, "%6i%c", size, scale);

                } else {
                    b->last = ngx_sprintf(b->last, " %6i", size);
                }
            }
        }

        ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm);

        b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d",
                              tm.ngx_tm_mday,
                              months[tm.ngx_tm_mon - 1],
                              tm.ngx_tm_year,
                              tm.ngx_tm_hour,
                              tm.ngx_tm_min);


        *b->last++ = CR;
        *b->last++ = LF;
    }

    /* Output table bottom */
    b->last = ngx_cpymem_ssz(b->last, t07_list2);

    *pb = b;
    return NGX_OK;
}



static ngx_int_t
ngx_http_fancyindex_handler(ngx_http_request_t *r)
{
    ngx_http_request_t             *sr;
    ngx_str_t                      *sr_uri;
    ngx_str_t                       rel_uri;
    ngx_int_t                       rc;
    ngx_http_fancyindex_loc_conf_t *alcf;
    ngx_chain_t                     out[3] = {
        { NULL, NULL }, { NULL, NULL}, { NULL, NULL }};


    if (r->uri.data[r->uri.len - 1] != '/') {
        return NGX_DECLINED;
    }

    /* TODO: Win32 */
#if defined(nginx_version) \
    && ((nginx_version < 7066) \
        || ((nginx_version > 8000) && (nginx_version < 8038)))
    if (r->zero_in_uri) {
        return NGX_DECLINED;
    }
#endif

    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
        return NGX_DECLINED;
    }

    alcf = ngx_http_get_module_loc_conf(r, ngx_http_fancyindex_module);

    if (!alcf->enable) {
        return NGX_DECLINED;
    }

    if ((rc = make_content_buf(r, &out[0].buf, alcf) != NGX_OK))
        return rc;

    out[0].buf->last_in_chain = 1;

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_type_len  = ngx_sizeof_ssz("text/html");
    r->headers_out.content_type.len  = ngx_sizeof_ssz("text/html");
    r->headers_out.content_type.data = (u_char *) "text/html";

    rc = ngx_http_send_header(r);

    if (rc != NGX_OK || r->header_only)
        return rc;

    if (alcf->header.len > 0) {
        /* URI is configured, make Nginx take care of with a subrequest. */
        sr_uri = &alcf->header;

        if (*sr_uri->data != '/') {
            /* Relative path */
            rel_uri.len  = r->uri.len + alcf->header.len;
            rel_uri.data = ngx_palloc(r->pool, rel_uri.len);
            if (rel_uri.data == NULL) {
                return NGX_HTTP_INTERNAL_SERVER_ERROR;
            }
            ngx_memcpy(ngx_cpymem(rel_uri.data, r->uri.data, r->uri.len),
                    alcf->header.data, alcf->header.len);
            sr_uri = &rel_uri;
        }

        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                "http fancyindex: header subrequest \"%V\"", sr_uri);

        rc = ngx_http_subrequest(r, sr_uri, NULL, &sr, NULL, 0);
        if (rc == NGX_ERROR || rc == NGX_DONE) {
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http fancyindex: header subrequest for \"%V\" failed", sr_uri);
            return rc;
        }

        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                "http fancyindex: header subrequest status = %i",
                sr->headers_out.status);
	/* ngx_http_subrequest returns NGX_OK(0), not NGX_HTTP_OK(200) */
        if (sr->headers_out.status != NGX_OK) {
            /*
             * XXX: Should we write a message to the error log just in case
             * we get something different from a 404?
             */
            goto add_builtin_header;
        }
    }
    else {
add_builtin_header:
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                "http fancyindex: adding built-in header");
        /* Make space before */
        out[1].next = out[0].next;
        out[1].buf  = out[0].buf;
        /* Chain header buffer */
        out[0].next = &out[1];
        out[0].buf  = make_header_buf(r, alcf->css_href);
    }

    /* If footer is disabled, chain up footer buffer. */
    if (alcf->footer.len == 0) {
        ngx_uint_t last  = (alcf->header.len == 0) ? 2 : 1;

        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                "http fancyindex: adding built-in footer at %i", last);

        out[last-1].next = &out[last];
        out[last].buf    = make_footer_buf(r);

        out[last-1].buf->last_in_chain = 0;
        out[last].buf->last_in_chain   = 1;
        out[last].buf->last_buf        = 1;
        /* Send everything with a single call :D */
        return ngx_http_output_filter(r, &out[0]);
    }

    /*
     * If we reach here, we were asked to send a custom footer. We need to:
     * partially send whatever is referenced from out[0] and then send the
     * footer as a subrequest. If the subrequest fails, we should send the
     * standard footer as well.
     */
    rc = ngx_http_output_filter(r, &out[0]);

    if (rc != NGX_OK && rc != NGX_AGAIN)
        return NGX_HTTP_INTERNAL_SERVER_ERROR;

    /* URI is configured, make Nginx take care of with a subrequest. */
    sr_uri = &alcf->footer;

    if (*sr_uri->data != '/') {
        /* Relative path */
        rel_uri.len  = r->uri.len + alcf->footer.len;
        rel_uri.data = ngx_palloc(r->pool, rel_uri.len);
        if (rel_uri.data == NULL) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
        ngx_memcpy(ngx_cpymem(rel_uri.data, r->uri.data, r->uri.len),
                alcf->footer.data, alcf->footer.len);
        sr_uri = &rel_uri;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
            "http fancyindex: footer subrequest \"%V\"", sr_uri);

    rc = ngx_http_subrequest(r, sr_uri, NULL, &sr, NULL, 0);
    if (rc == NGX_ERROR || rc == NGX_DONE) {
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                "http fancyindex: footer subrequest for \"%V\" failed", sr_uri);
        return rc;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
            "http fancyindex: header subrequest status = %i",
            sr->headers_out.status);

    /* see above: ngx_http_subrequest resturns NGX_OK (0) not NGX_HTTP_OK (200) */
    if (sr->headers_out.status != NGX_OK) {
        /*
         * XXX: Should we write a message to the error log just in case
         * we get something different from a 404?
         */
        out[0].next = NULL;
        out[0].buf  = make_footer_buf(r);
        out[0].buf->last_in_chain = 1;
        out[0].buf->last_buf = 1;
        /* Directly send out the builtin footer */
        return ngx_http_output_filter(r, &out[0]);
    }

    return (r != r->main) ? rc : ngx_http_send_special(r, NGX_HTTP_LAST);
}


static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name_desc(const void *one, const void *two)
{
    ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
    ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;

    /* move the directories to the start */
    if (first->dir && !second->dir) {
        return -1;
    }
    if (!first->dir && second->dir) {
        return 1;
    }

    return (int) ngx_strcmp(second->name.data, first->name.data);
}


static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_size_desc(const void *one, const void *two)
{
    ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
    ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;

    /* move the directories to the start */
    if (first->dir && !second->dir) {
        return -1;
    }
    if (!first->dir && second->dir) {
        return 1;
    }

    return second->size - first->size;
}


static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime_desc(const void *one, const void *two)
{
    ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
    ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;

    /* move the directories to the start */
    if (first->dir && !second->dir) {
        return -1;
    }
    if (!first->dir && second->dir) {
        return 1;
    }

    return second->mtime - first->mtime;
}


static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_name_asc(const void *one, const void *two)
{
    ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
    ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;

    /* move the directories to the start */
    if (first->dir && !second->dir) {
        return -1;
    }
    if (!first->dir && second->dir) {
        return 1;
    }

    return (int) ngx_strcmp(first->name.data, second->name.data);
}


static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_size_asc(const void *one, const void *two)
{
    ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
    ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;

    /* move the directories to the start */
    if (first->dir && !second->dir) {
        return -1;
    }
    if (!first->dir && second->dir) {
        return 1;
    }

    return first->size - second->size;
}


static int ngx_libc_cdecl
ngx_http_fancyindex_cmp_entries_mtime_asc(const void *one, const void *two)
{
    ngx_http_fancyindex_entry_t *first = (ngx_http_fancyindex_entry_t *) one;
    ngx_http_fancyindex_entry_t *second = (ngx_http_fancyindex_entry_t *) two;

    /* move the directories to the start */
    if (first->dir && !second->dir) {
        return -1;
    }
    if (!first->dir && second->dir) {
        return 1;
    }

    return first->mtime - second->mtime;
}


static ngx_int_t
ngx_http_fancyindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name)
{
    if (ngx_close_dir(dir) == NGX_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                      ngx_close_dir_n " \"%V\" failed", name);
    }

    return NGX_HTTP_INTERNAL_SERVER_ERROR;
}


static void *
ngx_http_fancyindex_create_loc_conf(ngx_conf_t *cf)
{
    ngx_http_fancyindex_loc_conf_t  *conf;

    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fancyindex_loc_conf_t));
    if (conf == NULL) {
        return NGX_CONF_ERROR;
    }

    /*
     * Set by ngx_pcalloc:
     *    conf->header.len   = 0
     *    conf->header.data  = NULL
     *    conf->footer.len   = 0
     *    conf->footer.data  = NULL
     */
    conf->enable       = NGX_CONF_UNSET;
    conf->default_sort = NGX_CONF_UNSET_UINT;
    conf->localtime    = NGX_CONF_UNSET;
    conf->name_length  = NGX_CONF_UNSET_UINT;
    conf->exact_size   = NGX_CONF_UNSET;
    conf->ignore       = NGX_CONF_UNSET_PTR;

    return conf;
}


static char *
ngx_http_fancyindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_fancyindex_loc_conf_t *prev = parent;
    ngx_http_fancyindex_loc_conf_t *conf = child;

    ngx_conf_merge_value(conf->enable, prev->enable, 0);
    ngx_conf_merge_uint_value(conf->default_sort, prev->default_sort, NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME);
    ngx_conf_merge_value(conf->localtime, prev->localtime, 0);
    ngx_conf_merge_value(conf->exact_size, prev->exact_size, 1);
    ngx_conf_merge_uint_value(conf->name_length, prev->name_length, 50);

    ngx_conf_merge_str_value(conf->header, prev->header, "");
    ngx_conf_merge_str_value(conf->footer, prev->footer, "");

    ngx_conf_merge_ptr_value(conf->ignore, prev->ignore, NULL);

    return NGX_CONF_OK;
}


static char*
ngx_http_fancyindex_ignore(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_fancyindex_loc_conf_t *alcf = conf;
    ngx_str_t *value;

#if (NGX_PCRE)
    ngx_uint_t          i;
    ngx_regex_elt_t    *re;
    ngx_regex_compile_t rc;
    u_char              errstr[NGX_MAX_CONF_ERRSTR];

    if (alcf->ignore == NGX_CONF_UNSET_PTR) {
        alcf->ignore = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t));
        if (alcf->ignore == NULL) {
            return NGX_CONF_ERROR;
        }
    }

    value = cf->args->elts;

    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

    rc.err.data = errstr;
    rc.err.len  = NGX_MAX_CONF_ERRSTR;
    rc.pool     = cf->pool;

    for (i = 1; i < cf->args->nelts; i++) {
        re = ngx_array_push(alcf->ignore);
        if (re == NULL) {
            return NGX_CONF_ERROR;
        }

        rc.pattern = value[i];
        rc.options = NGX_REGEX_CASELESS;

        if (ngx_regex_compile(&rc) != NGX_OK) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
            return NGX_CONF_ERROR;
        }

        re->name  = value[i].data;
        re->regex = rc.regex;
    }

    return NGX_CONF_OK;
#else /* !NGX_PCRE */
    ngx_uint_t i;
    ngx_str_t *str;

    if (alcf->ignore == NGX_CONF_UNSET_PTR) {
        alcf->ignore = ngx_array_create(cf->pool, 2, sizeof(ngx_str_t));
        if (alcf->ignore == NULL) {
            return NGX_CONF_ERROR;
        }
    }

    value = cf->args->elts;

    for (i = 1; i < cf->args->nelts; i++) {
        str = ngx_array_push(alcf->ignore);
        if (str == NULL) {
            return NGX_CONF_ERROR;
        }

        str->data = value[i].data;
        str->len  = value[i].len;
    }

    return NGX_CONF_OK;
#endif /* NGX_PCRE */

}


static ngx_int_t
ngx_http_fancyindex_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_fancyindex_handler;

    return NGX_OK;
}

/* vim:et:sw=4:ts=4:
 */
debian/modules/ngx-fancyindex/nginx-0.6-support.patch0000664000000000000000000000150212705233614017742 0ustar  === modified file 'ngx_http_fancyindex_module.c'
--- ngx_http_fancyindex_module.c	2008-09-11 17:55:52 +0000
+++ ngx_http_fancyindex_module.c	2008-12-10 01:33:43 +0000
@@ -383,7 +383,7 @@
         entry->mtime   = ngx_de_mtime(&dir);
         entry->size    = ngx_de_size(&dir);
         entry->utf_len = (r->utf8)
-            ?  ngx_utf8_length(entry->name.data, entry->name.len)
+            ?  ngx_utf_length(entry->name.data, entry->name.len)
             : len;
     }
 
@@ -478,8 +478,7 @@
                 copy = NGX_HTTP_FANCYINDEX_NAME_LEN + 1;
             }
 
-            b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
-                                          copy, entry[i].name.len);
+            b->last = ngx_utf_cpystrn(b->last, entry[i].name.data, copy);
             last = b->last;
 
         } else {

debian/modules/ngx-fancyindex/template.awk0000775000000000000000000000165412705233614016115 0ustar  #! /usr/bin/awk -f
#
# Copyright © Adrian Perez 
#
# Converts an HTML template into a C header suitable for inclusion.
# Take a look at the HACKING.rst file to know how to use it :-)
#
# This code is placed in the public domain.

BEGIN {
	varname = 0;
	print "/* Automagically generated, do not edit! */"
	vars_count = 0;
}

/^$/ {
	if (varname) print ";";
	if ($3 == "NONE") {
		varname = 0;
		next;
	}
	varname = $3;
	vars[vars_count++] = varname;
	print "static const u_char " varname "[] = \"\"";
	next;
}

/^$/ {
	if (!varname) next;
	print "\"\\n\"";
	next;
}

{
	if (!varname) next;
	# Order matters
	gsub(/[\t\v\n\r\f]+/, "");
	gsub(/\\/, "\\\\");
	gsub(/"/, "\\\"");
	print "\"" $0 "\""
}


END {
	if (varname) print ";";
	print "#define NFI_TEMPLATE_SIZE (0 \\";
	for (var in vars) {
		print "\t+ nfi_sizeof_ssz(" vars[var] ") \\";
	}
	print "\t)"
}

debian/modules/ngx-fancyindex/config0000664000000000000000000000047312705233614014761 0ustar  # vim:ft=sh:
ngx_addon_name=ngx_http_fancyindex_module

# XXX: Insert fancyindex module *after* index module!
#
HTTP_MODULES=`echo "${HTTP_MODULES}" | sed -e \
	's/ngx_http_index_module/ngx_http_fancyindex_module ngx_http_index_module/'`
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_fancyindex_module.c"
debian/modules/ngx-fancyindex/template.html0000664000000000000000000000404112705233614016265 0ustar  




	
		
		
		



		Index of 
<!-- var NONE -->
			/path/to/somewhere
<!-- var t03_head3 -->
		

	

	
		

Index of /path/to/somewhere

File Name  ↓  File Size  ↓  Date  ↓ 
Parent directory/ - -
test file 1 123kB date
test file 2 321MB date
test file 3 666 date
debian/modules/ngx-fancyindex/CHANGELOG.md0000664000000000000000000000237612705233614015406 0ustar # Change Log All notable changes to this project will be documented in this file. ## Unreleased ### Added - New feature: Allow setting the default sort criterion using the `fancyindex_default_sort` configuration directive. (Patch by Алексей Урбанский). - New feature: Allos changing the maximum length of file names, using the `fancyindex_name_length` configuration directive. (Patch by Martin Herkt). ### Changed - Renames `NEWS.rst` to `CHANGELOG.md`, which follows the recommendations from [Keep a Change Log](http://keepachangelog.com/). ## 0.3.4 - 2014-09-03 ### Added - Viewport is now defined in the generated HTML, which works better for mobile devices. ### Changed - Even-odd row styling moved to the CSS using :nth-child(). This makes the HTML served to clients smaller. ## 0.3.3 - 2013-10-25 ### Added - New feature: table headers in the default template are now clickable to set the sorting criteria and direction of the index entries. (https://github.com/aperezdc/ngx-fancyindex/issues/7) ## 0.3.2 - 2013-06-05 ### Fixed - Solved a bug that would leave certain clients stalled forever. - Improved handling of subrequests for non-builtin headers/footers. ## 0.3.1 - 2011-04-04 ### Added - `NEWS.rst` file, to act as change log. debian/modules/ngx-fancyindex/README.rst0000664000000000000000000001311612705233614015256 0ustar ======================== Nginx Fancy Index module ======================== .. image:: https://drone.io/github.com/aperezdc/ngx-fancyindex/status.png :target: https://drone.io/github.com/aperezdc/ngx-fancyindex/latest :alt: Build Status .. contents:: The Fancy Index module makes possible the generation of file listings, like the built-in `autoindex `__ module does, but adding a touch of style. This is possible because the module module allows a certain degree of customization of the generated content: * Custom headers. Either local or stored remotely. * Custom footers. Either local or stored remotely. * Add you own CSS style rules. * Allow choosing to sort elements by name (default), modification time, or size; both ascending (default), or descending. This module is designed to work with Nginx_, a high performance open source web server written by `Igor Sysoev `__. Requirements ============ You will need the sources for Nginx_. Any version starting from the 0.7 series onwards will work. Note that the modules *might* compile with versions in the 0.6 series by applying ``nginx-0.6-support.patch``, but this is unsupported (YMMV). Building ======== 1. Unpack the Nginx_ sources:: $ gunzip -c nginx-?.?.?.tar.gz | tar -xvf - 2. Unpack the sources for the fancy indexing module:: $ gunzip -c nginx-fancyindex-?.?.?.tar.gz | tar -xvf - 3. Change to the directory which contains the Nginx_ sources, run the configuration script with the desired options and be sure to put an ``--add-module`` flag pointing to the directory which contains the source of the fancy indexing module:: $ cd nginx-?.?.? $ ./configure --add-module=../nginx-fancyindex-?.?.? [extra desired options] 4. Build and install the software:: $ make And then, as ``root``:: # make install 5. Configure Nginx_ by using the modules' configuration directives_. Example ======= You can test the default built-in style by adding the following lines into a ``server`` section in your Nginx_ configuration file:: location / { fancyindex on; # Enable fancy indexes. fancyindex_exact_size off; # Output human-readable file sizes. } Advanced Theming ~~~~~~~~~~~~~~~~ For a more elaborate example using `fancyindex_header`_ and `fancyindex_footer`_ you can check `nice theme `__ designed by `@TheInsomniac `__. Directives ========== fancyindex ~~~~~~~~~~ :Syntax: *fancyindex* [*on* | *off*] :Default: fancyindex off :Context: http, server, location :Description: Enables or disables fancy directory indexes. fancyindex_default_sort ~~~~~~~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_default_sort* [*name* | *size* | *date* | *name_desc* | *size_desc* | *date_desc*] :Default: fancyindex_default_sort name :Context: http, server, location :Description: Defines sorting criterion by default. fancyindex_css_href ~~~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_css_href uri* :Default: fancyindex_css_href "" :Context: http, server, location :Description: Allows inserting a link to a CSS style sheet in generated listings. The provided *uri* parameter will be inserted as-is in a ```` HTML tag. The link is inserted after the built-in CSS rules, so you can override the default styles. fancyindex_exact_size ~~~~~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_exact_size* [*on* | *off*] :Default: fancyindex_exact_size on :Context: http, server, location :Description: Defines how to represent file sizes in the directory listing; either accurately, or rounding off to the kilobyte, the megabyte and the gigabyte. fancyindex_name_length ~~~~~~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_name_length length* :Default: fancyindex_name_length 50 :Context: http, server, location :Description: Defines the maximum file name length limit in bytes. fancyindex_footer ~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_footer path* :Default: fancyindex_footer "" :Context: http, server, location :Description: Specifies which file should be inserted at the foot of directory listings. If set to an empty string, the default footer supplied by the module will be sent. .. warning:: When inserting custom header/footer a subrequest will be issued so potentially any URL can be used as source for them. Although it will work with external URLs, only using internal ones is supported. External URLs are totally untested and using them will make Nginx_ block while waiting for the subrequest to complete. If you feel like external header/footer is a must-have for you, please `let me know `__. fancyindex_header ~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_header path* :Default: fancyindex_header "" :Context: http, server, location :Description: Specifies which file should be inserted at the head of directory listings. If set to an empty string, the default header supplied by the module will be sent. fancyindex_ignore ~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_ignore string1 [string2 [... stringN]]* :Default: No default. :Context: http, server, location :Description: Specifies a list of file names which will be not be shown in generated listings. If Nginx was built with PCRE support strings are interpreted as regular expressions. fancyindex_localtime ~~~~~~~~~~~~~~~~~~~~ :Syntax: *fancyindex_localtime* [*on* | *off*] :Default: fancyindex_localtime off :Context: http, server, location :Description: Enables showing file times as local time. Default is “off” (GMT time). .. _nginx: http://nginx.net .. vim:ft=rst:spell:spelllang=en: debian/modules/ngx-fancyindex/LICENSE0000664000000000000000000000230112705233614014566 0ustar Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. debian/modules/ngx-fancyindex/template.h0000664000000000000000000000432512705233614015555 0ustar /* Automagically generated, do not edit! */ static const u_char t01_head1[] = "" "" "\n" "" "\n" "" "" "" "" "\n" ; static const u_char t02_head2[] = "" "\n" "Index of " ; static const u_char t03_head3[] = "" "" "\n" "" ; static const u_char t04_body1[] = "" "" "

Index of " ; static const u_char t05_body2[] = "" "

" "\n" ; static const u_char t06_list1[] = "" "" "\n" "" "" "" "" "" "\n" "" "" "" "" "" "" "" "\n" "" ; static const u_char t_parentdir_entry[] = "" "" "" "" "" "" "\n" ; static const u_char t07_list2[] = "" "" "
File Name  ↓ File Size  ↓ Date  ↓ 
Parent directory/--
" ; static const u_char t08_foot1[] = "" "" "" ; #define NFI_TEMPLATE_SIZE (0 \ + nfi_sizeof_ssz(t01_head1) \ + nfi_sizeof_ssz(t02_head2) \ + nfi_sizeof_ssz(t03_head3) \ + nfi_sizeof_ssz(t04_body1) \ + nfi_sizeof_ssz(t05_body2) \ + nfi_sizeof_ssz(t06_list1) \ + nfi_sizeof_ssz(t_parentdir_entry) \ + nfi_sizeof_ssz(t07_list2) \ + nfi_sizeof_ssz(t08_foot1) \ ) debian/modules/nginx-upstream-fair/0000775000000000000000000000000012705233614014543 5ustar debian/modules/nginx-upstream-fair/README0000664000000000000000000000254412705233614015430 0ustar Nginx Upstream Fair Proxy Load Balancer -- Description: -- The Nginx fair proxy balancer enhances the standard round-robin load balancer provided with Nginx so that it will track busy back end servers (e.g. Thin, Ebb, Mongrel) and balance the load to non-busy server processes. Further information can be found on http://nginx.localdomain.pl/ Ezra Zygmuntowicz has a good writeup of the fair proxy load balancer and how to use it here: http://brainspl.at/articles/2007/11/09/a-fair-proxy-balancer-for-nginx-and-mongrel Installation: -- You'll need to re-compile Nginx from source to include this module. Modify your compile of Nginx by adding the following directive (modified to suit your path of course): ./configure --with-http_ssl_module --add-module=/absolute/path/to/nginx-upstream-fair make make install Usage: -- Change your Nginx config file's upstream block to include the 'fair' directive: upstream mongrel { fair; server 127.0.0.1:5000; server 127.0.0.1:5001; server 127.0.0.1:5002; } If you encounter any issues, please report them using the bugtracker at http://nginx.localdomain.pl/ Contributing: -- Git source repositories: http://github.com/gnosek/nginx-upstream-fair/tree/master http://git.localdomain.pl/?p=nginx-upstream-fair.git;a=summary Please feel free to fork the project at GitHub and submit pull requests or patches. debian/modules/nginx-upstream-fair/.gdbinit0000664000000000000000000000230112705233614016160 0ustar define show_fair_peer set $n = (ngx_http_upstream_fair_shm_block_t *)$arg0 set $peers = $n->peers printf "upstream id: 0x%08x (%s), current peer: %d/%d\n", $n->node.key, $peers->name.data, $peers->current, $peers->number set $i = 0 while $i < $peers->number set $peer = &$peers->peer[$i] printf "peer %d: %s weight: %d/%d fails: %d/%d acc: %d down: %d nreq: %u last_req_id: %u\n", $i, $peer->name.data,\ $peer->shared->current_weight, $peer->weight,\ $peer->shared->fails, $peer->max_fails,\ $peer->accessed, $peer->down,\ $peer->shared->nreq, $peer->shared->last_req_id set $i = $i + 1 end printf "-----------------\n" if ($n->node.left != $arg1) show_fair_peer $n->node.left $arg1 end if ($n->node.right != $arg1) show_fair_peer $n->node.right $arg1 end end define show_fair_peers set $tree = ngx_http_upstream_fair_rbtree if (!$tree) printf "Cannot find the upstream_fair peer information tree\n" else set $root = (ngx_http_upstream_fair_shm_block_t *)($tree->root) if ($root != $tree->sentinel) show_fair_peer $root $tree->sentinel else printf "No upstream_fair peer information\n" end end end document show_fair_peers Dump upstream_fair peer infromation end debian/modules/nginx-upstream-fair/ngx_http_upstream_fair_module.c0000664000000000000000000012172612705233614023041 0ustar /* * Copyright (C) 2007 Grzegorz Nosek * Work sponsored by Ezra Zygmuntowicz & EngineYard.com * * Based on nginx source (C) Igor Sysoev */ #include #include #include typedef struct { ngx_uint_t nreq; ngx_uint_t total_req; ngx_uint_t last_req_id; ngx_uint_t fails; ngx_uint_t current_weight; } ngx_http_upstream_fair_shared_t; typedef struct ngx_http_upstream_fair_peers_s ngx_http_upstream_fair_peers_t; typedef struct { ngx_rbtree_node_t node; ngx_uint_t generation; uintptr_t peers; /* forms a unique cookie together with generation */ ngx_uint_t total_nreq; ngx_uint_t total_requests; ngx_atomic_t lock; ngx_http_upstream_fair_shared_t stats[1]; } ngx_http_upstream_fair_shm_block_t; /* ngx_spinlock is defined without a matching unlock primitive */ #define ngx_spinlock_unlock(lock) (void) ngx_atomic_cmp_set(lock, ngx_pid, 0) typedef struct { ngx_http_upstream_fair_shared_t *shared; struct sockaddr *sockaddr; socklen_t socklen; ngx_str_t name; ngx_uint_t weight; ngx_uint_t max_fails; time_t fail_timeout; time_t accessed; ngx_uint_t down:1; #if (NGX_HTTP_SSL) ngx_ssl_session_t *ssl_session; /* local to a process */ #endif } ngx_http_upstream_fair_peer_t; #define NGX_HTTP_UPSTREAM_FAIR_NO_RR (1<<26) #define NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_IDLE (1<<27) #define NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_PEAK (1<<28) #define NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_MASK ((1<<27) | (1<<28)) enum { WM_DEFAULT = 0, WM_IDLE, WM_PEAK }; struct ngx_http_upstream_fair_peers_s { ngx_http_upstream_fair_shm_block_t *shared; ngx_uint_t current; ngx_uint_t size_err:1; ngx_uint_t no_rr:1; ngx_uint_t weight_mode:2; ngx_uint_t number; ngx_str_t *name; ngx_http_upstream_fair_peers_t *next; /* for backup peers support, not really used yet */ ngx_http_upstream_fair_peer_t peer[1]; }; #define NGX_PEER_INVALID (~0UL) typedef struct { ngx_http_upstream_fair_peers_t *peers; ngx_uint_t current; uintptr_t *tried; uintptr_t *done; uintptr_t data; uintptr_t data2; } ngx_http_upstream_fair_peer_data_t; static ngx_int_t ngx_http_upstream_init_fair(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us); static ngx_int_t ngx_http_upstream_get_fair_peer(ngx_peer_connection_t *pc, void *data); static void ngx_http_upstream_free_fair_peer(ngx_peer_connection_t *pc, void *data, ngx_uint_t state); static ngx_int_t ngx_http_upstream_init_fair_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us); static char *ngx_http_upstream_fair(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_upstream_fair_set_shm_size(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_int_t ngx_http_upstream_fair_init_module(ngx_cycle_t *cycle); #if (NGX_HTTP_EXTENDED_STATUS) static ngx_chain_t *ngx_http_upstream_fair_report_status(ngx_http_request_t *r, ngx_int_t *length); #endif #if (NGX_HTTP_SSL) static ngx_int_t ngx_http_upstream_fair_set_session(ngx_peer_connection_t *pc, void *data); static void ngx_http_upstream_fair_save_session(ngx_peer_connection_t *pc, void *data); #endif static ngx_command_t ngx_http_upstream_fair_commands[] = { { ngx_string("fair"), NGX_HTTP_UPS_CONF|NGX_CONF_ANY, ngx_http_upstream_fair, 0, 0, NULL }, { ngx_string("upstream_fair_shm_size"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_http_upstream_fair_set_shm_size, 0, 0, NULL }, ngx_null_command }; static ngx_http_module_t ngx_http_upstream_fair_module_ctx = { NULL, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ NULL, /* create location configuration */ NULL, /* merge location configuration */ #if (NGX_HTTP_EXTENDED_STATUS) ngx_http_upstream_fair_report_status, #endif }; ngx_module_t ngx_http_upstream_fair_module = { NGX_MODULE_V1, &ngx_http_upstream_fair_module_ctx, /* module context */ ngx_http_upstream_fair_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ ngx_http_upstream_fair_init_module, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING }; static ngx_uint_t ngx_http_upstream_fair_shm_size; static ngx_shm_zone_t * ngx_http_upstream_fair_shm_zone; static ngx_rbtree_t * ngx_http_upstream_fair_rbtree; static ngx_uint_t ngx_http_upstream_fair_generation; static int ngx_http_upstream_fair_compare_rbtree_node(const ngx_rbtree_node_t *v_left, const ngx_rbtree_node_t *v_right) { ngx_http_upstream_fair_shm_block_t *left, *right; left = (ngx_http_upstream_fair_shm_block_t *) v_left; right = (ngx_http_upstream_fair_shm_block_t *) v_right; if (left->generation < right->generation) { return -1; } else if (left->generation > right->generation) { return 1; } else { /* left->generation == right->generation */ if (left->peers < right->peers) { return -1; } else if (left->peers > right->peers) { return 1; } else { return 0; } } } /* * generic functions start here */ static void ngx_rbtree_generic_insert(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel, int (*compare)(const ngx_rbtree_node_t *left, const ngx_rbtree_node_t *right)) { for ( ;; ) { if (node->key < temp->key) { if (temp->left == sentinel) { temp->left = node; break; } temp = temp->left; } else if (node->key > temp->key) { if (temp->right == sentinel) { temp->right = node; break; } temp = temp->right; } else { /* node->key == temp->key */ if (compare(node, temp) < 0) { if (temp->left == sentinel) { temp->left = node; break; } temp = temp->left; } else { if (temp->right == sentinel) { temp->right = node; break; } temp = temp->right; } } } node->parent = temp; node->left = sentinel; node->right = sentinel; ngx_rbt_red(node); } #define NGX_BITVECTOR_ELT_SIZE (sizeof(uintptr_t) * 8) static uintptr_t * ngx_bitvector_alloc(ngx_pool_t *pool, ngx_uint_t size, uintptr_t *small) { ngx_uint_t nelts = (size + NGX_BITVECTOR_ELT_SIZE - 1) / NGX_BITVECTOR_ELT_SIZE; if (small && nelts == 1) { *small = 0; return small; } return ngx_pcalloc(pool, nelts * NGX_BITVECTOR_ELT_SIZE); } static ngx_int_t ngx_bitvector_test(uintptr_t *bv, ngx_uint_t bit) { ngx_uint_t n, m; n = bit / NGX_BITVECTOR_ELT_SIZE; m = 1 << (bit % NGX_BITVECTOR_ELT_SIZE); return bv[n] & m; } static void ngx_bitvector_set(uintptr_t *bv, ngx_uint_t bit) { ngx_uint_t n, m; n = bit / NGX_BITVECTOR_ELT_SIZE; m = 1 << (bit % NGX_BITVECTOR_ELT_SIZE); bv[n] |= m; } /* * generic functions end here */ static ngx_int_t ngx_http_upstream_fair_init_module(ngx_cycle_t *cycle) { ngx_http_upstream_fair_generation++; return NGX_OK; } static void ngx_http_upstream_fair_rbtree_insert(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) { ngx_rbtree_generic_insert(temp, node, sentinel, ngx_http_upstream_fair_compare_rbtree_node); } static ngx_int_t ngx_http_upstream_fair_init_shm_zone(ngx_shm_zone_t *shm_zone, void *data) { ngx_slab_pool_t *shpool; ngx_rbtree_t *tree; ngx_rbtree_node_t *sentinel; if (data) { shm_zone->data = data; return NGX_OK; } shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; tree = ngx_slab_alloc(shpool, sizeof *tree); if (tree == NULL) { return NGX_ERROR; } sentinel = ngx_slab_alloc(shpool, sizeof *sentinel); if (sentinel == NULL) { return NGX_ERROR; } ngx_rbtree_sentinel_init(sentinel); tree->root = sentinel; tree->sentinel = sentinel; tree->insert = ngx_http_upstream_fair_rbtree_insert; shm_zone->data = tree; ngx_http_upstream_fair_rbtree = tree; return NGX_OK; } static char * ngx_http_upstream_fair_set_shm_size(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ssize_t new_shm_size; ngx_str_t *value; value = cf->args->elts; new_shm_size = ngx_parse_size(&value[1]); if (new_shm_size == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Invalid memory area size `%V'", &value[1]); return NGX_CONF_ERROR; } new_shm_size = ngx_align(new_shm_size, ngx_pagesize); if (new_shm_size < 8 * (ssize_t) ngx_pagesize) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The upstream_fair_shm_size value must be at least %udKiB", (8 * ngx_pagesize) >> 10); new_shm_size = 8 * ngx_pagesize; } if (ngx_http_upstream_fair_shm_size && ngx_http_upstream_fair_shm_size != (ngx_uint_t) new_shm_size) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "Cannot change memory area size without restart, ignoring change"); } else { ngx_http_upstream_fair_shm_size = new_shm_size; } ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0, "Using %udKiB of shared memory for upstream_fair", new_shm_size >> 10); return NGX_CONF_OK; } static char * ngx_http_upstream_fair(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_upstream_srv_conf_t *uscf; ngx_uint_t i; ngx_uint_t extra_peer_flags = 0; for (i = 1; i < cf->args->nelts; i++) { ngx_str_t *value = cf->args->elts; if (ngx_strcmp(value[i].data, "no_rr") == 0) { extra_peer_flags |= NGX_HTTP_UPSTREAM_FAIR_NO_RR; } else if (ngx_strcmp(value[i].data, "weight_mode=peak") == 0) { if (extra_peer_flags & NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_MASK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "weight_mode= options are mutually exclusive"); return NGX_CONF_ERROR; } extra_peer_flags |= NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_PEAK; } else if (ngx_strcmp(value[i].data, "weight_mode=idle") == 0) { if (extra_peer_flags & NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_MASK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "weight_mode= options are mutually exclusive"); return NGX_CONF_ERROR; } extra_peer_flags |= NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_IDLE; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Invalid `fair' parameter `%V'", &value[i]); return NGX_CONF_ERROR; } } uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); uscf->peer.init_upstream = ngx_http_upstream_init_fair; uscf->flags = NGX_HTTP_UPSTREAM_CREATE |NGX_HTTP_UPSTREAM_WEIGHT |NGX_HTTP_UPSTREAM_MAX_FAILS |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT |NGX_HTTP_UPSTREAM_DOWN |extra_peer_flags; return NGX_CONF_OK; } static ngx_int_t ngx_http_upstream_cmp_servers(const void *one, const void *two) { const ngx_http_upstream_fair_peer_t *first, *second; first = one; second = two; return (first->weight < second->weight); } /* TODO: Actually support backup servers */ static ngx_int_t ngx_http_upstream_init_fair_rr(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { ngx_url_t u; ngx_uint_t i, j, n; ngx_http_upstream_server_t *server; ngx_http_upstream_fair_peers_t *peers, *backup; if (us->servers) { server = us->servers->elts; n = 0; for (i = 0; i < us->servers->nelts; i++) { if (server[i].backup) { continue; } n += server[i].naddrs; } peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_fair_peers_t) + sizeof(ngx_http_upstream_fair_peer_t) * (n - 1)); if (peers == NULL) { return NGX_ERROR; } peers->number = n; peers->name = &us->host; n = 0; for (i = 0; i < us->servers->nelts; i++) { for (j = 0; j < server[i].naddrs; j++) { if (server[i].backup) { continue; } peers->peer[n].sockaddr = server[i].addrs[j].sockaddr; peers->peer[n].socklen = server[i].addrs[j].socklen; peers->peer[n].name = server[i].addrs[j].name; peers->peer[n].max_fails = server[i].max_fails; peers->peer[n].fail_timeout = server[i].fail_timeout; peers->peer[n].down = server[i].down; peers->peer[n].weight = server[i].down ? 0 : server[i].weight; n++; } } us->peer.data = peers; ngx_sort(&peers->peer[0], (size_t) n, sizeof(ngx_http_upstream_fair_peer_t), ngx_http_upstream_cmp_servers); /* backup servers */ n = 0; for (i = 0; i < us->servers->nelts; i++) { if (!server[i].backup) { continue; } n += server[i].naddrs; } if (n == 0) { return NGX_OK; } backup = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_fair_peers_t) + sizeof(ngx_http_upstream_fair_peer_t) * (n - 1)); if (backup == NULL) { return NGX_ERROR; } backup->number = n; backup->name = &us->host; n = 0; for (i = 0; i < us->servers->nelts; i++) { for (j = 0; j < server[i].naddrs; j++) { if (!server[i].backup) { continue; } backup->peer[n].sockaddr = server[i].addrs[j].sockaddr; backup->peer[n].socklen = server[i].addrs[j].socklen; backup->peer[n].name = server[i].addrs[j].name; backup->peer[n].weight = server[i].weight; backup->peer[n].max_fails = server[i].max_fails; backup->peer[n].fail_timeout = server[i].fail_timeout; backup->peer[n].down = server[i].down; n++; } } peers->next = backup; ngx_sort(&backup->peer[0], (size_t) n, sizeof(ngx_http_upstream_fair_peer_t), ngx_http_upstream_cmp_servers); return NGX_OK; } /* an upstream implicitly defined by proxy_pass, etc. */ if (us->port == 0 && us->default_port == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no port in upstream \"%V\" in %s:%ui", &us->host, us->file_name, us->line); return NGX_ERROR; } ngx_memzero(&u, sizeof(ngx_url_t)); u.host = us->host; u.port = (in_port_t) (us->port ? us->port : us->default_port); if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "%s in upstream \"%V\" in %s:%ui", u.err, &us->host, us->file_name, us->line); } return NGX_ERROR; } n = u.naddrs; peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_fair_peers_t) + sizeof(ngx_http_upstream_fair_peer_t) * (n - 1)); if (peers == NULL) { return NGX_ERROR; } peers->number = n; peers->name = &us->host; for (i = 0; i < u.naddrs; i++) { peers->peer[i].sockaddr = u.addrs[i].sockaddr; peers->peer[i].socklen = u.addrs[i].socklen; peers->peer[i].name = u.addrs[i].name; peers->peer[i].weight = 1; peers->peer[i].max_fails = 1; peers->peer[i].fail_timeout = 10; } us->peer.data = peers; /* implicitly defined upstream has no backup servers */ return NGX_OK; } static ngx_int_t ngx_http_upstream_init_fair(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) { ngx_http_upstream_fair_peers_t *peers; ngx_uint_t n; ngx_str_t *shm_name; /* do the dirty work using rr module */ if (ngx_http_upstream_init_fair_rr(cf, us) != NGX_OK) { return NGX_ERROR; } /* setup our wrapper around rr */ peers = ngx_palloc(cf->pool, sizeof *peers); if (peers == NULL) { return NGX_ERROR; } peers = us->peer.data; n = peers->number; shm_name = ngx_palloc(cf->pool, sizeof *shm_name); shm_name->len = sizeof("upstream_fair") - 1; shm_name->data = (unsigned char *) "upstream_fair"; if (ngx_http_upstream_fair_shm_size == 0) { ngx_http_upstream_fair_shm_size = 8 * ngx_pagesize; } ngx_http_upstream_fair_shm_zone = ngx_shared_memory_add( cf, shm_name, ngx_http_upstream_fair_shm_size, &ngx_http_upstream_fair_module); if (ngx_http_upstream_fair_shm_zone == NULL) { return NGX_ERROR; } ngx_http_upstream_fair_shm_zone->init = ngx_http_upstream_fair_init_shm_zone; peers->shared = NULL; peers->current = n - 1; if (us->flags & NGX_HTTP_UPSTREAM_FAIR_NO_RR) { peers->no_rr = 1; } if (us->flags & NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_IDLE) { peers->weight_mode = WM_IDLE; } else if (us->flags & NGX_HTTP_UPSTREAM_FAIR_WEIGHT_MODE_PEAK) { peers->weight_mode = WM_PEAK; } peers->size_err = 0; us->peer.init = ngx_http_upstream_init_fair_peer; return NGX_OK; } static void ngx_http_upstream_fair_update_nreq(ngx_http_upstream_fair_peer_data_t *fp, int delta, ngx_log_t *log) { #if (NGX_DEBUG) ngx_uint_t nreq; ngx_uint_t total_nreq; nreq = (fp->peers->peer[fp->current].shared->nreq += delta); total_nreq = (fp->peers->shared->total_nreq += delta); ngx_log_debug6(NGX_LOG_DEBUG_HTTP, log, 0, "[upstream_fair] nreq for peer %ui @ %p/%p now %d, total %d, delta %d", fp->current, fp->peers, fp->peers->peer[fp->current].shared, nreq, total_nreq, delta); #endif } /* * SCHED_COUNTER_BITS is the portion of an ngx_uint_t which represents * the req_delta part (number of requests serviced on _other_ * backends). The rest (top bits) represents the number of currently * processed requests. * * The value is not too critical because overflow is handled via * saturation. With the default value of 20, scheduling is exact for * fewer than 4k concurrent requests per backend (on 32-bit * architectures) and fewer than 1M concurrent requests to all backends * together. Beyond these limits, the algorithm essentially falls back * to pure weighted round-robin. * * A higher score means less suitable. * * The `delta' parameter is bit-negated so that high values yield low * scores and get chosen more often. */ #define SCHED_COUNTER_BITS 20 #define SCHED_NREQ_MAX ((~0UL) >> SCHED_COUNTER_BITS) #define SCHED_COUNTER_MAX ((1 << SCHED_COUNTER_BITS) - 1) #define SCHED_SCORE(nreq,delta) (((nreq) << SCHED_COUNTER_BITS) | (~(delta) & SCHED_COUNTER_MAX)) #define ngx_upstream_fair_min(a,b) (((a) < (b)) ? (a) : (b)) static ngx_uint_t ngx_http_upstream_fair_sched_score(ngx_peer_connection_t *pc, ngx_http_upstream_fair_peer_data_t *fp, ngx_uint_t n) { ngx_http_upstream_fair_peer_t *peer = &fp->peers->peer[n]; ngx_http_upstream_fair_shared_t *fs = peer->shared; ngx_uint_t req_delta = fp->peers->shared->total_requests - fs->last_req_id; /* sanity check */ if ((ngx_int_t)fs->nreq < 0) { ngx_log_error(NGX_LOG_WARN, pc->log, 0, "[upstream_fair] upstream %ui has negative nreq (%i)", n, fs->nreq); return SCHED_SCORE(0, req_delta); } ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] peer %ui: nreq = %i, req_delta = %ui", n, fs->nreq, req_delta); return SCHED_SCORE( ngx_upstream_fair_min(fs->nreq, SCHED_NREQ_MAX), ngx_upstream_fair_min(req_delta, SCHED_COUNTER_MAX)); } /* * the core of load balancing logic */ static ngx_int_t ngx_http_upstream_fair_try_peer(ngx_peer_connection_t *pc, ngx_http_upstream_fair_peer_data_t *fp, ngx_uint_t peer_id) { ngx_http_upstream_fair_peer_t *peer; if (ngx_bitvector_test(fp->tried, peer_id)) return NGX_BUSY; peer = &fp->peers->peer[peer_id]; if (!peer->down) { if (peer->max_fails == 0 || peer->shared->fails < peer->max_fails) { return NGX_OK; } if (ngx_time() - peer->accessed > peer->fail_timeout) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] resetting fail count for peer %d, time delta %d > %d", peer_id, ngx_time() - peer->accessed, peer->fail_timeout); peer->shared->fails = 0; return NGX_OK; } } return NGX_BUSY; } static ngx_uint_t ngx_http_upstream_choose_fair_peer_idle(ngx_peer_connection_t *pc, ngx_http_upstream_fair_peer_data_t *fp) { ngx_uint_t i, n; ngx_uint_t npeers = fp->peers->number; ngx_uint_t weight_mode = fp->peers->weight_mode; ngx_uint_t best_idx = NGX_PEER_INVALID; ngx_uint_t best_nreq = ~0U; for (i = 0, n = fp->current; i < npeers; i++, n = (n + 1) % npeers) { ngx_uint_t nreq = fp->peers->peer[n].shared->nreq; ngx_uint_t weight = fp->peers->peer[n].weight; if (fp->peers->peer[n].shared->fails > 0) continue; if (nreq >= weight || (nreq > 0 && weight_mode != WM_IDLE)) { continue; } if (ngx_http_upstream_fair_try_peer(pc, fp, n) != NGX_OK) { continue; } /* not in WM_IDLE+no_rr mode: the first completely idle backend gets chosen */ if (weight_mode != WM_IDLE || !fp->peers->no_rr) { best_idx = n; break; } /* in WM_IDLE+no_rr mode we actually prefer slightly loaded backends * to totally idle ones, under the assumption that they're spawned * on demand and can handle up to 'weight' concurrent requests */ if (best_idx == NGX_PEER_INVALID || nreq) { if (best_nreq <= nreq) { continue; } best_idx = n; best_nreq = nreq; } } return best_idx; } static ngx_int_t ngx_http_upstream_choose_fair_peer_busy(ngx_peer_connection_t *pc, ngx_http_upstream_fair_peer_data_t *fp) { ngx_uint_t i, n; ngx_uint_t npeers = fp->peers->number; ngx_uint_t weight_mode = fp->peers->weight_mode; ngx_uint_t best_idx = NGX_PEER_INVALID; ngx_uint_t sched_score; ngx_uint_t best_sched_score = ~0UL; /* * calculate sched scores for all the peers, choosing the lowest one */ for (i = 0, n = fp->current; i < npeers; i++, n = (n + 1) % npeers) { ngx_http_upstream_fair_peer_t *peer; ngx_uint_t nreq; ngx_uint_t weight; peer = &fp->peers->peer[n]; nreq = fp->peers->peer[n].shared->nreq; if (weight_mode == WM_PEAK && nreq >= peer->weight) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] backend %d has nreq %ui >= weight %ui in WM_PEAK mode", n, nreq, peer->weight); continue; } if (ngx_http_upstream_fair_try_peer(pc, fp, n) != NGX_OK) { if (!pc->tries) { ngx_log_debug(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] all backends exhausted"); return NGX_PEER_INVALID; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] backend %d already tried", n); continue; } sched_score = ngx_http_upstream_fair_sched_score(pc, fp, n); if (weight_mode == WM_DEFAULT) { /* * take peer weight into account */ weight = peer->shared->current_weight; if (peer->max_fails) { ngx_uint_t mf = peer->max_fails; weight = peer->shared->current_weight * (mf - peer->shared->fails) / mf; } if (weight > 0) { sched_score /= weight; } ngx_log_debug8(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] bss = %ui, ss = %ui (n = %d, w = %d/%d, f = %d/%d, weight = %d)", best_sched_score, sched_score, n, peer->shared->current_weight, peer->weight, peer->shared->fails, peer->max_fails, weight); } if (sched_score <= best_sched_score) { best_idx = n; best_sched_score = sched_score; } } return best_idx; } static ngx_int_t ngx_http_upstream_choose_fair_peer(ngx_peer_connection_t *pc, ngx_http_upstream_fair_peer_data_t *fp, ngx_uint_t *peer_id) { ngx_uint_t npeers; ngx_uint_t best_idx = NGX_PEER_INVALID; ngx_uint_t weight_mode; npeers = fp->peers->number; weight_mode = fp->peers->weight_mode; /* just a single backend */ if (npeers == 1) { *peer_id = 0; return NGX_OK; } /* any idle backends? */ best_idx = ngx_http_upstream_choose_fair_peer_idle(pc, fp); if (best_idx != NGX_PEER_INVALID) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] peer %i is idle", best_idx); goto chosen; } /* no idle backends, choose the least loaded one */ best_idx = ngx_http_upstream_choose_fair_peer_busy(pc, fp); if (best_idx != NGX_PEER_INVALID) { goto chosen; } return NGX_BUSY; chosen: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] chose peer %i", best_idx); *peer_id = best_idx; ngx_bitvector_set(fp->tried, best_idx); if (weight_mode == WM_DEFAULT) { ngx_http_upstream_fair_peer_t *peer = &fp->peers->peer[best_idx]; if (peer->shared->current_weight-- == 0) { peer->shared->current_weight = peer->weight; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] peer %d expired weight, reset to %d", best_idx, peer->weight); } } return NGX_OK; } ngx_int_t ngx_http_upstream_get_fair_peer(ngx_peer_connection_t *pc, void *data) { ngx_int_t ret; ngx_uint_t peer_id, i; ngx_http_upstream_fair_peer_data_t *fp = data; ngx_http_upstream_fair_peer_t *peer; ngx_atomic_t *lock; peer_id = fp->current; fp->current = (fp->current + 1) % fp->peers->number; lock = &fp->peers->shared->lock; ngx_spinlock(lock, ngx_pid, 1024); ret = ngx_http_upstream_choose_fair_peer(pc, fp, &peer_id); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] fp->current = %d, peer_id = %d, ret = %d", fp->current, peer_id, ret); if (pc) pc->tries--; if (ret == NGX_BUSY) { for (i = 0; i < fp->peers->number; i++) { fp->peers->peer[i].shared->fails = 0; } pc->name = fp->peers->name; fp->current = NGX_PEER_INVALID; ngx_spinlock_unlock(lock); return NGX_BUSY; } /* assert(ret == NGX_OK); */ peer = &fp->peers->peer[peer_id]; fp->current = peer_id; if (!fp->peers->no_rr) { fp->peers->current = peer_id; } pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->name = &peer->name; peer->shared->last_req_id = fp->peers->shared->total_requests; ngx_http_upstream_fair_update_nreq(fp, 1, pc->log); peer->shared->total_req++; ngx_spinlock_unlock(lock); return ret; } void ngx_http_upstream_free_fair_peer(ngx_peer_connection_t *pc, void *data, ngx_uint_t state) { ngx_http_upstream_fair_peer_data_t *fp = data; ngx_http_upstream_fair_peer_t *peer; ngx_atomic_t *lock; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, pc->log, 0, "[upstream_fair] fp->current = %d, state = %ui, pc->tries = %d, pc->data = %p", fp->current, state, pc->tries, pc->data); if (fp->current == NGX_PEER_INVALID) { return; } lock = &fp->peers->shared->lock; ngx_spinlock(lock, ngx_pid, 1024); if (!ngx_bitvector_test(fp->done, fp->current)) { ngx_bitvector_set(fp->done, fp->current); ngx_http_upstream_fair_update_nreq(fp, -1, pc->log); } if (fp->peers->number == 1) { pc->tries = 0; } if (state & NGX_PEER_FAILED) { peer = &fp->peers->peer[fp->current]; peer->shared->fails++; peer->accessed = ngx_time(); } ngx_spinlock_unlock(lock); } /* * walk through the rbtree, removing old entries and looking for * a matching one -- compared by (cycle, peers) pair * * no attempt at optimisation is made, for two reasons: * - the tree will be quite small, anyway * - being called once per worker startup per upstream block, * this code isn't really the hot path */ static ngx_http_upstream_fair_shm_block_t * ngx_http_upstream_fair_walk_shm( ngx_slab_pool_t *shpool, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel, ngx_http_upstream_fair_peers_t *peers) { ngx_http_upstream_fair_shm_block_t *uf_node; ngx_http_upstream_fair_shm_block_t *found_node = NULL; ngx_http_upstream_fair_shm_block_t *tmp_node; if (node == sentinel) { return NULL; } /* visit left node */ if (node->left != sentinel) { tmp_node = ngx_http_upstream_fair_walk_shm(shpool, node->left, sentinel, peers); if (tmp_node) { found_node = tmp_node; } } /* visit right node */ if (node->right != sentinel) { tmp_node = ngx_http_upstream_fair_walk_shm(shpool, node->right, sentinel, peers); if (tmp_node) { found_node = tmp_node; } } /* visit current node */ uf_node = (ngx_http_upstream_fair_shm_block_t *) node; if (uf_node->generation != ngx_http_upstream_fair_generation) { ngx_spinlock(&uf_node->lock, ngx_pid, 1024); if (uf_node->total_nreq == 0) { /* don't bother unlocking */ ngx_rbtree_delete(ngx_http_upstream_fair_rbtree, node); ngx_slab_free_locked(shpool, node); } ngx_spinlock_unlock(&uf_node->lock); } else if (uf_node->peers == (uintptr_t) peers) { found_node = uf_node; } return found_node; } static ngx_int_t ngx_http_upstream_fair_shm_alloc(ngx_http_upstream_fair_peers_t *usfp, ngx_log_t *log) { ngx_slab_pool_t *shpool; ngx_uint_t i; if (usfp->shared) { return NGX_OK; } shpool = (ngx_slab_pool_t *)ngx_http_upstream_fair_shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); usfp->shared = ngx_http_upstream_fair_walk_shm(shpool, ngx_http_upstream_fair_rbtree->root, ngx_http_upstream_fair_rbtree->sentinel, usfp); if (usfp->shared) { ngx_shmtx_unlock(&shpool->mutex); return NGX_OK; } usfp->shared = ngx_slab_alloc_locked(shpool, sizeof(ngx_http_upstream_fair_shm_block_t) + (usfp->number - 1) * sizeof(ngx_http_upstream_fair_shared_t)); if (!usfp->shared) { ngx_shmtx_unlock(&shpool->mutex); if (!usfp->size_err) { ngx_log_error(NGX_LOG_EMERG, log, 0, "upstream_fair_shm_size too small (current value is %udKiB)", ngx_http_upstream_fair_shm_size >> 10); usfp->size_err = 1; } return NGX_ERROR; } usfp->shared->node.key = ngx_crc32_short((u_char *) &ngx_cycle, sizeof ngx_cycle) ^ ngx_crc32_short((u_char *) &usfp, sizeof(usfp)); usfp->shared->generation = ngx_http_upstream_fair_generation; usfp->shared->peers = (uintptr_t) usfp; usfp->shared->total_nreq = 0; usfp->shared->total_requests = 0; for (i = 0; i < usfp->number; i++) { usfp->shared->stats[i].nreq = 0; usfp->shared->stats[i].last_req_id = 0; usfp->shared->stats[i].total_req = 0; } ngx_rbtree_insert(ngx_http_upstream_fair_rbtree, &usfp->shared->node); ngx_shmtx_unlock(&shpool->mutex); return NGX_OK; } ngx_int_t ngx_http_upstream_init_fair_peer(ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us) { ngx_http_upstream_fair_peer_data_t *fp; ngx_http_upstream_fair_peers_t *usfp; ngx_uint_t n; fp = r->upstream->peer.data; if (fp == NULL) { fp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_fair_peer_data_t)); if (fp == NULL) { return NGX_ERROR; } r->upstream->peer.data = fp; } usfp = us->peer.data; fp->tried = ngx_bitvector_alloc(r->pool, usfp->number, &fp->data); fp->done = ngx_bitvector_alloc(r->pool, usfp->number, &fp->data2); if (fp->tried == NULL || fp->done == NULL) { return NGX_ERROR; } /* set up shared memory area */ ngx_http_upstream_fair_shm_alloc(usfp, r->connection->log); fp->current = usfp->current; fp->peers = usfp; usfp->shared->total_requests++; for (n = 0; n < usfp->number; n++) { usfp->peer[n].shared = &usfp->shared->stats[n]; } r->upstream->peer.get = ngx_http_upstream_get_fair_peer; r->upstream->peer.free = ngx_http_upstream_free_fair_peer; r->upstream->peer.tries = usfp->number; #if (NGX_HTTP_SSL) r->upstream->peer.set_session = ngx_http_upstream_fair_set_session; r->upstream->peer.save_session = ngx_http_upstream_fair_save_session; #endif return NGX_OK; } #if (NGX_HTTP_SSL) static ngx_int_t ngx_http_upstream_fair_set_session(ngx_peer_connection_t *pc, void *data) { ngx_http_upstream_fair_peer_data_t *fp = data; ngx_int_t rc; ngx_ssl_session_t *ssl_session; ngx_http_upstream_fair_peer_t *peer; if (fp->current == NGX_PEER_INVALID) return NGX_OK; peer = &fp->peers->peer[fp->current]; /* TODO: threads only mutex */ /* ngx_lock_mutex(fp->peers->mutex); */ ssl_session = peer->ssl_session; rc = ngx_ssl_set_session(pc->connection, ssl_session); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "set session: %p:%d", ssl_session, ssl_session ? ssl_session->references : 0); /* ngx_unlock_mutex(fp->peers->mutex); */ return rc; } static void ngx_http_upstream_fair_save_session(ngx_peer_connection_t *pc, void *data) { ngx_http_upstream_fair_peer_data_t *fp = data; ngx_ssl_session_t *old_ssl_session, *ssl_session; ngx_http_upstream_fair_peer_t *peer; if (fp->current == NGX_PEER_INVALID) return; ssl_session = ngx_ssl_get_session(pc->connection); if (ssl_session == NULL) { return; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "save session: %p:%d", ssl_session, ssl_session->references); peer = &fp->peers->peer[fp->current]; /* TODO: threads only mutex */ /* ngx_lock_mutex(fp->peers->mutex); */ old_ssl_session = peer->ssl_session; peer->ssl_session = ssl_session; /* ngx_unlock_mutex(fp->peers->mutex); */ if (old_ssl_session) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "old session: %p:%d", old_ssl_session, old_ssl_session->references); /* TODO: may block */ ngx_ssl_free_session(old_ssl_session); } } #endif #if (NGX_HTTP_EXTENDED_STATUS) static void ngx_http_upstream_fair_walk_status(ngx_pool_t *pool, ngx_chain_t *cl, ngx_int_t *length, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) { ngx_http_upstream_fair_shm_block_t *s_node = (ngx_http_upstream_fair_shm_block_t *) node; ngx_http_upstream_fair_peers_t *peers; ngx_chain_t *new_cl; ngx_buf_t *b; ngx_uint_t size, i; if (node == sentinel) { return; } if (node->left != sentinel) { ngx_http_upstream_fair_walk_status(pool, cl, length, node->left, sentinel); } if (s_node->generation != ngx_http_upstream_fair_generation) { size = 100; peers = NULL; } else { /* this is rather ugly (casting an uintptr_t back into a pointer * but as long as the generation is still the same (verified above), * it should be still safe */ peers = (ngx_http_upstream_fair_peers_t *) s_node->peers; if (!peers->shared) { goto next; } size = 200 + peers->number * 120; /* LOTS of slack */ } b = ngx_create_temp_buf(pool, size); if (!b) { goto next; } new_cl = ngx_alloc_chain_link(pool); if (!new_cl) { goto next; } new_cl->buf = b; new_cl->next = NULL; while (cl->next) { cl = cl->next; } cl->next = new_cl; if (peers) { b->last = ngx_sprintf(b->last, "upstream %V (%p): current peer %d/%d, total requests: %ui\n", peers->name, (void*) node, peers->current, peers->number, s_node->total_requests); for (i = 0; i < peers->number; i++) { ngx_http_upstream_fair_peer_t *peer = &peers->peer[i]; ngx_http_upstream_fair_shared_t *sh = peer->shared; b->last = ngx_sprintf(b->last, " peer %d: %V weight: %d/%d, fails: %d/%d, acc: %d, down: %d, nreq: %d, total_req: %ui, last_req: %ui\n", i, &peer->name, sh->current_weight, peer->weight, sh->fails, peer->max_fails, peer->accessed, peer->down, sh->nreq, sh->total_req, sh->last_req_id); } } else { b->last = ngx_sprintf(b->last, "upstream %p: gen %ui != %ui, total_nreq = %ui", (void*) node, s_node->generation, ngx_http_upstream_fair_generation, s_node->total_nreq); } b->last = ngx_sprintf(b->last, "\n"); b->last_buf = 1; *length += b->last - b->pos; if (cl->buf) { cl->buf->last_buf = 0; } cl = cl->next; next: if (node->right != sentinel) { ngx_http_upstream_fair_walk_status(pool, cl, length, node->right, sentinel); } } static ngx_chain_t* ngx_http_upstream_fair_report_status(ngx_http_request_t *r, ngx_int_t *length) { ngx_buf_t *b; ngx_chain_t *cl; ngx_slab_pool_t *shpool; b = ngx_create_temp_buf(r->pool, sizeof("\nupstream_fair status report:\n")); if (!b) { return NULL; } cl = ngx_alloc_chain_link(r->pool); if (!cl) { return NULL; } cl->next = NULL; cl->buf = b; b->last = ngx_cpymem(b->last, "\nupstream_fair status report:\n", sizeof("\nupstream_fair status report:\n") - 1); *length = b->last - b->pos; shpool = (ngx_slab_pool_t *)ngx_http_upstream_fair_shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); ngx_http_upstream_fair_walk_status(r->pool, cl, length, ngx_http_upstream_fair_rbtree->root, ngx_http_upstream_fair_rbtree->sentinel); ngx_shmtx_unlock(&shpool->mutex); if (!cl->next || !cl->next->buf) { /* no upstream_fair status to report */ return NULL; } return cl; } #endif /* vim: set et ts=4 sw=4: */ debian/modules/nginx-upstream-fair/config0000664000000000000000000000027012705233614015732 0ustar ngx_addon_name=ngx_http_upstream_fair_module HTTP_MODULES="$HTTP_MODULES ngx_http_upstream_fair_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_upstream_fair_module.c" debian/modules/headers-more-nginx-module/0000775000000000000000000000000012705233614015622 5ustar debian/modules/headers-more-nginx-module/util/0000775000000000000000000000000012705233614016577 5ustar debian/modules/headers-more-nginx-module/util/build.sh0000775000000000000000000000206112705233614020234 0ustar #!/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:$LIBDRIZZLE_LIB:$LUAJIT_LIB:/usr/local/lib" \ --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 \ --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?!) debian/modules/headers-more-nginx-module/t/0000775000000000000000000000000012705233614016065 5ustar debian/modules/headers-more-nginx-module/t/input-conn.t0000664000000000000000000000502612705233614020347 0ustar # 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] debian/modules/headers-more-nginx-module/t/vars.t0000664000000000000000000000151712705233614017231 0ustar # 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: debian/modules/headers-more-nginx-module/t/builtin.t0000664000000000000000000001347212705233614017727 0ustar # 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 debian/modules/headers-more-nginx-module/t/bug.t0000664000000000000000000001360512705233614017034 0ustar # vi:filetype= use Test::Nginx::Socket; # 'no_plan'; repeat_each(2); plan tests => 43 * 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] debian/modules/headers-more-nginx-module/t/input-cookie.t0000664000000000000000000000574612705233614020674 0ustar # 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] debian/modules/headers-more-nginx-module/t/input-ua.t0000664000000000000000000003112312705233614020014 0ustar # 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] debian/modules/headers-more-nginx-module/t/phase.t0000664000000000000000000000054412705233614017355 0ustar # 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 debian/modules/headers-more-nginx-module/t/unused.t0000664000000000000000000000474512705233614017567 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (blocks() * 4 + 3); #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) --- 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) --- 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 debian/modules/headers-more-nginx-module/t/eval.t0000664000000000000000000000116712705233614017206 0ustar # vi:filetype=perl 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 debian/modules/headers-more-nginx-module/t/input.t0000664000000000000000000005303612705233614017420 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; # 'no_plan'; repeat_each(2); plan tests => repeat_each() * 105; no_long_string(); #no_diff; run_tests(); __DATA__ === TEST 1: set request header at client side --- config location /foo { #more_set_input_headers 'X-Foo: howdy'; echo $http_x_foo; } --- request GET /foo --- more_headers X-Foo: blah --- response_headers ! X-Foo --- response_body blah === TEST 2: set request header at client side and rewrite it --- config location /foo { more_set_input_headers 'X-Foo: howdy'; echo $http_x_foo; } --- request GET /foo --- more_headers X-Foo: blah --- response_headers ! X-Foo --- response_body howdy === TEST 3: rewrite content length --- config location /bar { more_set_input_headers 'Content-Length: 2048'; echo_read_request_body; echo_request_body; } --- request eval "POST /bar\n" . "a" x 4096 --- response_body eval "a" x 2048 --- timeout: 15 === TEST 4: try to rewrite content length using the rewrite module Thisshould not take effect ;) --- config location /bar { set $http_content_length 2048; echo_read_request_body; echo_request_body; } --- request eval "POST /bar\n" . "a" x 4096 --- response_body eval "a" x 4096 === TEST 5: rewrite host and user-agent --- config location /bar { more_set_input_headers 'Host: foo' 'User-Agent: blah'; echo "Host: $host"; echo "User-Agent: $http_user_agent"; } --- request GET /bar --- response_body Host: foo User-Agent: blah === TEST 6: clear host and user-agent $host always has a default value and cannot be really cleared. --- config location /bar { more_clear_input_headers 'Host: foo' 'User-Agent: blah'; echo "Host: $host"; echo "Host (2): $http_host"; echo "User-Agent: $http_user_agent"; } --- request GET /bar --- response_body Host: localhost Host (2): User-Agent: === TEST 7: clear host and user-agent (the other way) --- config location /bar { more_set_input_headers 'Host:' 'User-Agent:' 'X-Foo:'; echo "Host: $host"; echo "User-Agent: $http_user_agent"; echo "X-Foo: $http_x_foo"; } --- request GET /bar --- more_headers X-Foo: bar --- response_body Host: localhost User-Agent: X-Foo: === TEST 8: clear content-length --- config location /bar { more_set_input_headers 'Content-Length: '; echo "Content-Length: $http_content_length"; } --- request POST /bar hello --- more_headers --- response_body Content-Length: === TEST 9: clear content-length (the other way) --- config location /bar { more_clear_input_headers 'Content-Length: '; echo "Content-Length: $http_content_length"; } --- request POST /bar hello --- more_headers --- response_body Content-Length: === TEST 10: rewrite type --- config location /bar { more_set_input_headers 'Content-Type: text/css'; echo "Content-Type: $content_type"; } --- request POST /bar hello --- more_headers Content-Type: text/plain --- response_body Content-Type: text/css === TEST 11: clear type --- config location /bar { more_set_input_headers 'Content-Type:'; echo "Content-Type: $content_type"; } --- request POST /bar hello --- more_headers Content-Type: text/plain --- response_body Content-Type: === TEST 12: clear type (the other way) --- config location /bar { more_clear_input_headers 'Content-Type:foo'; echo "Content-Type: $content_type"; } --- request POST /bar hello --- more_headers Content-Type: text/plain --- response_body Content-Type: === TEST 13: add type constraints --- config location /bar { more_set_input_headers -t 'text/plain' 'X-Blah:yay'; echo $http_x_blah; } --- request POST /bar hello --- more_headers Content-Type: text/plain --- response_body yay === TEST 14: add type constraints (not matched) --- config location /bar { more_set_input_headers -t 'text/plain' 'X-Blah:yay'; echo $http_x_blah; } --- request POST /bar hello --- more_headers Content-Type: text/css --- response_body eval: "\n" === TEST 15: add type constraints (OR'd) --- config location /bar { more_set_input_headers -t 'text/plain text/css' 'X-Blah:yay'; echo $http_x_blah; } --- request POST /bar hello --- more_headers Content-Type: text/css --- response_body yay === TEST 16: add type constraints (OR'd) --- config location /bar { more_set_input_headers -t 'text/plain text/css' 'X-Blah:yay'; echo $http_x_blah; } --- request POST /bar hello --- more_headers Content-Type: text/plain --- response_body yay === TEST 17: add type constraints (OR'd) (not matched) --- config location /bar { more_set_input_headers -t 'text/plain text/css' 'X-Blah:yay'; echo $http_x_blah; } --- request POST /bar hello --- more_headers Content-Type: text/html --- response_body eval: "\n" === TEST 18: mix input and output cmds --- config location /bar { more_set_input_headers 'X-Blah:yay'; more_set_headers 'X-Blah:hiya'; echo $http_x_blah; } --- request GET /bar --- response_headers X-Blah: hiya --- response yay === TEST 19: set request header at client side and replace --- config location /foo { more_set_input_headers -r 'X-Foo: howdy'; echo $http_x_foo; } --- request GET /foo --- more_headers X-Foo: blah --- response_headers ! X-Foo --- response_body howdy === TEST 20: do no set request header at client, so no replace with -r option --- config location /foo { more_set_input_headers -r 'X-Foo: howdy'; echo "empty_header:" $http_x_foo; } --- request GET /foo --- response_headers ! X-Foo --- response_body empty_header: === TEST 21: clear input headers --- config location /foo { set $val 'dog'; more_clear_input_headers 'User-Agent'; proxy_pass http://127.0.0.1:$server_port/proxy; } location /proxy { echo -n $echo_client_request_headers; } --- request GET /foo --- more_headers User-Agent: my-sock --- response_body eval "GET /proxy HTTP/1.0\r Host: 127.0.0.1:\$ServerPort\r Connection: close\r \r " --- skip_nginx: 3: < 0.7.46 === TEST 22: clear input headers --- config location /foo { more_clear_input_headers 'User-Agent'; proxy_pass http://127.0.0.1:$server_port/proxy; } location /proxy { echo -n $echo_client_request_headers; } --- request GET /foo --- response_body eval "GET /proxy HTTP/1.0\r Host: 127.0.0.1:\$ServerPort\r Connection: close\r \r " --- skip_nginx: 3: < 0.7.46 === TEST 23: clear input headers --- config location /foo { more_clear_input_headers 'X-Foo19'; more_clear_input_headers 'X-Foo20'; more_clear_input_headers 'X-Foo21'; proxy_pass http://127.0.0.1:$server_port/proxy; } location /proxy { echo -n $echo_client_request_headers; } --- request GET /foo --- more_headers eval my $s; for my $i (3..21) { $s .= "X-Foo$i: $i\n"; } $s; --- response_body eval "GET /proxy HTTP/1.0\r Host: 127.0.0.1:\$ServerPort\r Connection: close\r X-Foo3: 3\r X-Foo4: 4\r X-Foo5: 5\r X-Foo6: 6\r X-Foo7: 7\r X-Foo8: 8\r X-Foo9: 9\r X-Foo10: 10\r X-Foo11: 11\r X-Foo12: 12\r X-Foo13: 13\r X-Foo14: 14\r X-Foo15: 15\r X-Foo16: 16\r X-Foo17: 17\r X-Foo18: 18\r \r " --- skip_nginx: 3: < 0.7.46 === TEST 24: Accept-Encoding --- config location /bar { default_type 'text/plain'; more_set_input_headers 'Accept-Encoding: gzip'; gzip on; gzip_min_length 1; gzip_buffers 4 8k; gzip_types text/plain; } --- user_files ">>> bar " . ("hello" x 512) --- request GET /bar --- response_headers Content-Encoding: gzip --- response_body_like: . === TEST 25: rewrite + set request header --- config location /t { rewrite ^ /foo last; } location /foo { more_set_input_headers 'X-Foo: howdy'; proxy_pass http://127.0.0.1:$server_port/echo; } location /echo { echo "X-Foo: $http_x_foo"; } --- request GET /foo --- response_headers ! X-Foo --- response_body X-Foo: howdy === TEST 26: clear_header should clear all the instances of the user custom header --- config location = /t { more_clear_input_headers Foo; proxy_pass http://127.0.0.1:$server_port/echo; } location = /echo { echo "Foo: [$http_foo]"; echo "Test-Header: [$http_test_header]"; } --- request GET /t --- more_headers Foo: foo Foo: bah Test-Header: 1 --- response_body Foo: [] Test-Header: [1] === TEST 27: clear_header should clear all the instances of the builtin header --- config location = /t { more_clear_input_headers Content-Type; proxy_pass http://127.0.0.1:$server_port/echo; } location = /echo { echo "Content-Type: [$http_content_type]"; echo "Test-Header: [$http_test_header]"; #echo $echo_client_request_headers; } --- request GET /t --- more_headers Content-Type: foo Content-Type: bah Test-Header: 1 --- response_body Content-Type: [] Test-Header: [1] === TEST 28: Converting POST to GET - clearing headers (bug found by Matthieu Tourne, 411 error page) --- config location /t { more_clear_input_headers Content-Type; more_clear_input_headers Content-Length; #proxy_pass http://127.0.0.1:8888; proxy_pass http://127.0.0.1:$server_port/back; } location /back { echo $echo_client_request_headers; } --- request POST /t hello world --- more_headers Content-Type: application/ocsp-request Test-Header: 1 --- response_body_like eval qr/Connection: close\r Test-Header: 1\r \r $/ --- no_error_log [error] === TEST 29: clear_header() does not duplicate subsequent headers (old bug) --- config location = /t { more_clear_input_headers Foo; proxy_pass http://127.0.0.1:$server_port/echo; } location = /echo { echo $echo_client_request_headers; } --- request GET /t --- more_headers Bah: bah Foo: foo Test-Header: 1 Foo1: foo1 Foo2: foo2 Foo3: foo3 Foo4: foo4 Foo5: foo5 Foo6: foo6 Foo7: foo7 Foo8: foo8 Foo9: foo9 Foo10: foo10 Foo11: foo11 Foo12: foo12 Foo13: foo13 Foo14: foo14 Foo15: foo15 Foo16: foo16 Foo17: foo17 Foo18: foo18 Foo19: foo19 Foo20: foo20 Foo21: foo21 Foo22: foo22 --- response_body_like eval qr/Bah: bah\r Test-Header: 1\r Foo1: foo1\r Foo2: foo2\r Foo3: foo3\r Foo4: foo4\r Foo5: foo5\r Foo6: foo6\r Foo7: foo7\r Foo8: foo8\r Foo9: foo9\r Foo10: foo10\r Foo11: foo11\r Foo12: foo12\r Foo13: foo13\r Foo14: foo14\r Foo15: foo15\r Foo16: foo16\r Foo17: foo17\r Foo18: foo18\r Foo19: foo19\r Foo20: foo20\r Foo21: foo21\r Foo22: foo22\r / === TEST 30: clear input header (just more than 20 headers) --- config location = /t { more_clear_input_headers "R"; proxy_pass http://127.0.0.1:$server_port/back; proxy_set_header Host foo; #proxy_pass http://127.0.0.1:1234/back; } location = /back { echo -n $echo_client_request_headers; } --- request GET /t --- more_headers eval my $s = "User-Agent: curl\n"; for my $i ('a' .. 'r') { $s .= uc($i) . ": " . "$i\n" } $s --- response_body eval "GET /back HTTP/1.0\r Host: foo\r Connection: close\r User-Agent: curl\r A: a\r B: b\r C: c\r D: d\r E: e\r F: f\r G: g\r H: h\r I: i\r J: j\r K: k\r L: l\r M: m\r N: n\r O: o\r P: p\r Q: q\r \r " === TEST 31: clear input header (just more than 20 headers, and add more) --- config location = /t { more_clear_input_headers R; more_set_input_headers "foo-1: 1" "foo-2: 2" "foo-3: 3" "foo-4: 4" "foo-5: 5" "foo-6: 6" "foo-7: 7" "foo-8: 8" "foo-9: 9" "foo-10: 10" "foo-11: 11" "foo-12: 12" "foo-13: 13" "foo-14: 14" "foo-15: 15" "foo-16: 16" "foo-17: 17" "foo-18: 18" "foo-19: 19" "foo-20: 20" "foo-21: 21"; proxy_pass http://127.0.0.1:$server_port/back; proxy_set_header Host foo; #proxy_pass http://127.0.0.1:1234/back; } location = /back { echo -n $echo_client_request_headers; } --- request GET /t --- more_headers eval my $s = "User-Agent: curl\n"; for my $i ('a' .. 'r') { $s .= uc($i) . ": " . "$i\n" } $s --- response_body eval "GET /back HTTP/1.0\r Host: foo\r Connection: close\r User-Agent: curl\r A: a\r B: b\r C: c\r D: d\r E: e\r F: f\r G: g\r H: h\r I: i\r J: j\r K: k\r L: l\r M: m\r N: n\r O: o\r P: p\r Q: q\r foo-1: 1\r foo-2: 2\r foo-3: 3\r foo-4: 4\r foo-5: 5\r foo-6: 6\r foo-7: 7\r foo-8: 8\r foo-9: 9\r foo-10: 10\r foo-11: 11\r foo-12: 12\r foo-13: 13\r foo-14: 14\r foo-15: 15\r foo-16: 16\r foo-17: 17\r foo-18: 18\r foo-19: 19\r foo-20: 20\r foo-21: 21\r \r " === TEST 32: clear input header (just more than 21 headers) --- config location = /t { more_clear_input_headers R Q; proxy_pass http://127.0.0.1:$server_port/back; proxy_set_header Host foo; #proxy_pass http://127.0.0.1:1234/back; } location = /back { echo -n $echo_client_request_headers; } --- request GET /t --- more_headers eval my $s = "User-Agent: curl\nBah: bah\n"; for my $i ('a' .. 'r') { $s .= uc($i) . ": " . "$i\n" } $s --- response_body eval "GET /back HTTP/1.0\r Host: foo\r Connection: close\r User-Agent: curl\r Bah: bah\r A: a\r B: b\r C: c\r D: d\r E: e\r F: f\r G: g\r H: h\r I: i\r J: j\r K: k\r L: l\r M: m\r N: n\r O: o\r P: p\r \r " === TEST 33: clear input header (just more than 21 headers) --- config location = /t { more_clear_input_headers R Q; more_set_input_headers "foo-1: 1" "foo-2: 2" "foo-3: 3" "foo-4: 4" "foo-5: 5" "foo-6: 6" "foo-7: 7" "foo-8: 8" "foo-9: 9" "foo-10: 10" "foo-11: 11" "foo-12: 12" "foo-13: 13" "foo-14: 14" "foo-15: 15" "foo-16: 16" "foo-17: 17" "foo-18: 18" "foo-19: 19" "foo-20: 20" "foo-21: 21"; proxy_pass http://127.0.0.1:$server_port/back; proxy_set_header Host foo; #proxy_pass http://127.0.0.1:1234/back; } location = /back { echo -n $echo_client_request_headers; } --- request GET /t --- more_headers eval my $s = "User-Agent: curl\nBah: bah\n"; for my $i ('a' .. 'r') { $s .= uc($i) . ": " . "$i\n" } $s --- response_body eval "GET /back HTTP/1.0\r Host: foo\r Connection: close\r User-Agent: curl\r Bah: bah\r A: a\r B: b\r C: c\r D: d\r E: e\r F: f\r G: g\r H: h\r I: i\r J: j\r K: k\r L: l\r M: m\r N: n\r O: o\r P: p\r foo-1: 1\r foo-2: 2\r foo-3: 3\r foo-4: 4\r foo-5: 5\r foo-6: 6\r foo-7: 7\r foo-8: 8\r foo-9: 9\r foo-10: 10\r foo-11: 11\r foo-12: 12\r foo-13: 13\r foo-14: 14\r foo-15: 15\r foo-16: 16\r foo-17: 17\r foo-18: 18\r foo-19: 19\r foo-20: 20\r foo-21: 21\r \r " === TEST 34: clear X-Real-IP --- config location /t { more_clear_input_headers X-Real-IP; echo "X-Real-IP: $http_x_real_ip"; } --- request GET /t --- more_headers X-Real-IP: 8.8.8.8 --- stap F(ngx_http_headers_more_exec_input_cmd) { if (@defined($r->headers_in->x_real_ip) && $r->headers_in->x_real_ip) { printf("rewrite: x-real-ip: %s\n", user_string_n($r->headers_in->x_real_ip->value->data, $r->headers_in->x_real_ip->value->len)) } else { println("rewrite: no x-real-ip") } } F(ngx_http_core_content_phase) { if (@defined($r->headers_in->x_real_ip) && $r->headers_in->x_real_ip) { printf("content: x-real-ip: %s\n", user_string_n($r->headers_in->x_real_ip->value->data, $r->headers_in->x_real_ip->value->len)) } else { println("content: no x-real-ip") } } --- stap_out rewrite: x-real-ip: 8.8.8.8 content: no x-real-ip --- response_body X-Real-IP: --- no_error_log [error] === TEST 35: set custom X-Real-IP --- config location /t { more_set_input_headers "X-Real-IP: 8.8.4.4"; echo "X-Real-IP: $http_x_real_ip"; } --- request GET /t --- stap F(ngx_http_headers_more_exec_input_cmd) { if (@defined($r->headers_in->x_real_ip) && $r->headers_in->x_real_ip) { printf("rewrite: x-real-ip: %s\n", user_string_n($r->headers_in->x_real_ip->value->data, $r->headers_in->x_real_ip->value->len)) } else { println("rewrite: no x-real-ip") } } F(ngx_http_core_content_phase) { if (@defined($r->headers_in->x_real_ip) && $r->headers_in->x_real_ip) { printf("content: x-real-ip: %s\n", user_string_n($r->headers_in->x_real_ip->value->data, $r->headers_in->x_real_ip->value->len)) } else { println("content: no x-real-ip") } } --- stap_out rewrite: no x-real-ip content: x-real-ip: 8.8.4.4 --- response_body X-Real-IP: 8.8.4.4 --- no_error_log [error] === TEST 36: clear Via --- config location /t { more_clear_input_headers Via; echo "Via: $http_via"; } --- request GET /t --- more_headers Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) --- stap F(ngx_http_headers_more_exec_input_cmd) { if (@defined($r->headers_in->via) && $r->headers_in->via) { printf("rewrite: via: %s\n", user_string_n($r->headers_in->via->value->data, $r->headers_in->via->value->len)) } else { println("rewrite: no via") } } F(ngx_http_core_content_phase) { if (@defined($r->headers_in->via) && $r->headers_in->via) { printf("content: via: %s\n", user_string_n($r->headers_in->via->value->data, $r->headers_in->via->value->len)) } else { println("content: no via") } } --- stap_out rewrite: via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) content: no via --- response_body Via: --- no_error_log [error] === TEST 37: set custom Via --- config location /t { more_set_input_headers "Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)"; echo "Via: $http_via"; } --- request GET /t --- stap F(ngx_http_headers_more_exec_input_cmd) { if (@defined($r->headers_in->via) && $r->headers_in->via) { printf("rewrite: via: %s\n", user_string_n($r->headers_in->via->value->data, $r->headers_in->via->value->len)) } else { println("rewrite: no via") } } F(ngx_http_core_content_phase) { if (@defined($r->headers_in->via) && $r->headers_in->via) { printf("content: via: %s\n", user_string_n($r->headers_in->via->value->data, $r->headers_in->via->value->len)) } else { println("content: no via") } } --- stap_out rewrite: no via content: via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) --- response_body Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) --- no_error_log [error] === TEST 38: HTTP 0.9 (set) --- config location /foo { more_set_input_headers 'X-Foo: howdy'; echo "x-foo: $http_x_foo"; } --- raw_request eval "GET /foo\r\n" --- response_headers ! X-Foo --- response_body x-foo: --- http09 === TEST 39: HTTP 0.9 (clear) --- config location /foo { more_clear_input_headers 'X-Foo'; echo "x-foo: $http_x_foo"; } --- raw_request eval "GET /foo\r\n" --- response_headers ! X-Foo --- response_body x-foo: --- http09 === TEST 40: Host header with port and $host --- config location /bar { more_set_input_headers 'Host: agentzh.org:1984'; echo "host var: $host"; echo "http_host var: $http_host"; } --- request GET /bar --- response_body host var: agentzh.org http_host var: agentzh.org:1984 === TEST 41: Host header with upper case letters and $host --- config location /bar { more_set_input_headers 'Host: agentZH.org:1984'; echo "host var: $host"; echo "http_host var: $http_host"; } --- request GET /bar --- response_body host var: agentzh.org http_host var: agentZH.org:1984 === TEST 42: clear all and re-insert --- config location = /t { more_clear_input_headers Host Connection Cache-Control Accept User-Agent Accept-Encoding Accept-Language Cookie; more_set_input_headers "Host: a" "Connection: b" "Cache-Control: c" "Accept: d" "User-Agent: e" "Accept-Encoding: f" "Accept-Language: g" "Cookie: h"; more_clear_input_headers Host Connection Cache-Control Accept User-Agent Accept-Encoding Accept-Language Cookie; more_set_input_headers "Host: a" "Connection: b" "Cache-Control: c" "Accept: d" "User-Agent: e" "Accept-Encoding: f" "Accept-Language: g" "Cookie: h"; echo ok; } --- raw_request eval "GET /t HTTP/1.1\r Host: localhost\r Connection: close\r Cache-Control: max-age=0\r Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36\r Accept-Encoding: gzip,deflate,sdch\r Accept-Language: en-US,en;q=0.8\r Cookie: test=cookie;\r \r " --- response_body ok --- no_error_log [error] === TEST 43: more_set_input_header does not override request headers with multiple values --- config #lua_code_cache off; location = /t { more_set_input_headers "AAA: 111"; content_by_lua ' local headers = ngx.req.get_headers() ngx.say(headers["AAA"]) '; } --- request GET /t --- more_headers AAA: 123 AAA: 456 AAA: 678 --- response_body 111 --- no_error_log [error] debian/modules/headers-more-nginx-module/t/sanity.t0000664000000000000000000002433212705233614017565 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * 113; #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 debian/modules/headers-more-nginx-module/t/subrequest.t0000664000000000000000000000233312705233614020455 0ustar # 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 debian/modules/headers-more-nginx-module/README.markdown0000664000000000000000000004051412705233614020327 0ustar 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 ================= * [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.25](http://github.com/agentzh/headers-more-nginx-module/tags) released on 10 January 2014. 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'; ``` 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>]... <new-header>...* **default:** *no* **context:** *http, server, location, location if* **phase:** *output-header-filter* Adds or replaces 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 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"; ``` 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. Wildcard `*` can also be used to specify a header name 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` 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 -s 404 -t 'text/plain' Foo Baz; ``` is exactly equivalent to ```nginx more_set_input_headers -s 404 -t 'text/plain' "Foo: " "Baz: "; ``` or ```nginx more_set_input_headers -s 404 -t 'text/plain' Foo Baz ``` See [more_set_input_headers](#more_set_input_headers) for more details. [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.5.8 (see [nginx compatibility](#compatibility)), and then build the source with this module: ```bash wget 'http://nginx.org/download/nginx-1.5.8.tar.gz' tar -xzvf nginx-1.5.8.tar.gz cd nginx-1.5.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](http://github.com/agentzh/headers-more-nginx-module/tags). Also, this module is included and enabled by default in the [ngx_openresty bundle](http://openresty.org). [Back to TOC](#table-of-contents) Compatibility ============= The following versions of Nginx should work with this module: * **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](http://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 [agentzh/headers-more-nginx-module](http://github.com/agentzh/headers-more-nginx-module). [Back to TOC](#table-of-contents) Changes ======= The changes of every release of this module can be obtained from the ngx_openresty bundle's change logs: [Back to TOC](#table-of-contents) Test Suite ========== This module comes with a Perl-driven test suite. The [test cases](http://github.com/agentzh/headers-more-nginx-module/tree/master/t/) are [declarative](http://github.com/agentzh/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](http://github.com/agentzh/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>*, CloudFlare Inc. * Bernd Dorn ( ) 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-2014, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. Copyright (c) 2010-2013, Bernd Dorn. 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. [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](http://github.com/agentzh/echo-nginx-module) for Nginx module's automated testing. * The standard [headers](http://nginx.org/en/docs/http/ngx_http_headers_module.html) module. debian/modules/headers-more-nginx-module/doc/0000775000000000000000000000000012705233614016367 5ustar debian/modules/headers-more-nginx-module/doc/HttpHeadersMoreModule.wiki0000664000000000000000000003607712705233614023475 0ustar = Name = '''ngx_headers_more''' - Set and clear input and output headers...more than "add"! ''This module is not distributed with the Nginx source.'' See [[#Installation|the installation instructions]]. = Version = This document describes headers-more-nginx-module [http://github.com/agentzh/headers-more-nginx-module/tags v0.25] released on 10 January 2014. = Synopsis = # 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 [[HttpHeadersModule|headers]] 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, more_set_headers -s 404 -t 'text/html' 'X-Foo: Bar'; Input headers can be modified as well. For example 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 [[HttpHeadersModule|headers]] module, this module's directives will by default apply to all the status codes, including 4xx and 5xx. = Directives = == more_set_headers == '''syntax:''' ''more_set_headers [-t ]... [-s ]... ...'' '''default:''' ''no'' '''context:''' ''http, server, location, location if'' '''phase:''' ''output-header-filter'' Adds or replaces 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 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: more_set_headers "Server: my_server"; A single directive can set/add multiple output headers. For example 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 more_set_headers -s 404 -s '500 503' 'Foo: bar'; is equivalent to more_set_headers -s '404 500 503' 'Foo: bar'; The new header should be the one of the forms: # Name: Value # Name: # Name The last two effectively clear the value of the header Name. Nginx variables are allowed in header values. For example: 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 ? # 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. == more_clear_headers == '''syntax:''' ''more_clear_headers [-t ]... [-s ]... ...'' '''default:''' ''no'' '''context:''' ''http, server, location, location if'' '''phase:''' ''output-header-filter'' Clears the specified output headers. In fact, more_clear_headers -s 404 -t 'text/plain' Foo Baz; is exactly equivalent to more_set_headers -s 404 -t 'text/plain' "Foo: " "Baz: "; or more_set_headers -s 404 -t 'text/plain' Foo Baz See [[#more_set_headers|more_set_headers]] for more details. Wildcard * can also be used to specify a header name pattern. For example, the following directive effectively clears ''any'' output headers starting by "X-Hidden-": more_clear_headers 'X-Hidden-*'; The * wildcard support was first introduced in [[#v0.09|v0.09]]. == more_set_input_headers == '''syntax:''' ''more_set_input_headers [-r] [-t ]... ...'' '''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 so that it runs ''after'' the standard [[HttpRewriteModule|rewrite module]] 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. == more_clear_input_headers == '''syntax:''' ''more_clear_input_headers [-t ]... ...'' '''default:''' ''no'' '''context:''' ''http, server, location, location if'' '''phase:''' ''rewrite tail'' Clears the specified input headers. In fact, more_clear_input_headers -s 404 -t 'text/plain' Foo Baz; is exactly equivalent to more_set_input_headers -s 404 -t 'text/plain' "Foo: " "Baz: "; or more_set_input_headers -s 404 -t 'text/plain' Foo Baz See [[#more_set_input_headers|more_set_input_headers]] for more details. = Limitations = * Unlike the standard [[HttpHeadersModule|headers]] 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 [[HttpHeadersModule|headers]] 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. = Installation = Grab the nginx source code from [http://nginx.org/ nginx.org], for example, the version 1.5.8 (see [[#Compatibility|nginx compatibility]]), and then build the source with this module: wget 'http://nginx.org/download/nginx-1.5.8.tar.gz' tar -xzvf nginx-1.5.8.tar.gz cd nginx-1.5.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 [http://github.com/agentzh/headers-more-nginx-module/tags headers-more-nginx-module file list]. Also, this module is included and enabled by default in the [http://openresty.org ngx_openresty bundle]. = Compatibility = The following versions of Nginx should work with this module: * '''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 [[#Report Bugs|reporting a bug]]. = Community = == English Mailing List == The [https://groups.google.com/group/openresty-en openresty-en] mailing list is for English speakers. == Chinese Mailing List == The [https://groups.google.com/group/openresty openresty] mailing list is for Chinese speakers. = Bugs and Patches = Please submit bug reports, wishlists, or patches by # creating a ticket on the [http://github.com/chaoslawful/lua-nginx-module/issues GitHub Issue Tracker], # or posting to the [[#Community|OpenResty community]]. = Source Repository = Available on github at [http://github.com/agentzh/headers-more-nginx-module agentzh/headers-more-nginx-module]. = Changes = The changes of every release of this module can be obtained from the ngx_openresty bundle's change logs: http://openresty.org/#Changes = Test Suite = This module comes with a Perl-driven test suite. The [http://github.com/agentzh/headers-more-nginx-module/tree/master/t/ test cases] are [http://github.com/agentzh/headers-more-nginx-module/blob/master/t/sanity.t declarative] too. Thanks to the [http://search.cpan.org/perldoc?Test::Nginx Test::Nginx] module in the Perl world. To run it on your side: $ 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: $ 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 [[HttpProxyModule|proxy]], [[HttpRewriteModule|rewrite]], and [[HttpEchoModule|echo]] to be enabled as well when building Nginx. = TODO = * Support variables in new headers' keys. = 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. = Authors = * Yichun "agentzh" Zhang (章亦春) '''', CloudFlare 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. = Copyright & License = The code base is borrowed directly from the standard [[HttpHeadersModule|headers]] module in Nginx 0.8.24. This part of code is copyrighted by Igor Sysoev. Copyright (c) 2009-2014, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. Copyright (c) 2010-2013, Bernd Dorn. 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. = See Also = * The original thread on the Nginx mailing list that inspires this module's development: [http://forum.nginx.org/read.php?2,11206,11738 "A question about add_header replication"]. * The orginal announcement thread on the Nginx mailing list: [http://forum.nginx.org/read.php?2,23460 "The "headers_more" module: Set and clear output headers...more than 'add'!"]. * The original [http://agentzh.blogspot.com/2009/11/headers-more-module-scripting-input-and.html blog post] about this module's initial development. * The [[HttpEchoModule|echo module]] for Nginx module's automated testing. * The standard [[HttpHeadersModule|headers]] module. debian/modules/headers-more-nginx-module/config0000664000000000000000000000131312705233614017010 0ustar ngx_addon_name=ngx_http_headers_more_filter_module HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_headers_more_filter_module" NGX_ADDON_SRCS="$NGX_ADDON_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" NGX_ADDON_DEPS="$NGX_ADDON_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" debian/modules/headers-more-nginx-module/src/0000775000000000000000000000000012705233614016411 5ustar debian/modules/headers-more-nginx-module/src/ddebug.h0000664000000000000000000000512512705233614020017 0ustar #ifndef DDEBUG_H #define DDEBUG_H #include #include #include #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 #include #include static 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 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 static void dd(const char * fmt, ...) { } static 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 */ debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_util.c0000664000000000000000000002266612705233614024176 0ustar /* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_headers_more_util.h" #include 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 to 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)) { continue; } t = ngx_array_push(types); if (t == NULL) { return NGX_ERROR; } t->len = 1; t->data = p; continue; } if (isspace(*p)) { t = NULL; continue; } t->len++; } return NGX_OK; } ngx_int_t ngx_http_headers_more_rm_header(ngx_list_t *l, ngx_table_elt_t *h) { ngx_uint_t i; ngx_list_part_t *part; ngx_table_elt_t *data; part = &l->part; data = part->elts; for (i = 0; /* void */; i++) { dd("i: %d, part: %p", (int) i, part); if (i >= part->nelts) { if (part->next == NULL) { break; } dd("switching to the next part %p", part->next); part = part->next; #if 1 data = part->elts; #endif h = part->elts; i = 0; } if (&data[i] == h) { dd("found header at %d", (int) i); return ngx_http_headers_more_rm_header_helper(l, part, i); } } return NGX_ERROR; } 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; } debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_util.h0000664000000000000000000000243612705233614024174 0ustar /* * 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); ngx_int_t ngx_http_headers_more_rm_header(ngx_list_t *l, ngx_table_elt_t *h); #endif /* NGX_HTTP_HEADERS_MORE_UTIL_H */ debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.h0000664000000000000000000000113312705233614025311 0ustar /* * 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 */ debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_in.c0000664000000000000000000005110512705233614025310 0ustar /* * 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 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_cookie_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[] = { #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("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 }, { 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-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 }, { 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 }, { ngx_string("Content-Length"), offsetof(ngx_http_headers_in_t, content_length), ngx_http_set_content_length_header }, { ngx_string("Cookie"), 0, ngx_http_set_cookie_header }, #if (NGX_HTTP_REALIP) { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip), ngx_http_set_builtin_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 (h[i].key.len == hv->key.len && ngx_strncasecmp(h[i].key.data, hv->key.data, h[i].key.len) == 0) { 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; } 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; 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; } else 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; } 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_cookie_header(ngx_http_request_t *r, ngx_http_headers_more_header_val_t *hv, ngx_str_t *value) { ngx_table_elt_t **cookie, *h; if (r->headers_in.cookies.nelts > 0) { ngx_array_destroy(&r->headers_in.cookies); if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK) { return NGX_ERROR; } dd("clear headers in cookies: %d", (int) r->headers_in.cookies.nelts); } #if 1 if (r->headers_in.cookies.nalloc == 0) { if (ngx_array_init(&r->headers_in.cookies, 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); cookie = ngx_array_push(&r->headers_in.cookies); if (cookie == NULL) { return NGX_ERROR; } *cookie = h; return NGX_OK; } 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; } debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_filter_module.c0000664000000000000000000002271612705233614026047 0ustar /* * 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 /* 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; } debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_out.h0000664000000000000000000000111412705233614025511 0ustar /* * 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 */ debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_filter_module.h0000664000000000000000000000417612705233614026054 0ustar /* * Copyright (c) Yichun Zhang (agentzh) */ #ifndef NGX_HTTP_HEADERS_MORE_FILTER_MODULE_H #define NGX_HTTP_HEADERS_MORE_FILTER_MODULE_H #include #include #include 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; ngx_flag_t replace; ngx_flag_t wildcard; }; 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 */ debian/modules/headers-more-nginx-module/src/ngx_http_headers_more_headers_out.c0000664000000000000000000004364012705233614025516 0ustar /* * 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 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 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 */ 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; 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) { 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; } 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; 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_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; } } 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; } 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; } debian/modules/headers-more-nginx-module/valgrind.suppress0000664000000000000000000000663312705233614021246 0ustar { Memcheck:Cond fun:lj_str_new } { Memcheck:Cond fun:lj_str_new fun:lua_pushlstring } { Memcheck:Addr4 fun:lj_str_new fun:lua_pushlstring } { Memcheck:Leak fun:malloc fun:ngx_alloc obj:* } { Memcheck:Leak fun:malloc fun:ngx_alloc } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:ngx_palloc_large fun:ngx_palloc } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:ngx_calloc fun:ngx_event_process_init } { Memcheck:Addr4 fun:lj_str_new fun:lua_pushlstring fun:ngx_http_lua_get_output_header } { Memcheck:Addr4 fun:lj_str_new fun:lua_getfield fun:ngx_http_lua_cache_load_code } { Memcheck:Addr4 fun:lj_str_new fun:lua_setfield fun:ngx_http_lua_cache_store_code } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:ngx_event_process_init } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:(below main) } { Memcheck:Param epoll_ctl(event) fun:epoll_ctl } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:ngx_create_pool } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:ngx_malloc fun:ngx_palloc_large } { Memcheck:Cond fun:memcpy fun:ngx_vslprintf fun:ngx_log_error_core fun:ngx_http_charset_header_filter } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:ngx_malloc fun:ngx_pnalloc } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:ngx_malloc fun:ngx_palloc } { 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 } { Memcheck:Leak fun:memalign fun:posix_memalign fun:ngx_memalign fun:ngx_palloc_block fun:ngx_palloc } { Memcheck:Addr8 fun:getenv fun:gcov_exit fun:exit fun:ngx_master_process_exit } debian/modules/nginx-development-kit/0000775000000000000000000000000012705233614015073 5ustar debian/modules/nginx-development-kit/objs/0000775000000000000000000000000012705233614016030 5ustar debian/modules/nginx-development-kit/objs/ndk_conf_cmd_extra.h0000664000000000000000000056673712705233614022040 0ustar /* * 2010 (C) Marcus Clyne * * DO NOT EDIT THIS FILE MANUALLY * ------------------------------ * This file has been generated automatically from scripts in the $base/auto dir and * data in the $base/auto/data dir. If you wish to edit the output of this file, then * you should edit these files instead. * */ /* conf command macros */ #define NDK_HTTP_MAIN_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_BITMASK(name,p,post)\ NDK_HTTP_SRV_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_BITMASK(name,p,post)\ NDK_HTTP_SIF_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_BITMASK(name,p,post)\ NDK_HTTP_LOC_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_BITMASK(name,p,post)\ NDK_HTTP_LIF_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_BITMASK(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_BITMASK(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_BITMASK(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_BITMASK(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_BITMASK(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_BITMASK(name,p,post)\ NDK_HTTP_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_BITMASK(name,p,post)\ NDK_HTTP_UPS_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_BITMASK(name,p,post)\ NDK_HTTP_ANY_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_BITMASK(name,p,post)\ NDK_ANY_CONF_1MORE\ (name,\ ndk_conf_set_bitmask_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_BUFS(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_BUFS(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_BUFS(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_BUFS(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_BUFS(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_BUFS(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_BUFS(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_BUFS(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_BUFS(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_BUFS(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_BUFS(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_BUFS(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_BUFS(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_bufs_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_COMPLEX_KEYVAL(name,p,post)\ NDK_ANY_CONF_TAKE2\ (name,\ ndk_conf_set_http_complex_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_COMPLEX_PATH(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_COMPLEX_PATH(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_SRV_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_SIF_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_LOC_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_LIF_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_UPS_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_HTTP_ANY_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_COMPLEX_VALUE_ARRAY(name,p,post)\ NDK_ANY_CONF_1MORE\ (name,\ ndk_conf_set_http_complex_value_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_COMPLEX_VALUE(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_COMPLEX_VALUE(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_http_complex_value_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_ENCODING(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_ENCODING(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_ENCODING(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_ENCODING(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_ENCODING(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_ENCODING(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_ENCODING(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_ENCODING(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_ENCODING(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_ENCODING(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_ENCODING(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_ENCODING(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_ENCODING(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_encoding_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_ENUM(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_ENUM(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_ENUM(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_ENUM(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_ENUM(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_ENUM(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_ENUM(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_ENUM(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_ENUM(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_ENUM(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_ENUM(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_ENUM(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_ENUM(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_enum_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_FALSE(name,p,post)\ NDK_HTTP_SRV_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_FALSE(name,p,post)\ NDK_HTTP_SIF_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_FALSE(name,p,post)\ NDK_HTTP_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_FALSE(name,p,post)\ NDK_HTTP_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_FALSE(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_FALSE(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_FALSE(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_FALSE(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_FALSE(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_FALSE(name,p,post)\ NDK_HTTP_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_FALSE(name,p,post)\ NDK_HTTP_UPS_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_FALSE(name,p,post)\ NDK_HTTP_ANY_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_FALSE(name,p,post)\ NDK_ANY_CONF_NOARGS\ (name,\ ndk_conf_set_false_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_FULL_PATH(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_FULL_PATH(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_full_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_KEYVAL1(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_KEYVAL1(name,p,post)\ NDK_ANY_CONF_TAKE2\ (name,\ ndk_conf_set_keyval1_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_KEYVAL(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_KEYVAL(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_KEYVAL(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_KEYVAL(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_KEYVAL(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_KEYVAL(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_KEYVAL(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_KEYVAL(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_KEYVAL(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_KEYVAL(name,p,post)\ NDK_HTTP_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_KEYVAL(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_KEYVAL(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_KEYVAL(name,p,post)\ NDK_ANY_CONF_TAKE2\ (name,\ ndk_conf_set_keyval_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_MSEC(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_MSEC(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_MSEC(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_MSEC(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_MSEC(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_MSEC(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_MSEC(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_MSEC(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_MSEC(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_MSEC(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_MSEC(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_MSEC(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_MSEC(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_msec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_NULL(name,p,post)\ NDK_HTTP_SRV_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_NULL(name,p,post)\ NDK_HTTP_SIF_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_NULL(name,p,post)\ NDK_HTTP_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_NULL(name,p,post)\ NDK_HTTP_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_NULL(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_NULL(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_NULL(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_NULL(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_NULL(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_NULL(name,p,post)\ NDK_HTTP_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_NULL(name,p,post)\ NDK_HTTP_UPS_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_NULL(name,p,post)\ NDK_HTTP_ANY_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_NULL(name,p,post)\ NDK_ANY_CONF_NOARGS\ (name,\ ndk_conf_set_null_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_NUM64(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_NUM64(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_NUM64(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_NUM64(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_NUM64(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_NUM64(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_NUM64(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_NUM64(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_NUM64(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_NUM64(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_NUM64(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_NUM64(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_NUM64(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_num64_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_NUM_FLAG(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_NUM_FLAG(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_num_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_NUM(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_NUM(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_NUM(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_NUM(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_NUM(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_NUM(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_NUM(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_NUM(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_NUM(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_NUM(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_NUM(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_NUM(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_NUM(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_num_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_OFF(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_OFF(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_OFF(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_OFF(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_OFF(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_OFF(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_OFF(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_OFF(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_OFF(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_OFF(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_OFF(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_OFF(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_OFF(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_off_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_ONOFF(name,p,post)\ NDK_HTTP_SRV_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_ONOFF(name,p,post)\ NDK_HTTP_SIF_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_ONOFF(name,p,post)\ NDK_HTTP_LOC_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_ONOFF(name,p,post)\ NDK_HTTP_LIF_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_ONOFF(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_ONOFF(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_ONOFF(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_ONOFF(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_ONOFF(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_ONOFF(name,p,post)\ NDK_HTTP_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_ONOFF(name,p,post)\ NDK_HTTP_UPS_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_ONOFF(name,p,post)\ NDK_HTTP_ANY_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_ONOFF(name,p,post)\ NDK_ANY_CONF_FLAG\ (name,\ ndk_conf_set_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_PATH(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_PATH(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_PATH(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_PATH(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_PATH(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_PATH(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_PATH(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_PATH(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_PATH(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_PATH(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_PATH(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_PATH(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_PATH(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_split_path_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_PTR(name,p,post)\ NDK_HTTP_SRV_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_PTR(name,p,post)\ NDK_HTTP_SIF_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_PTR(name,p,post)\ NDK_HTTP_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_PTR(name,p,post)\ NDK_HTTP_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_PTR(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_PTR(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_PTR(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_PTR(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_PTR(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_PTR(name,p,post)\ NDK_HTTP_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_PTR(name,p,post)\ NDK_HTTP_UPS_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_PTR(name,p,post)\ NDK_HTTP_ANY_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_PTR(name,p,post)\ NDK_ANY_CONF_NOARGS\ (name,\ ndk_conf_set_ptr_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_SRV_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_SIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_UPS_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_REGEX_ARRAY(name,p,post)\ NDK_HTTP_ANY_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_REGEX_ARRAY(name,p,post)\ NDK_ANY_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_SRV_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_SIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_UPS_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_HTTP_ANY_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_REGEX_ARRAY_CL(name,p,post)\ NDK_ANY_CONF_1MORE\ (name,\ ndk_conf_set_regex_array_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_REGEX_CL(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_REGEX_CL(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_regex_caseless_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_REXEX(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_REXEX(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_REXEX(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_REXEX(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_REXEX(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_REXEX(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_REXEX(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_REXEX(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_REXEX(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_REXEX(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_REXEX(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_REXEX(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_REXEX(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_regex_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_SEC_FLAG(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_SEC_FLAG(name,p,post)\ NDK_ANY_CONF_TAKE2\ (name,\ ndk_conf_set_sec_flag_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_SEC(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_SEC(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_SEC(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_SEC(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_SEC(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_SEC(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_SEC(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_SEC(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_SEC(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_SEC(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_SEC(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_SEC(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_SEC(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_sec_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_SIZE(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_SIZE(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_SIZE(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_SIZE(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_SIZE(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_SIZE(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_SIZE(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_SIZE(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_SIZE(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_SIZE(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_SIZE(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_SIZE(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_SIZE(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_size_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_SRV_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_SIF_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_LOC_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_LIF_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_UPS_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_STR_ARRAY(name,p,post)\ NDK_HTTP_ANY_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_STR_ARRAY(name,p,post)\ NDK_ANY_CONF_1MORE\ (name,\ ndk_conf_set_str_array_multi_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_STR_ARRAY1(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_STR_ARRAY1(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_str_array_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_STR(name,p,post)\ NDK_HTTP_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_STR(name,p,post)\ NDK_HTTP_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_STR(name,p,post)\ NDK_HTTP_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_STR(name,p,post)\ NDK_HTTP_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_STR(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_STR(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_STR(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_STR(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_STR(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_STR(name,p,post)\ NDK_HTTP_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_STR(name,p,post)\ NDK_HTTP_UPS_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_STR(name,p,post)\ NDK_HTTP_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_STR(name,p,post)\ NDK_ANY_CONF_TAKE1\ (name,\ ndk_conf_set_str_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_MAIN_CONF_OFFSET,\ offsetof (ndk_module_main_conf_t, p),\ post) #define NDK_HTTP_SRV_CONF_TRUE(name,p,post)\ NDK_HTTP_SRV_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_SIF_CONF_TRUE(name,p,post)\ NDK_HTTP_SIF_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_LOC_CONF_TRUE(name,p,post)\ NDK_HTTP_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_LIF_CONF_TRUE(name,p,post)\ NDK_HTTP_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_SRV_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_SIF_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_SRV_CONF_OFFSET,\ offsetof (ndk_module_srv_conf_t, p),\ post) #define NDK_HTTP_MAIN_LOC_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_LIF_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LOC_CONF_TRUE(name,p,post)\ NDK_HTTP_SRV_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SRV_LIF_CONF_TRUE(name,p,post)\ NDK_HTTP_SRV_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LOC_CONF_TRUE(name,p,post)\ NDK_HTTP_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_SIF_LIF_CONF_TRUE(name,p,post)\ NDK_HTTP_SIF_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LOC_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_SRV_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_LIF_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_SRV_LIF_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SIF_LOC_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TRUE(name,p,post)\ NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_CONF_TRUE(name,p,post)\ NDK_HTTP_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_UPS_CONF_TRUE(name,p,post)\ NDK_HTTP_UPS_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_HTTP_ANY_CONF_TRUE(name,p,post)\ NDK_HTTP_ANY_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) #define NDK_ANY_CONF_TRUE(name,p,post)\ NDK_ANY_CONF_NOARGS\ (name,\ ndk_conf_set_true_slot,\ NGX_HTTP_LOC_CONF_OFFSET,\ offsetof (ndk_module_loc_conf_t, p),\ post) debian/modules/nginx-development-kit/objs/ndk_includes.h0000664000000000000000000000212212705233614020640 0ustar /* optional includes */ #if (NDK_BUF) #include #endif #if (NDK_COMPLEX_PATH) #include #endif #if (NDK_COMPLEX_VALUE) #include #endif #if (NDK_CONF_FILE) #include #endif #if (NDK_ENCODING) #include #endif #if (NDK_HASH) #include #endif #if (NDK_HTTP) #include #endif #if (NDK_PATH) #include #endif #if (NDK_PROCESS) #include #endif #if (NDK_REGEX) #include #endif #if (NDK_REWRITE) #include #endif #if (NDK_SET_VAR) #include #endif #if (NDK_STRING) #include #endif #if (NDK_UPSTREAM_LIST) #include #endif #if (NDK_URI) #include #endif /* non-optional includes */ #include #include #include #include /* auto-generated headers */ #include #include #include #include #include debian/modules/nginx-development-kit/objs/ndk_config.c0000664000000000000000000000246312705233614020302 0ustar /* * 2010 (C) Marcus Clyne * * DO NOT EDIT THIS FILE MANUALLY * ------------------------------ * This file has been generated automatically from scripts in the $base/auto dir and * data in the $base/auto/data dir. If you wish to edit the output of this file, then * you should edit these files instead. * */ /* optional includes */ #if (NDK_BUF) #include #endif #if (NDK_COMPLEX_PATH) #include #endif #if (NDK_COMPLEX_VALUE) #include #endif #if (NDK_CONF_FILE) #include #endif #if (NDK_ENCODING) #include #endif #if (NDK_HASH) #include #endif #if (NDK_HTTP) #include #endif #if (NDK_PATH) #include #endif #if (NDK_PROCESS) #include #endif #if (NDK_REGEX) #include #endif #if (NDK_REWRITE) #include #endif #if (NDK_SET_VAR) #include #endif #if (NDK_STRING) #include #endif #if (NDK_UPSTREAM_LIST) #include #endif #if (NDK_URI) #include #endif /* module commands */ static ngx_command_t ndk_http_commands[] = { #if (NDK_UPSTREAM_LIST) #define NDK_UPSTREAM_LIST_CMDS 1 #include #undef NDK_UPSTREAM_LIST_CMDS #endif ngx_null_command }; debian/modules/nginx-development-kit/objs/ndk_conf_cmd_basic.h0000664000000000000000000033514412705233614021760 0ustar /* * 2010 (C) Marcus Clyne * * DO NOT EDIT THIS FILE MANUALLY * ------------------------------ * This file has been generated automatically from scripts in the $base/auto dir and * data in the $base/auto/data dir. If you wish to edit the output of this file, then * you should edit these files instead. * */ /* conf cmd core values/bitmasks */ #define NDK_1MORE NGX_1MORE #define NDK_2MORE NGX_2MORE #define NDK_ANY NGX_ANY #define NDK_ARGS_NUMBER NGX_ARGS_NUMBER #define NDK_BLOCK NGX_BLOCK #define NDK_FLAG NGX_FLAG #define NDK_MULTI NGX_MULTI #define NDK_TAKE1 NGX_TAKE1 #define NDK_TAKE12 NGX_TAKE12 #define NDK_TAKE123 NGX_TAKE123 #define NDK_TAKE1234 NGX_TAKE1234 #define NDK_TAKE13 NGX_TAKE13 #define NDK_TAKE2 NGX_TAKE2 #define NDK_TAKE23 NGX_TAKE23 #define NDK_TAKE3 NGX_TAKE3 #define NDK_TAKE4 NGX_TAKE4 #define NDK_TAKE5 NGX_TAKE5 #define NDK_TAKE6 NGX_TAKE6 #define NDK_TAKE7 NGX_TAKE7 #define NDK_TAKE8 NGX_TAKE8 /* conf cmd bitmasks */ /* TODO : finish this */ #define NDK_HTTP_MAIN_CONF NGX_HTTP_MAIN_CONF #define NDK_HTTP_SRV_CONF NGX_HTTP_SRV_CONF #define NDK_HTTP_SIF_CONF NGX_HTTP_SIF_CONF #define NDK_HTTP_LOC_CONF NGX_HTTP_LOC_CONF #define NDK_HTTP_LIF_CONF NGX_HTTP_LIF_CONF #define NDK_HTTP_UPS_CONF NGX_HTTP_UPS_CONF #define NDK_MAIN_CONF NGX_MAIN_CONF #define NDK_ANY_CONF NGX_ANY_CONF /* compound locations */ #define NDK_HTTP_MAIN_SRV_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SRV_CONF #define NDK_HTTP_MAIN_SIF_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SRV_SIF_CONF #define NDK_HTTP_MAIN_LOC_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_LOC_CONF #define NDK_HTTP_MAIN_LIF_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_LOC_LIF_CONF #define NDK_HTTP_SRV_SIF_CONF NDK_HTTP_SRV_CONF|NDK_HTTP_SIF_CONF #define NDK_HTTP_SRV_LOC_CONF NDK_HTTP_SRV_CONF|NDK_HTTP_LOC_CONF #define NDK_HTTP_SRV_LOC_LIF_CONF NDK_HTTP_SRV_CONF|NDK_HTTP_LOC_LIF_CONF #define NDK_HTTP_SRV_SIF_LOC_CONF NDK_HTTP_SRV_SIF_CONF|NDK_HTTP_LOC_CONF #define NDK_HTTP_SRV_SIF_LOC_LIF_CONF NDK_HTTP_SRV_SIF_CONF|NDK_HTTP_LOC_LIF_CONF #define NDK_HTTP_LOC_LIF_CONF NDK_HTTP_LOC_CONF|NDK_HTTP_LIF_CONF #define NDK_HTTP_MAIN_SRV_LOC_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SRV_LOC_CONF #define NDK_HTTP_MAIN_SRV_LIF_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SRV_LIF_CONF #define NDK_HTTP_MAIN_SIF_LOC_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SIF_LOC_CONF #define NDK_HTTP_MAIN_SRV_SIF_LOC_LIF_CONF NDK_HTTP_SRV_SIF_LOC_LIF_CONF|NDK_MAIN_CONF #define NDK_HTTP_CONF NDK_HTTP_MAIN_SRV_SIF_LOC_LIF_CONF #define NDK_HTTP_ANY_CONF NDK_HTTP_CONF|NDK_HTTP_UPS_CONF /* property offsets NOTE : ngx_module_main_conf_t etc should be defined in the module's .c file before the commands */ #define NDK_HTTP_MAIN_CONF_PROP(p) NGX_HTTP_MAIN_CONF_OFFSET, offsetof (ndk_module_main_conf_t, p) #define NDK_HTTP_SRV_CONF_PROP(p) NGX_HTTP_SRV_CONF_OFFSET, offsetof (ndk_module_srv_conf_t, p) #define NDK_HTTP_LOC_CONF_PROP(p) NGX_HTTP_LOC_CONF_OFFSET, offsetof (ndk_module_loc_conf_t, p) /* conf cmd basic macros */ #define NDK_HTTP_MAIN_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_1MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_1MORE|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_2MORE(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_2MORE|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_ANY(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ANY|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_ARGS_NUMBER(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_ARGS_NUMBER|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_BLOCK(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_BLOCK|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_FLAG(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_FLAG|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_MULTI(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_MULTI|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE1(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE12(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE12|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE123(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE123|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE1234(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE1234|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE13(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE13|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE2(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE2|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE23(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE23|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE3(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE3|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE4(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE4|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE5(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE5|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE6(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE6|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE7(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE7|NDK_ANY_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LOC_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_LIF_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_SRV_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_SIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LOC_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_LIF_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LOC_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SRV_LIF_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LOC_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_SIF_LIF_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_SIF_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LOC_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_SRV_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_LIF_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_SRV_LIF_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SIF_LOC_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_MAIN_SRV_SIF_LOC_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_MAIN_SRV_SIF_LOC_CONF,\ func, off1, off2, post}, #define NDK_HTTP_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_CONF,\ func, off1, off2, post}, #define NDK_HTTP_UPS_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_UPS_CONF,\ func, off1, off2, post}, #define NDK_HTTP_ANY_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_HTTP_ANY_CONF,\ func, off1, off2, post}, #define NDK_ANY_CONF_TAKE8(name,func,off1,off2,post)\ {ngx_string (name),\ NGX_CONF_TAKE8|NDK_ANY_CONF,\ func, off1, off2, post}, debian/modules/nginx-development-kit/objs/ndk_config.h0000664000000000000000000000312012705233614020276 0ustar /* * 2010 (C) Marcus Clyne * * DO NOT EDIT THIS FILE MANUALLY * ------------------------------ * This file has been generated automatically from scripts in the $base/auto dir and * data in the $base/auto/data dir. If you wish to edit the output of this file, then * you should edit these files instead. * */ /* include all optional modules */ #ifdef NDK_ALL #ifndef NDK_BUF #define NDK_BUF 1 #endif #ifndef NDK_COMPLEX_PATH #define NDK_COMPLEX_PATH 1 #endif #ifndef NDK_COMPLEX_VALUE #define NDK_COMPLEX_VALUE 1 #endif #ifndef NDK_CONF_FILE #define NDK_CONF_FILE 1 #endif #ifndef NDK_ENCODING #define NDK_ENCODING 1 #endif #ifndef NDK_HASH #define NDK_HASH 1 #endif #ifndef NDK_HTTP #define NDK_HTTP 1 #endif #ifndef NDK_PATH #define NDK_PATH 1 #endif #ifndef NDK_PROCESS #define NDK_PROCESS 1 #endif #ifndef NDK_REGEX #define NDK_REGEX 1 #endif #ifndef NDK_REWRITE #define NDK_REWRITE 1 #endif #ifndef NDK_SET_VAR #define NDK_SET_VAR 1 #endif #ifndef NDK_STRING #define NDK_STRING 1 #endif #ifndef NDK_UPSTREAM_LIST #define NDK_UPSTREAM_LIST 1 #endif #ifndef NDK_URI #define NDK_URI 1 #endif #endif /* module dependencies */ #ifdef NDK_COMPLEX_PATH #ifndef NDK_COMPLEX_VALUE #define NDK_COMPLEX_VALUE 1 #endif #ifndef NDK_PATH #define NDK_PATH 1 #endif #endif #ifdef NDK_CONF_FILE #ifndef NDK_STRING #define NDK_STRING 1 #endif #endif #ifdef NDK_HASH #ifndef NDK_STRING #define NDK_STRING 1 #endif #endif #ifdef NDK_SET_VAR #ifndef NDK_REWRITE #define NDK_REWRITE 1 #endif #endif #ifdef NDK_UPSTREAM_LIST #ifndef NDK_HTTP_CREATE_MAIN_CONF #define NDK_HTTP_CREATE_MAIN_CONF 1 #endif #endif debian/modules/nginx-development-kit/objs/ndk_array.h0000664000000000000000000002117512705233614020161 0ustar /* * 2010 (C) Marcus Clyne * * DO NOT EDIT THIS FILE MANUALLY * ------------------------------ * This file has been generated automatically from scripts in the $base/auto dir and * data in the $base/auto/data dir. If you wish to edit the output of this file, then * you should edit these files instead. * */ /* Non-generated macros */ #define ndk_array_count(a) ((a)->nelts) #define ndk_array_get_first(a) ((a)->elts) #define ndk_array_get_index(a,n) ((void*) ((char*) (a)->elts + (a)->size * n)) #define ndk_array_get_last(a) ((void*) ((char*) (a)->elts + (a)->size * ((a)->nelts - 1))) #define ndk_array_get_reverse_index(a,n) ((void*) ((char*) (a)->elts + (a)->size * ((a)->nelts - 1 - n))) #define ndk_array_push_clean(p,a) {p = ngx_array_push (a); ndk_zerop (p);} /* base action macro macros */ #define ndk_array_create_ac(a,pl,n,sz,ac) {a = ngx_array_create (pl,n,sz); if (a == NULL) ac;} #define ndk_array_init_ac(a,pl,n,sz,ac) {if (ngx_array_init (a,pl,n,sz) == NGX_ERROR) ac;} #define ndk_array_push_ac(p,a,ac) {p = ngx_array_push (a); if (p == NULL) ac;} #define ndk_array_push_clean_ac(p,a,ac) {p = ngx_array_push (a); if (p == NULL) ac; ndk_zerop (p);} #define ndk_array_push_n_ac(p,a,n,ac) {p = ngx_array_push_n (a,n); if (p == NULL) ac;} #define ndk_array_push_n_clean_ac(p,a,n,ac) {p = ngx_array_push_n (a,n); if (p == NULL) ac; ndk_zeropn (p,n);} /* generated action macros */ #define ndk_array_create_r0(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,return 0) #define ndk_array_create_r1(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,return 1) #define ndk_array_create_r_1(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,return -1) #define ndk_array_create_rok(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,return NGX_OK) #define ndk_array_create_rce(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,return NGX_CONF_ERROR) #define ndk_array_create_rcok(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,return NGX_CONF_OK) #define ndk_array_create_re(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,return NGX_ERROR) #define ndk_array_create_rn(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,return NULL) #define ndk_array_create_rse(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,{ngx_script_error (e); return;}) #define ndk_array_create_sce(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,{ngx_script_configure_error (c); return;}) #define ndk_array_create_g(a,pl,n,sz,_lb) ndk_array_create_ac (a,pl,n,sz,goto _lb) #define ndk_array_create_ge(a,pl,n,sz) ndk_array_create_ac (a,pl,n,sz,goto error) #define ndk_array_init_r0(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,return 0) #define ndk_array_init_r1(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,return 1) #define ndk_array_init_r_1(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,return -1) #define ndk_array_init_rok(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,return NGX_OK) #define ndk_array_init_rce(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,return NGX_CONF_ERROR) #define ndk_array_init_rcok(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,return NGX_CONF_OK) #define ndk_array_init_re(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,return NGX_ERROR) #define ndk_array_init_rn(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,return NULL) #define ndk_array_init_rse(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,{ngx_script_error (e); return;}) #define ndk_array_init_sce(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,{ngx_script_configure_error (c); return;}) #define ndk_array_init_g(a,pl,n,sz,_lb) ndk_array_init_ac (a,pl,n,sz,goto _lb) #define ndk_array_init_ge(a,pl,n,sz) ndk_array_init_ac (a,pl,n,sz,goto error) #define ndk_array_push_r0(p,a) ndk_array_push_ac (p,a,return 0) #define ndk_array_push_r1(p,a) ndk_array_push_ac (p,a,return 1) #define ndk_array_push_r_1(p,a) ndk_array_push_ac (p,a,return -1) #define ndk_array_push_rok(p,a) ndk_array_push_ac (p,a,return NGX_OK) #define ndk_array_push_rce(p,a) ndk_array_push_ac (p,a,return NGX_CONF_ERROR) #define ndk_array_push_rcok(p,a) ndk_array_push_ac (p,a,return NGX_CONF_OK) #define ndk_array_push_re(p,a) ndk_array_push_ac (p,a,return NGX_ERROR) #define ndk_array_push_rn(p,a) ndk_array_push_ac (p,a,return NULL) #define ndk_array_push_rse(p,a) ndk_array_push_ac (p,a,{ngx_script_error (e); return;}) #define ndk_array_push_sce(p,a) ndk_array_push_ac (p,a,{ngx_script_configure_error (c); return;}) #define ndk_array_push_g(p,a,_lb) ndk_array_push_ac (p,a,goto _lb) #define ndk_array_push_ge(p,a) ndk_array_push_ac (p,a,goto error) #define ndk_array_push_clean_r0(p,a) ndk_array_push_clean_ac (p,a,return 0) #define ndk_array_push_clean_r1(p,a) ndk_array_push_clean_ac (p,a,return 1) #define ndk_array_push_clean_r_1(p,a) ndk_array_push_clean_ac (p,a,return -1) #define ndk_array_push_clean_rok(p,a) ndk_array_push_clean_ac (p,a,return NGX_OK) #define ndk_array_push_clean_rce(p,a) ndk_array_push_clean_ac (p,a,return NGX_CONF_ERROR) #define ndk_array_push_clean_rcok(p,a) ndk_array_push_clean_ac (p,a,return NGX_CONF_OK) #define ndk_array_push_clean_re(p,a) ndk_array_push_clean_ac (p,a,return NGX_ERROR) #define ndk_array_push_clean_rn(p,a) ndk_array_push_clean_ac (p,a,return NULL) #define ndk_array_push_clean_rse(p,a) ndk_array_push_clean_ac (p,a,{ngx_script_error (e); return;}) #define ndk_array_push_clean_sce(p,a) ndk_array_push_clean_ac (p,a,{ngx_script_configure_error (c); return;}) #define ndk_array_push_clean_g(p,a,_lb) ndk_array_push_clean_ac (p,a,goto _lb) #define ndk_array_push_clean_ge(p,a) ndk_array_push_clean_ac (p,a,goto error) #define ndk_array_push_n_r0(p,a,n) ndk_array_push_n_ac (p,a,n,return 0) #define ndk_array_push_n_r1(p,a,n) ndk_array_push_n_ac (p,a,n,return 1) #define ndk_array_push_n_r_1(p,a,n) ndk_array_push_n_ac (p,a,n,return -1) #define ndk_array_push_n_rok(p,a,n) ndk_array_push_n_ac (p,a,n,return NGX_OK) #define ndk_array_push_n_rce(p,a,n) ndk_array_push_n_ac (p,a,n,return NGX_CONF_ERROR) #define ndk_array_push_n_rcok(p,a,n) ndk_array_push_n_ac (p,a,n,return NGX_CONF_OK) #define ndk_array_push_n_re(p,a,n) ndk_array_push_n_ac (p,a,n,return NGX_ERROR) #define ndk_array_push_n_rn(p,a,n) ndk_array_push_n_ac (p,a,n,return NULL) #define ndk_array_push_n_rse(p,a,n) ndk_array_push_n_ac (p,a,n,{ngx_script_error (e); return;}) #define ndk_array_push_n_sce(p,a,n) ndk_array_push_n_ac (p,a,n,{ngx_script_configure_error (c); return;}) #define ndk_array_push_n_g(p,a,n,_lb) ndk_array_push_n_ac (p,a,n,goto _lb) #define ndk_array_push_n_ge(p,a,n) ndk_array_push_n_ac (p,a,n,goto error) #define ndk_array_push_n_clean_r0(p,a,n) ndk_array_push_n_clean_ac (p,a,n,return 0) #define ndk_array_push_n_clean_r1(p,a,n) ndk_array_push_n_clean_ac (p,a,n,return 1) #define ndk_array_push_n_clean_r_1(p,a,n) ndk_array_push_n_clean_ac (p,a,n,return -1) #define ndk_array_push_n_clean_rok(p,a,n) ndk_array_push_n_clean_ac (p,a,n,return NGX_OK) #define ndk_array_push_n_clean_rce(p,a,n) ndk_array_push_n_clean_ac (p,a,n,return NGX_CONF_ERROR) #define ndk_array_push_n_clean_rcok(p,a,n) ndk_array_push_n_clean_ac (p,a,n,return NGX_CONF_OK) #define ndk_array_push_n_clean_re(p,a,n) ndk_array_push_n_clean_ac (p,a,n,return NGX_ERROR) #define ndk_array_push_n_clean_rn(p,a,n) ndk_array_push_n_clean_ac (p,a,n,return NULL) #define ndk_array_push_n_clean_rse(p,a,n) ndk_array_push_n_clean_ac (p,a,n,{ngx_script_error (e); return;}) #define ndk_array_push_n_clean_sce(p,a,n) ndk_array_push_n_clean_ac (p,a,n,{ngx_script_configure_error (c); return;}) #define ndk_array_push_n_clean_g(p,a,n,_lb) ndk_array_push_n_clean_ac (p,a,n,goto _lb) #define ndk_array_push_n_clean_ge(p,a,n) ndk_array_push_n_clean_ac (p,a,n,goto error) debian/modules/nginx-development-kit/objs/ndk_conf_merge.h0000664000000000000000000002725512705233614021154 0ustar /* * 2010 (C) Marcus Clyne * * DO NOT EDIT THIS FILE MANUALLY * ------------------------------ * This file has been generated automatically from scripts in the $base/auto dir and * data in the $base/auto/data dir. If you wish to edit the output of this file, then * you should edit these files instead. * */ /* conf-merge-value macros */ /* TODO : check that all the main types have a corresponding merge function */ #define ndk_conf_merge_value ngx_conf_merge_value #define ndk_conf_merge_off_value ngx_conf_merge_off_value #define ndk_conf_merge_ptr_value ngx_conf_merge_ptr_value #define ndk_conf_merge_str_value ngx_conf_merge_str_value #define ndk_conf_merge_size_value ngx_conf_merge_size_value #define ndk_conf_merge_keyval_value(conf,prev,default) \ \ conf = prev ? prev : default; #define ndk_conf_merge_str_array_value(conf,prev,val1,...) \ \ if (conf == NGX_CONF_UNSET_PTR) { \ if (prev == NGX_CONF_UNSET_PTR) { \ if (val1 == NULL) { \ conf = NULL; \ } else { \ char * elts[] = {val1,##__VA_ARGS__}; \ int n = sizeof(elts)/sizeof(char*); \ \ conf = ndk_str_array_create (cf->pool, elts, n); \ \ if (conf == NULL) \ return NGX_CONF_ERROR; \ } \ } else { \ conf = prev; \ } \ } #define ndk_conf_merge_http_complex_value_value(conf,prev,default) \ \ if (!conf.str.len) { \ if (prev.str.len) { \ conf = prev; \ } else { \ conf.str.data = (u_char *) default; \ conf.str.len = sizeof (default) - 1; \ \ if (ndk_http_complex_value_compile (cf, &conf)) \ return NGX_CONF_ERROR; \ } \ } #define ndk_conf_merge_http_complex_value_array_value(conf,prev,val1,...) \ \ if (conf == NGX_CONF_UNSET_PTR) { \ if (prev == NGX_CONF_UNSET_PTR) { \ if (val1 == NULL) \ conf = NULL; \ else { \ char * elts[] = {val1,##__VA_ARGS__}; \ int n = sizeof(elts)/sizeof(char*); \ \ conf = ndk_http_complex_value_array_create (cf, elts, n); \ \ if (conf == NULL) \ return NGX_CONF_ERROR; \ } \ } else { \ conf = prev; \ } \ } #define ndk_conf_merge_http_complex_path_value(conf,prev,...) \ ndk_conf_merge_http_complex_value_array_value (conf.a, prev.a, __VA_ARGS__) #define ndk_conf_merge_split_path_value(conf,prev,path) \ \ if (conf == NGX_CONF_UNSET_PTR) { \ conf = (prev == NGX_CONF_UNSET_PTR ? \ ndk_split_path_create_raw (cf, path) : prev); \ } /* conf-merge-prop macros */ #define ndk_conf_merge_prop(prop,default)\ ndk_conf_merge_value\ (conf->prop, prev->prop, default) #define ndk_conf_merge_bitmask_prop(prop,default,...)\ ndk_conf_merge_bitmask_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_bufs_prop(prop,default,...)\ ndk_conf_merge_bufs_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_encoding_prop(prop,default,...)\ ndk_conf_merge_encoding_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_enum_prop(prop,default,...)\ ndk_conf_merge_enum_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_false_prop(prop,default,...)\ ndk_conf_merge_false_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_flag_prop(prop,default,...)\ ndk_conf_merge_flag_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_full_path_prop(prop,default,...)\ ndk_conf_merge_full_path_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_http_complex_keyval_prop(prop,default,...)\ ndk_conf_merge_http_complex_keyval_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_http_complex_path_prop(prop,default,...)\ ndk_conf_merge_http_complex_path_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_http_complex_value_prop(prop,default,...)\ ndk_conf_merge_http_complex_value_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_http_complex_value_array_prop(prop,default,...)\ ndk_conf_merge_http_complex_value_array_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_keyval_prop(prop,default,...)\ ndk_conf_merge_keyval_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_keyval1_prop(prop,default,...)\ ndk_conf_merge_keyval1_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_msec_prop(prop,default,...)\ ndk_conf_merge_msec_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_null_prop(prop,default,...)\ ndk_conf_merge_null_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_num_prop(prop,default,...)\ ndk_conf_merge_num_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_num64_prop(prop,default,...)\ ndk_conf_merge_num64_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_num_flag_prop(prop,default,...)\ ndk_conf_merge_num_flag_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_off_prop(prop,default,...)\ ndk_conf_merge_off_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_ptr_prop(prop,default,...)\ ndk_conf_merge_ptr_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_regex_prop(prop,default,...)\ ndk_conf_merge_regex_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_regex_array_prop(prop,default,...)\ ndk_conf_merge_regex_array_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_regex_array_caseless_prop(prop,default,...)\ ndk_conf_merge_regex_array_caseless_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_regex_caseless_prop(prop,default,...)\ ndk_conf_merge_regex_caseless_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_sec_prop(prop,default,...)\ ndk_conf_merge_sec_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_sec_flag_prop(prop,default,...)\ ndk_conf_merge_sec_flag_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_size_prop(prop,default,...)\ ndk_conf_merge_size_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_split_path_prop(prop,default,...)\ ndk_conf_merge_split_path_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_str_prop(prop,default,...)\ ndk_conf_merge_str_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_str_array_prop(prop,default,...)\ ndk_conf_merge_str_array_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_str_array_multi_prop(prop,default,...)\ ndk_conf_merge_str_array_multi_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) #define ndk_conf_merge_true_prop(prop,default,...)\ ndk_conf_merge_true_value\ (conf->prop, prev->prop, default,##__VA_ARGS__) debian/modules/nginx-development-kit/objs/ndk_palloc.h0000664000000000000000000002061112705233614020307 0ustar /* * 2010 (C) Marcus Clyne * * DO NOT EDIT THIS FILE MANUALLY * ------------------------------ * This file has been generated automatically from scripts in the $base/auto dir and * data in the $base/auto/data dir. If you wish to edit the output of this file, then * you should edit these files instead. * */ /* Non-generated macros */ #define ndk_pallocp(p,pl) p = ngx_palloc (pl,sizeof(*p)) #define ndk_pallocpn(p,pl,n) p = ngx_palloc (pl,sizeof(*p)*(n)) #define ndk_pcallocp(p,pl) p = ngx_pcalloc (pl,sizeof(*p)) #define ndk_pcallocpn(p,pl,n) p = ngx_pcalloc (pl,sizeof(*p)*(n)) /* base action macro macros */ #define ndk_palloc_ac(p,pl,sz,ac) {p = ngx_palloc (pl,sz); if (p == NULL) ac;} #define ndk_pallocp_ac(p,pl,ac) {ndk_pallocp (p,pl); if (p == NULL) ac;} #define ndk_pallocpn_ac(p,pl,n,ac) {ndk_pallocpn (p,pl,n); if (p == NULL) ac;} #define ndk_pcalloc_ac(p,pl,sz,ac) {p = ngx_pcalloc (pl,sz); if (p == NULL) ac;} #define ndk_pcallocp_ac(p,pl,ac) {ndk_pcallocp (p,pl); if (p == NULL) ac;} #define ndk_pcallocpn_ac(p,pl,n,ac) {ndk_pcallocpn (p,pl,n); if (p == NULL) ac;} /* generated action macros */ #define ndk_palloc_r0(p,pl,sz) ndk_palloc_ac (p,pl,sz,return 0) #define ndk_palloc_r1(p,pl,sz) ndk_palloc_ac (p,pl,sz,return 1) #define ndk_palloc_r_1(p,pl,sz) ndk_palloc_ac (p,pl,sz,return -1) #define ndk_palloc_rok(p,pl,sz) ndk_palloc_ac (p,pl,sz,return NGX_OK) #define ndk_palloc_rce(p,pl,sz) ndk_palloc_ac (p,pl,sz,return NGX_CONF_ERROR) #define ndk_palloc_rcok(p,pl,sz) ndk_palloc_ac (p,pl,sz,return NGX_CONF_OK) #define ndk_palloc_re(p,pl,sz) ndk_palloc_ac (p,pl,sz,return NGX_ERROR) #define ndk_palloc_rn(p,pl,sz) ndk_palloc_ac (p,pl,sz,return NULL) #define ndk_palloc_rse(p,pl,sz) ndk_palloc_ac (p,pl,sz,{ngx_script_error (e); return;}) #define ndk_palloc_sce(p,pl,sz) ndk_palloc_ac (p,pl,sz,{ngx_script_configure_error (c); return;}) #define ndk_palloc_g(p,pl,sz,_lb) ndk_palloc_ac (p,pl,sz,goto _lb) #define ndk_palloc_ge(p,pl,sz) ndk_palloc_ac (p,pl,sz,goto error) #define ndk_pallocp_r0(p,pl) ndk_pallocp_ac (p,pl,return 0) #define ndk_pallocp_r1(p,pl) ndk_pallocp_ac (p,pl,return 1) #define ndk_pallocp_r_1(p,pl) ndk_pallocp_ac (p,pl,return -1) #define ndk_pallocp_rok(p,pl) ndk_pallocp_ac (p,pl,return NGX_OK) #define ndk_pallocp_rce(p,pl) ndk_pallocp_ac (p,pl,return NGX_CONF_ERROR) #define ndk_pallocp_rcok(p,pl) ndk_pallocp_ac (p,pl,return NGX_CONF_OK) #define ndk_pallocp_re(p,pl) ndk_pallocp_ac (p,pl,return NGX_ERROR) #define ndk_pallocp_rn(p,pl) ndk_pallocp_ac (p,pl,return NULL) #define ndk_pallocp_rse(p,pl) ndk_pallocp_ac (p,pl,{ngx_script_error (e); return;}) #define ndk_pallocp_sce(p,pl) ndk_pallocp_ac (p,pl,{ngx_script_configure_error (c); return;}) #define ndk_pallocp_g(p,pl,_lb) ndk_pallocp_ac (p,pl,goto _lb) #define ndk_pallocp_ge(p,pl) ndk_pallocp_ac (p,pl,goto error) #define ndk_pallocpn_r0(p,pl,n) ndk_pallocpn_ac (p,pl,n,return 0) #define ndk_pallocpn_r1(p,pl,n) ndk_pallocpn_ac (p,pl,n,return 1) #define ndk_pallocpn_r_1(p,pl,n) ndk_pallocpn_ac (p,pl,n,return -1) #define ndk_pallocpn_rok(p,pl,n) ndk_pallocpn_ac (p,pl,n,return NGX_OK) #define ndk_pallocpn_rce(p,pl,n) ndk_pallocpn_ac (p,pl,n,return NGX_CONF_ERROR) #define ndk_pallocpn_rcok(p,pl,n) ndk_pallocpn_ac (p,pl,n,return NGX_CONF_OK) #define ndk_pallocpn_re(p,pl,n) ndk_pallocpn_ac (p,pl,n,return NGX_ERROR) #define ndk_pallocpn_rn(p,pl,n) ndk_pallocpn_ac (p,pl,n,return NULL) #define ndk_pallocpn_rse(p,pl,n) ndk_pallocpn_ac (p,pl,n,{ngx_script_error (e); return;}) #define ndk_pallocpn_sce(p,pl,n) ndk_pallocpn_ac (p,pl,n,{ngx_script_configure_error (c); return;}) #define ndk_pallocpn_g(p,pl,n,_lb) ndk_pallocpn_ac (p,pl,n,goto _lb) #define ndk_pallocpn_ge(p,pl,n) ndk_pallocpn_ac (p,pl,n,goto error) #define ndk_pcalloc_r0(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,return 0) #define ndk_pcalloc_r1(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,return 1) #define ndk_pcalloc_r_1(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,return -1) #define ndk_pcalloc_rok(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,return NGX_OK) #define ndk_pcalloc_rce(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,return NGX_CONF_ERROR) #define ndk_pcalloc_rcok(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,return NGX_CONF_OK) #define ndk_pcalloc_re(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,return NGX_ERROR) #define ndk_pcalloc_rn(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,return NULL) #define ndk_pcalloc_rse(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,{ngx_script_error (e); return;}) #define ndk_pcalloc_sce(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,{ngx_script_configure_error (c); return;}) #define ndk_pcalloc_g(p,pl,sz,_lb) ndk_pcalloc_ac (p,pl,sz,goto _lb) #define ndk_pcalloc_ge(p,pl,sz) ndk_pcalloc_ac (p,pl,sz,goto error) #define ndk_pcallocp_r0(p,pl) ndk_pcallocp_ac (p,pl,return 0) #define ndk_pcallocp_r1(p,pl) ndk_pcallocp_ac (p,pl,return 1) #define ndk_pcallocp_r_1(p,pl) ndk_pcallocp_ac (p,pl,return -1) #define ndk_pcallocp_rok(p,pl) ndk_pcallocp_ac (p,pl,return NGX_OK) #define ndk_pcallocp_rce(p,pl) ndk_pcallocp_ac (p,pl,return NGX_CONF_ERROR) #define ndk_pcallocp_rcok(p,pl) ndk_pcallocp_ac (p,pl,return NGX_CONF_OK) #define ndk_pcallocp_re(p,pl) ndk_pcallocp_ac (p,pl,return NGX_ERROR) #define ndk_pcallocp_rn(p,pl) ndk_pcallocp_ac (p,pl,return NULL) #define ndk_pcallocp_rse(p,pl) ndk_pcallocp_ac (p,pl,{ngx_script_error (e); return;}) #define ndk_pcallocp_sce(p,pl) ndk_pcallocp_ac (p,pl,{ngx_script_configure_error (c); return;}) #define ndk_pcallocp_g(p,pl,_lb) ndk_pcallocp_ac (p,pl,goto _lb) #define ndk_pcallocp_ge(p,pl) ndk_pcallocp_ac (p,pl,goto error) #define ndk_pcallocpn_r0(p,pl,n) ndk_pcallocpn_ac (p,pl,n,return 0) #define ndk_pcallocpn_r1(p,pl,n) ndk_pcallocpn_ac (p,pl,n,return 1) #define ndk_pcallocpn_r_1(p,pl,n) ndk_pcallocpn_ac (p,pl,n,return -1) #define ndk_pcallocpn_rok(p,pl,n) ndk_pcallocpn_ac (p,pl,n,return NGX_OK) #define ndk_pcallocpn_rce(p,pl,n) ndk_pcallocpn_ac (p,pl,n,return NGX_CONF_ERROR) #define ndk_pcallocpn_rcok(p,pl,n) ndk_pcallocpn_ac (p,pl,n,return NGX_CONF_OK) #define ndk_pcallocpn_re(p,pl,n) ndk_pcallocpn_ac (p,pl,n,return NGX_ERROR) #define ndk_pcallocpn_rn(p,pl,n) ndk_pcallocpn_ac (p,pl,n,return NULL) #define ndk_pcallocpn_rse(p,pl,n) ndk_pcallocpn_ac (p,pl,n,{ngx_script_error (e); return;}) #define ndk_pcallocpn_sce(p,pl,n) ndk_pcallocpn_ac (p,pl,n,{ngx_script_configure_error (c); return;}) #define ndk_pcallocpn_g(p,pl,n,_lb) ndk_pcallocpn_ac (p,pl,n,goto _lb) #define ndk_pcallocpn_ge(p,pl,n) ndk_pcallocpn_ac (p,pl,n,goto error) debian/modules/nginx-development-kit/notes/0000775000000000000000000000000012705233614016223 5ustar debian/modules/nginx-development-kit/notes/LICENSE0000664000000000000000000000276612705233614017243 0ustar Copyright (c) 2010, Marcus Clyne, Simpl (simpl.it) 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. * Neither the name of the organization (Simpl) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 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 MARCUS CLYNE OR SIMPL 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. debian/modules/nginx-development-kit/notes/CHANGES0000664000000000000000000000143512705233614017221 0ustar Changelog --------- 0.1 feature : set_var functions 0.1.1 feature : upstream_list directive and functions 0.2 feature : conf merge functions feature : conf command macros feature : 'action' macros 0.2.1 bugfix : ndk_map_uri_to_path_add_suffix 0.2.2 feature : regex conf functions 0.2.3 feature : version number 0.2.4 change : the auto/build script is now executed automatically on compilation 0.2.9 feature : ngx_auto_lib included with source 0.2.11 bugfix : hash functions did not display properly 0.2.12 feature : patches for rewrite functions and rewrite phase handler 0.2.13 change : revert to old behaviour rewrite functions change : pre-generated config and macro files now provideddebian/modules/nginx-development-kit/examples/0000775000000000000000000000000012705233614016711 5ustar debian/modules/nginx-development-kit/examples/README0000664000000000000000000000042512705233614017572 0ustar 2010 (C) Marcus Clyne Examples -------- In this section there are a number of examples of the various features of the tools module. These have been given in the form of dummy modules, to make it easier to use as templates for your own module should you choose to do so. debian/modules/nginx-development-kit/examples/http/0000775000000000000000000000000012705233614017670 5ustar debian/modules/nginx-development-kit/examples/http/set_var/0000775000000000000000000000000012705233614021333 5ustar debian/modules/nginx-development-kit/examples/http/set_var/config0000664000000000000000000000033512705233614022524 0ustar ngx_addon_name=ngx_http_set_var_examples_module HTTP_MODULES="$HTTP_MODULES ngx_http_set_var_examples_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_set_var_examples_module.c" have=NDK_SET_VAR . auto/havedebian/modules/nginx-development-kit/examples/http/set_var/ngx_http_set_var_examples_module.c0000664000000000000000000000703012705233614030320 0ustar /* * 2010 (C) Marcus Clyne */ #include static ngx_int_t ngx_http_set_var_concat2 (ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *v); static char * ngx_http_set_prepend_hello (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ndk_set_var_t ngx_http_var_set_concat2 = { NDK_SET_VAR_MULTI_VALUE, ngx_http_set_var_concat2, 2, NULL }; static ngx_command_t ngx_http_set_var_examples_commands[] = { { ngx_string ("set_concat2"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE3, ndk_set_var_multi_value, 0, 0, &ngx_http_var_set_concat2 }, { ngx_string ("set_prepend_hello"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, ngx_http_set_prepend_hello, 0, 0, NULL }, ngx_null_command }; ngx_http_module_t ngx_http_set_var_examples_module_ctx = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; ngx_module_t ngx_http_set_var_examples_module = { NGX_MODULE_V1, &ngx_http_set_var_examples_module_ctx, // module context ngx_http_set_var_examples_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 }; /* This function is called by both examples, takes two variable values and concatenates them to give a third string. */ static ngx_int_t ngx_http_set_var_concat2 (ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *v) { size_t len; ngx_http_variable_value_t *v2; u_char *p; v2 = v + 1; len = v->len + v2->len; /* * NDK provided abbreviation for the following code: * * p = ngx_palloc (r->pool, len); * if (p == NULL) * return NGX_ERROR; * * */ ndk_palloc_re(p, r->pool, len); val->data = p; val->len = len; ngx_memzero (p, len); p = ngx_cpymem (p, v->data, v->len); ngx_memcpy (p, v2->data, v2->len); return NGX_OK; } /* This function demonstrates using the 'core' function in a function that appends the word 'hello_' to the beginning of a variable. set $var world; set_prepend_hello $var $var; If the arguments used in the variable value filter do not all come directly from the conf file, or are not given in the order direcive $var_name val1 "val2 string $var" ... then the _core functions should be used inside the function that is called when the directive is read. */ static char * ngx_http_set_prepend_hello (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t s[2], *var_name; ndk_set_var_t filter; var_name = cf->args->elts; var_name++; s[0].data = (u_char*) "hello_"; s[0].len = 6; s[1] = *(var_name + 1); filter.type = NDK_SET_VAR_MULTI_VALUE; filter.func = ngx_http_set_var_concat2; filter.size = 2; return ndk_set_var_multi_value_core (cf, var_name, (ngx_str_t *) s, &filter); } debian/modules/nginx-development-kit/README0000664000000000000000000001036312705233614015756 0ustar Nginx Development Kit (NDK) =========================== Synopsis The NDK is an Nginx module that is designed to extend the core functionality of the excellent Nginx webserver in a way that can be used as a basis of other Nginx modules. It has functions and macros to deal with generic tasks that don't currently have generic code as part of the core distribution. The NDK itself adds few features that are seen from a user's point of view - it's just designed to help reduce the code that Nginx module developers need to write. Nginx module developers wishing to use any of the features in the NDK should specify that the NDK is a dependency of their module, and that users will need to compile it as well when they compile their own modules. They will also need to declare in their own modules which features of the NDK they wish to use (explained below). If you are not an Nginx module developer, then the only useful part of this project will be the 'usage for users' section below. Status The NDK is now considered to be stable. It is already being used in quite a few third party modules. Features - additional conf_set functions for regexes, complex/script values, paths... - macros to simplify tasks like checking for NULL values when doing ngx_array_push - patches to the main source code - ngx_auto_lib_core generic external library handler is included (see separate readme) Design modular : The kit itself is designed in a modular way, so that only the required code is compiled. It's possible to add just a single NDK module, a few or all of them. auto-generated & easily extensible : Many of the macros available in the NDK are auto-generated from simple configuration files. This makes creating similar macros for your own code very simple - it's usually just the case of adding an extra line to a config file and re-running the build script. Usage for users If another Nginx module you wish to use specifies that the NDK is a dependency, you will need to do the following : 1 - download the source (http://github.com/simpl/ngx_devel_kit) 2 - unpack the source (tar -xzf $name) 3 - compile Nginx with the following extra option --add-module=/path/to/src e.g. ./configure --add-module=/path/to/ndk/base --add-module=/path/to/another/mod Usage for developers To use the NDK in your own module, you need to add the following : 1 - add this line to your module #include note : since the NDK includes the following lines #include #include #include you can replace these with the single include above. 2 - add the following line in the config file for your module : have=NDK_[module_name] . auto/have for each NDK module that you wish to use (you need to include auto/have multiple times if you wish to use multiple NDK modules. Note : the old method of setting CFLAGS="$CFLAGS -DNDK_[module_name]" is now deprecated. It will still work, but results in unnecessary lines being displayed when compiling Nginx. Warning : using NDK_ALL You can also set NDK_ALL to include all the NDK modules. This is primarily as a convenience in the early stages of development of another module. However, DO NOT LEAVE 'NDK_ALL' IN YOUR CONFIG FILE WHEN PUBLISHING Although the NDK is fairly small now, it could in time become a large repository of code that would, if using NDK_ALL, result in considerably more code being compiled than is necessary. Todo - documentation for modules that don't already have it - additional phase-handler functions - generically testing for needing to add a handler - remove dependency of set_var on OpenSSL being compiled in License BSD Contributing / Feedback If you are an Nginx module developer, and have developed some functions that are generic in nature (or would be easily adapted to be so), then please send them to me at the address below, and I'll add them to the kit. Author Marcus Clyne (contact at simpl dot it) debian/modules/nginx-development-kit/auto/0000775000000000000000000000000012705233614016043 5ustar debian/modules/nginx-development-kit/auto/data/0000775000000000000000000000000012705233614016754 5ustar debian/modules/nginx-development-kit/auto/data/headers0000664000000000000000000000004312705233614020307 0ustar http_headers log parse string_util debian/modules/nginx-development-kit/auto/data/modules_optional0000664000000000000000000000017412705233614022256 0ustar buf complex_path complex_value conf_file encoding hash http path process regex rewrite set_var string upstream_list * uri debian/modules/nginx-development-kit/auto/data/conf_locs0000664000000000000000000000176512705233614020655 0ustar HTTP_MAIN HTTP_MAIN main HTTP_SRV HTTP_SRV srv HTTP_SIF HTTP_SRV srv HTTP_LOC HTTP_LOC loc HTTP_LIF HTTP_LOC loc HTTP_MAIN_SRV HTTP_SRV srv HTTP_MAIN_SIF HTTP_SRV srv HTTP_MAIN_LOC HTTP_LOC loc HTTP_MAIN_LIF HTTP_LOC loc HTTP_SRV_LOC HTTP_LOC loc HTTP_SRV_LIF HTTP_LOC loc HTTP_SIF_LOC HTTP_LOC loc HTTP_SIF_LIF HTTP_LOC loc HTTP_MAIN_SRV_LOC HTTP_LOC loc HTTP_MAIN_SRV_LIF HTTP_LOC loc HTTP_MAIN_SIF_LOC HTTP_LOC loc HTTP_MAIN_SRV_SIF_LOC HTTP_LOC loc HTTP HTTP_LOC loc HTTP_UPS HTTP_LOC loc HTTP_ANY HTTP_LOC loc ANY HTTP_LOC loc debian/modules/nginx-development-kit/auto/data/conf_macros0000664000000000000000000000246012705233614021172 0ustar BITMASK 1MORE bitmask BUFS TAKE1 bufs COMPLEX_KEYVAL TAKE2 http_complex_keyval COMPLEX_PATH TAKE1 http_complex_path COMPLEX_VALUE TAKE1 http_complex_value COMPLEX_VALUE_ARRAY 1MORE http_complex_value_array ENCODING TAKE1 encoding ENUM TAKE1 enum FALSE NOARGS false FULL_PATH TAKE1 full_path KEYVAL TAKE2 keyval KEYVAL1 TAKE2 keyval1 MSEC TAKE1 msec NULL NOARGS null NUM TAKE1 num NUM64 TAKE1 num64 NUM_FLAG TAKE1 num_flag ONOFF FLAG flag OFF TAKE1 off PATH TAKE1 split_path REXEX TAKE1 regex REGEX_CL TAKE1 regex_caseless REGEX_ARRAY 1MORE regex_array REGEX_ARRAY_CL 1MORE regex_array_caseless PTR NOARGS ptr SEC TAKE1 sec SEC_FLAG TAKE2 sec_flag SIZE TAKE1 size STR TAKE1 str STR_ARRAY 1MORE str_array_multi STR_ARRAY1 TAKE1 str_array TRUE NOARGS true debian/modules/nginx-development-kit/auto/data/action_replacements0000664000000000000000000000011512705233614022713 0ustar OK NGX_OK E NGX_ERROR CE NGX_CONF_ERROR COK NGX_CONF_OK debian/modules/nginx-development-kit/auto/data/action_types0000664000000000000000000000050612705233614021401 0ustar r0 return 0 r1 return 1 r_1 return -1 rok return %OK% rce return %CE% rcok return %COK% re return %E% rn return NULL rse {ngx_script_error (e); return;} sce {ngx_script_configure_error (c); return;} g(_lb) goto _lb ge goto error debian/modules/nginx-development-kit/auto/data/module_dependencies0000664000000000000000000000022112705233614022665 0ustar complex_path complex_value path conf_file string hash string set_var rewrite upstream_list http_create_main_conf debian/modules/nginx-development-kit/auto/data/contexts0000664000000000000000000000023312705233614020544 0ustar MAIN SRV SIF LOC LIF MAIN_SRV MAIN_SIF MAIN_LOC MAIN_LIF SRV_LOC SRV_LIF SIF_LOC SIF_LIF MAIN_SRV_LOC MAIN_SRV_LIF MAIN_SIF_LOC MAIN_SIF_LIF ANY_MAIN debian/modules/nginx-development-kit/auto/data/prefixes0000664000000000000000000000001112705233614020514 0ustar ngx ndk debian/modules/nginx-development-kit/auto/data/header_files0000664000000000000000000000001612705233614021306 0ustar array palloc debian/modules/nginx-development-kit/auto/data/conf_args0000664000000000000000000000020612705233614020636 0ustar TAKE1 TAKE2 TAKE3 TAKE4 TAKE5 TAKE6 TAKE7 TAKE8 TAKE12 TAKE13 TAKE23 TAKE123 TAKE1234 1MORE 2MORE ANY FLAG BLOCK MULTI ARGS_NUMBER debian/modules/nginx-development-kit/auto/actions/0000775000000000000000000000000012705233614017503 5ustar debian/modules/nginx-development-kit/auto/actions/palloc0000664000000000000000000000075612705233614020710 0ustar palloc (p,pl,sz) p = %1%_palloc (pl,sz); if (p == NULL) %A% pallocp (p,pl) %2%_pallocp (p,pl); if (p == NULL) %A% pallocpn (p,pl,n) %2%_pallocpn (p,pl,n); if (p == NULL) %A% pcalloc (p,pl,sz) p = %1%_pcalloc (pl,sz); if (p == NULL) %A% pcallocp (p,pl) %2%_pcallocp (p,pl); if (p == NULL) %A% pcallocpn (p,pl,n) %2%_pcallocpn (p,pl,n); if (p == NULL) %A% debian/modules/nginx-development-kit/auto/actions/array0000664000000000000000000000102712705233614020544 0ustar array_create (a,pl,n,sz) a = %1%_array_create (pl,n,sz); if (a == NULL) %A% array_init (a,pl,n,sz) if (%1%_array_init (a,pl,n,sz) == %E%) %A% array_push (p,a) p = %1%_array_push (a); if (p == NULL) %A% array_push_clean (p,a) p = %1%_array_push (a); if (p == NULL) %A%; %2%_zerop (p) array_push_n (p,a,n) p = %1%_array_push_n (a,n); if (p == NULL) %A% array_push_n_clean (p,a,n) p = %1%_array_push_n (a,n); if (p == NULL) %A%; %2%_zeropn (p,n) debian/modules/nginx-development-kit/auto/build0000664000000000000000000003041512705233614017070 0ustar #! /bin/bash cd `dirname $0` if [ $# -eq 2 ]; then if [ `expr $2 : /` -eq 1 ]; then output_dir=$2 else output_dir=$1/$2 fi else output_dir=../objs fi list_file=data/action_list types_file=data/action_types reps_file=data/action_replacements prefix_file=data/prefixes header_file=data/header_files optional_modules_file=data/modules_optional headers_file=data/headers module_dependencies_file=data/module_dependencies conf_macros_file=data/conf_macros conf_locs_file=data/conf_locs conf_args_file=data/conf_args autogen_notice=text/autogen actions_dir=actions srcs_dir=src include_prefix= file_prefix=ndk_ auto_file_name=config auto_includes_name=includes conf_merge_filename=conf_merge.h conf_cmd_basic_filename=conf_cmd_basic.h conf_cmd_extra_filename=conf_cmd_extra.h spacer=¬ sed_delete_empty_lines='t_NEL;d;:_NEL' function trim_lines { sed -e '/./,$!d' -e :a -e '/^\n*$/{$d;N;ba' -e '}' } function strtoupper { [ $# -eq 1 ] || return 1 local _str _cu _cl _x _cu=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) _cl=(a b c d e f g h i j k l m n o p q r s t u v w x y z) _str=$1 for ((_x=0;_x<${#_cl[*]};_x++)); do _str=${_str//${_cl[$_x]}/${_cu[$_x]}} done echo $_str } function sed_pad_right { len=$1 spacer=$2 prefix=_PR$3 # returns a SED script that pads out (spaces) to the right to alignment $len # this script should be used inside a call to sed # NOTE : a spacer character $spacer should have already been written into the parsed string echo "t${prefix}a;:${prefix}a;s/^[^$spacer]{$len}/&/;\ t${prefix}b;s/^[^$spacer]*/& /;t${prefix}a;:${prefix}b;s/$spacer/ /" } function sed_pad_left { len=$1 spacer=$2 prefix=_PL$3 # echo "t${prefix}a;:${prefix}a;s/^[^$spacer]{$len}/& /;t${prefix}a" # NOT CORRECT? } function add_notice { echo > $1 cat $autogen_notice | trim_lines >> $1 echo >> $1 echo >> $1 } function add_non_generated_content { file=src/$1.h [ ! -f $file ] && return echo "/* Non-generated macros */" >> $2 echo >> $2 cat $file | trim_lines >> $2 echo >> $2 echo >> $2 } function add_action_macros { list_file=$actions_dir/$1 [ ! -f $list_file ] && return out=$2 # alignment settings align1=20 align2=35 align3=62 base_shrink=12 define="#define " # base macros echo "/* base action macro macros */" >> $out echo >> $out cat $list_file | trim_lines | sed -r \ -e "s/^[ ]*([a-zA-Z0-9_]+)([ ]*)\(([a-zA-Z0-9_,]+)\)([ ]*)(.*)/$define%2%_\1_ac(\3,ac)\2\4 {\5;}/" \ -e "s/[ ]{$base_shrink}\{/\{/" \ -e 's/%A%/ac/g' \ >> $out echo >> $out echo >> $out # generated macros echo "/* generated action macros */" >> $out echo >> $out cat -s $list_file | while read list_line; do [ "x`echo $list_line`" = 'x' ] && continue cat $types_file | while read type_line; do [ "x`echo $type_line`" = 'x' ] && continue #ext=`echo $type_line | grep -E '^[a-zA-Z0-9_]+' | cut -d " " -f1` ext=`echo $type_line | sed -r 's/^([a-zA-Z0-9_]+).*/\1/'` params=`echo $type_line | sed -r 's/^[a-zA-Z0-9_]+[ ]*\((.*)\).*/\1/;ta;d;:a'` act=`echo $type_line | sed -r 's/^[a-zA-Z0-9_]+[ ]*(\(.*\))?(.*)/\2/'` [ "x$params" != "x" ] && params=",$params" echo $list_line | sed -r \ -e "s/^([a-zA-Z0-9_]+)[ ]*\(([a-zA-Z0-9_,]+)\).*/%2%_\1_$ext(\2$params)$spacer%2%_\1_ac$spacer(\2,$act)/" \ -e 's/[ ]*,[ ]*/,/g' \ -e "`sed_pad_right $align2 $spacer 1`" \ -e "`sed_pad_right $align3 $spacer 2`" \ -e "s/.*/$define&/" \ >> $out done echo >> $out done } function replace_prefixes { temp=.temp file=`cat $prefix_file` prefix1= prefix2= for prefix in $file ; do [ "x$prefix2" != "x" ] && echo "Too many prefixes in prefix file $prefix_file" && exit 1 [ "x$prefix1" != "x" ] && prefix2=$prefix && continue prefix1=$prefix done sed -r "s/%1%/$prefix1/g;s/%2%/$prefix2/g" < $1 > $temp mv -f $temp $1 } function replace_other_strings { temp=.temp cat $reps_file | while read line; do rep1= rep2= for rep in $line ; do [ "x$rep2" != "x" ] && echo "Too many replacments in replacements file $reps_file" && exit 1 [ "x$rep1" != "x" ] && rep2=$rep && continue rep1=$rep done sed -r "s/%$rep1%/$rep2/g" < $1 > $temp mv -f $temp $1 done } function generate_header_file { name=$1 out=$output_dir/$file_prefix$name.h add_notice $out add_non_generated_content $name $out add_action_macros $name $out replace_prefixes $out replace_other_strings $out } function add_auto_include { echo "#include <${file_prefix}$2>" >> $1 } function add_include { echo "#include <${include_prefix}${file_prefix}$2>" >> $1 } function generate_non_optional_h_includes { # TODO : split into auto-generated and non-auto-generated ones echo "/* non-optional includes */" >> $1 echo >> $1 for mod in `cat $headers_file | sort`; do add_auto_include $1 $mod.h done echo >> $1 echo >> $1 } function generate_include_all_includes { echo "/* include all optional modules */" >> $1 echo >> $1 echo "#ifdef NDK_ALL" >> $1 echo >> $1 modules=`cat $optional_modules_file | sed 's/*//g' | sort` for mod in $modules; do def="NDK_`strtoupper $mod`" echo "#ifndef $def" >> $1 echo "#define $def 1" >> $1 echo "#endif" >> $1 done echo >> $1 echo "#endif" >> $1 echo >> $1 echo >> $1 } function generate_dependent_includes { echo "/* module dependencies */" >> $1 echo >> $1 cat $module_dependencies_file | while read line; do first=1 for mod in $line; do def="NDK_`strtoupper $mod`" if [ $first = 1 ] ; then echo "#ifdef $def" >> $1 first=0 else echo "#ifndef $def" >> $1 echo "#define $def 1" >> $1 echo "#endif" >> $1 fi done [ $first = 0 ] && echo "#endif" >> $1 done echo >> $1 echo >> $1 } function generate_optional_h_includes { echo "/* optional includes */" >> $1 echo >> $1 for mod in $modules; do def="NDK_`strtoupper $mod`" echo "#if ($def)" >> $1 add_include $1 $mod.h echo "#endif" >> $1 done echo >> $1 echo >> $1 } function generate_conf_merge_macros_file { file=$conf_merge_filename out_file=${file_prefix}$file out=$output_dir/$out_file add_notice $out echo "/* conf-merge-value macros */" >> $out echo >> $out cat $srcs_dir/$file | trim_lines >> $out echo >> $out echo >> $out echo "/* conf-merge-prop macros */" >> $out echo >> $out echo "#define ndk_conf_merge_prop(prop,default)\\" >> $out echo " ndk_conf_merge_value\\" >> $out echo " (conf->prop, prev->prop, default)" >> $out echo >> $out # loads macros, removes empty elements, sorts and translates to merge-prop macros cat $conf_macros_file | sed -r 's/^[A-Z0-9_]+[ ]*[A-Z0-9_]+[ ]*([a-z0-9_]+).*$/\1/;ta;d;:a' \ | sort | sed -r \ 's/(.*)/#define ndk_conf_merge_\1_prop(prop,default,...)\\\ ndk_conf_merge_\1_value\\\ (conf->prop, prev->prop, default,##__VA_ARGS__)\ /' \ >> $out add_auto_include $1 $file } function generate_conf_cmd_basic_file { temp=.rep file=$conf_cmd_basic_filename out_file=${file_prefix}$file out=$output_dir/$out_file align1=35 # initial text add_notice $out # add ndk bitmasks echo "/* conf cmd core values/bitmasks */" >> $out echo >> $out cat $conf_args_file | sort | trim_lines | sed -r \ -e "s/^([A-Z0-9_]+)/${define}NDK_\1${spacer}NGX_\1/" \ -e $sed_delete_empty_lines \ -e "`sed_pad_right $align1 $spacer`" \ >> $out echo >> $out echo >> $out # add additional bitmasks stored in file echo "/* conf cmd bitmasks */" >> $out echo >> $out cat $srcs_dir/$conf_cmd_basic_filename | trim_lines >> $out echo >> $out echo >> $out echo "/* conf cmd basic macros */" >> $out echo >> $out # build replacement string echo -n "s/^([A-Z0-9_]+)$/" > $temp cat $conf_locs_file | sed \ -r -e 's/^([A-Z0-9_]+) *([A-Z0-9_]+).*/#define NDK_\1_CONF_\\1\(name,func,off1,off2,post)\\\\\\\ {ngx_string (name),\\\\\\\ NGX_CONF_\\1|NDK_\1_CONF,\\\\\\\ func, off1, off2, post},\\\ \\/' -e $sed_delete_empty_lines \ >> $temp echo -n "/;$sed_delete_empty_lines" >> $temp # apply the replacement string to the cat $conf_args_file | sort | trim_lines | sed -rf $temp >> $out rm -f $temp add_auto_include $1 $file } function generate_conf_cmd_extra_file { temp=.rep file=$conf_cmd_extra_filename out=$output_dir/${file_prefix}$file align1=35 # initial text add_notice $out echo "/* conf command macros */" >> $out echo >> $out # build replacement string echo -n 's/^([A-Z0-9_]+)[ ]*([A-Z0-9_]+)[ ]*([a-z0-9_]+).*$/' > $temp cat $conf_locs_file | sed \ -r -e 's/^([A-Z0-9_]+)[ ]*([A-Z0-9_]+)[ ]*([a-zA-Z0-9_]+)/#define NDK_\1_CONF_\\1(name,p,post\)\\\\\\\ NDK_\1_CONF_\\2\\\\\\\ (name,\\\\\\\ ndk_conf_set_\\3_slot,\\\\\\\ NGX_\2_CONF_OFFSET,\\\\\\\ offsetof (ndk_module_\3_conf_t, p),\\\\\\\ post)\\\ \\/' -e $sed_delete_empty_lines \ >> $temp echo -n "/;$sed_delete_empty_lines" >> $temp #echo -n ";`sed_pad_right 60 $spacer`" >> $temp # apply the replacement string to the cat $conf_macros_file | sort | trim_lines | sed -rf $temp -e "`sed_pad_right 60 $spacer`" >> $out rm -f $temp add_auto_include $1 $file } function generate_auto_generated_h_includes { echo "/* auto-generated headers */" >> $1 echo >> $1 for name in `cat $header_file | sort` ; do generate_header_file $name add_auto_include $1 $name.h done generate_conf_merge_macros_file $1 generate_conf_cmd_basic_file $1 generate_conf_cmd_extra_file $1 echo >> $1 echo >> $1 } function generate_optional_c_includes { echo "/* optional includes */" >> $1 echo >> $1 modules=`cat $optional_modules_file | sed 's/*//g' | sort` for mod in $modules; do def="NDK_`strtoupper "$mod"`" echo "#if ($def)" >> $1 add_include $1 $mod.c echo "#endif" >> $1 done echo >> $1 echo >> $1 } function generate_commands { echo "/* module commands */" >> $1 echo >> $1 echo "static ngx_command_t ndk_http_commands[] = {" >> $1 cat $optional_modules_file | sort | while read line; do cmds=`echo "$line" | grep -E '\*'` [ "x$cmds" = "x" ] && continue mod=`echo "$line" | grep -E '^[a-zA-Z0-9_]+' | cut -d " " -f1` up=`strtoupper $mod` def="NDK_$up" defcmd="NDK_${up}_CMDS" echo "#if ($def)" >> $1 echo "#define $defcmd 1" >> $1 add_include $1 $mod.h echo "#undef $defcmd" >> $1 echo "#endif" >> $1 done echo -e " ngx_null_command\n};" >> $1 } function generate_all_h_files { out=$output_dir/${file_prefix}$auto_file_name.h add_notice $out generate_include_all_includes $out generate_dependent_includes $out out=$output_dir/${file_prefix}$auto_includes_name.h generate_optional_h_includes $out generate_non_optional_h_includes $out generate_auto_generated_h_includes $out $list } function generate_all_c_files { out=$output_dir/${file_prefix}$auto_file_name.c add_notice $out generate_optional_c_includes $out generate_commands $out } function generate_all_files { mkdir -p $output_dir rm -f $output_dir/* generate_all_h_files generate_all_c_files } generate_all_files debian/modules/nginx-development-kit/auto/src/0000775000000000000000000000000012705233614016632 5ustar debian/modules/nginx-development-kit/auto/src/conf_merge.h0000664000000000000000000001342312705233614021112 0ustar /* TODO : check that all the main types have a corresponding merge function */ #define ndk_conf_merge_value ngx_conf_merge_value #define ndk_conf_merge_off_value ngx_conf_merge_off_value #define ndk_conf_merge_ptr_value ngx_conf_merge_ptr_value #define ndk_conf_merge_str_value ngx_conf_merge_str_value #define ndk_conf_merge_size_value ngx_conf_merge_size_value #define ndk_conf_merge_keyval_value(conf,prev,default) \ \ conf = prev ? prev : default; #define ndk_conf_merge_str_array_value(conf,prev,val1,...) \ \ if (conf == NGX_CONF_UNSET_PTR) { \ if (prev == NGX_CONF_UNSET_PTR) { \ if (val1 == NULL) { \ conf = NULL; \ } else { \ char * elts[] = {val1,##__VA_ARGS__}; \ int n = sizeof(elts)/sizeof(char*); \ \ conf = ndk_str_array_create (cf->pool, elts, n); \ \ if (conf == NULL) \ return NGX_CONF_ERROR; \ } \ } else { \ conf = prev; \ } \ } #define ndk_conf_merge_http_complex_value_value(conf,prev,default) \ \ if (!conf.str.len) { \ if (prev.str.len) { \ conf = prev; \ } else { \ conf.str.data = (u_char *) default; \ conf.str.len = sizeof (default) - 1; \ \ if (ndk_http_complex_value_compile (cf, &conf)) \ return NGX_CONF_ERROR; \ } \ } #define ndk_conf_merge_http_complex_value_array_value(conf,prev,val1,...) \ \ if (conf == NGX_CONF_UNSET_PTR) { \ if (prev == NGX_CONF_UNSET_PTR) { \ if (val1 == NULL) \ conf = NULL; \ else { \ char * elts[] = {val1,##__VA_ARGS__}; \ int n = sizeof(elts)/sizeof(char*); \ \ conf = ndk_http_complex_value_array_create (cf, elts, n); \ \ if (conf == NULL) \ return NGX_CONF_ERROR; \ } \ } else { \ conf = prev; \ } \ } #define ndk_conf_merge_http_complex_path_value(conf,prev,...) \ ndk_conf_merge_http_complex_value_array_value (conf.a, prev.a, __VA_ARGS__) #define ndk_conf_merge_split_path_value(conf,prev,path) \ \ if (conf == NGX_CONF_UNSET_PTR) { \ conf = (prev == NGX_CONF_UNSET_PTR ? \ ndk_split_path_create_raw (cf, path) : prev); \ } debian/modules/nginx-development-kit/auto/src/array.h0000664000000000000000000000101712705233614020120 0ustar #define %2%_array_count(a) ((a)->nelts) #define %2%_array_get_first(a) ((a)->elts) #define %2%_array_get_index(a,n) ((void*) ((char*) (a)->elts + (a)->size * n)) #define %2%_array_get_last(a) ((void*) ((char*) (a)->elts + (a)->size * ((a)->nelts - 1))) #define %2%_array_get_reverse_index(a,n) ((void*) ((char*) (a)->elts + (a)->size * ((a)->nelts - 1 - n))) #define %2%_array_push_clean(p,a) {p = %1%_array_push (a); %2%_zerop (p);} debian/modules/nginx-development-kit/auto/src/palloc.h0000664000000000000000000000051012705233614020251 0ustar #define %2%_pallocp(p,pl) p = %1%_palloc (pl,sizeof(*p)) #define %2%_pallocpn(p,pl,n) p = %1%_palloc (pl,sizeof(*p)*(n)) #define %2%_pcallocp(p,pl) p = %1%_pcalloc (pl,sizeof(*p)) #define %2%_pcallocpn(p,pl,n) p = %1%_pcalloc (pl,sizeof(*p)*(n)) debian/modules/nginx-development-kit/auto/src/conf_cmd_basic.h0000664000000000000000000000462012705233614021716 0ustar /* TODO : finish this */ #define NDK_HTTP_MAIN_CONF NGX_HTTP_MAIN_CONF #define NDK_HTTP_SRV_CONF NGX_HTTP_SRV_CONF #define NDK_HTTP_SIF_CONF NGX_HTTP_SIF_CONF #define NDK_HTTP_LOC_CONF NGX_HTTP_LOC_CONF #define NDK_HTTP_LIF_CONF NGX_HTTP_LIF_CONF #define NDK_HTTP_UPS_CONF NGX_HTTP_UPS_CONF #define NDK_MAIN_CONF NGX_MAIN_CONF #define NDK_ANY_CONF NGX_ANY_CONF /* compound locations */ #define NDK_HTTP_MAIN_SRV_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SRV_CONF #define NDK_HTTP_MAIN_SIF_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SRV_SIF_CONF #define NDK_HTTP_MAIN_LOC_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_LOC_CONF #define NDK_HTTP_MAIN_LIF_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_LOC_LIF_CONF #define NDK_HTTP_SRV_SIF_CONF NDK_HTTP_SRV_CONF|NDK_HTTP_SIF_CONF #define NDK_HTTP_SRV_LOC_CONF NDK_HTTP_SRV_CONF|NDK_HTTP_LOC_CONF #define NDK_HTTP_SRV_LOC_LIF_CONF NDK_HTTP_SRV_CONF|NDK_HTTP_LOC_LIF_CONF #define NDK_HTTP_SRV_SIF_LOC_CONF NDK_HTTP_SRV_SIF_CONF|NDK_HTTP_LOC_CONF #define NDK_HTTP_SRV_SIF_LOC_LIF_CONF NDK_HTTP_SRV_SIF_CONF|NDK_HTTP_LOC_LIF_CONF #define NDK_HTTP_LOC_LIF_CONF NDK_HTTP_LOC_CONF|NDK_HTTP_LIF_CONF #define NDK_HTTP_MAIN_SRV_LOC_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SRV_LOC_CONF #define NDK_HTTP_MAIN_SRV_LIF_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SRV_LIF_CONF #define NDK_HTTP_MAIN_SIF_LOC_CONF NDK_HTTP_MAIN_CONF|NDK_HTTP_SIF_LOC_CONF #define NDK_HTTP_MAIN_SRV_SIF_LOC_LIF_CONF NDK_HTTP_SRV_SIF_LOC_LIF_CONF|NDK_MAIN_CONF #define NDK_HTTP_CONF NDK_HTTP_MAIN_SRV_SIF_LOC_LIF_CONF #define NDK_HTTP_ANY_CONF NDK_HTTP_CONF|NDK_HTTP_UPS_CONF /* property offsets NOTE : ngx_module_main_conf_t etc should be defined in the module's .c file before the commands */ #define NDK_HTTP_MAIN_CONF_PROP(p) NGX_HTTP_MAIN_CONF_OFFSET, offsetof (ndk_module_main_conf_t, p) #define NDK_HTTP_SRV_CONF_PROP(p) NGX_HTTP_SRV_CONF_OFFSET, offsetof (ndk_module_srv_conf_t, p) #define NDK_HTTP_LOC_CONF_PROP(p) NGX_HTTP_LOC_CONF_OFFSET, offsetof (ndk_module_loc_conf_t, p) debian/modules/nginx-development-kit/auto/text/0000775000000000000000000000000012705233614017027 5ustar debian/modules/nginx-development-kit/auto/text/autogen0000664000000000000000000000050012705233614020407 0ustar /* * 2010 (C) Marcus Clyne * * DO NOT EDIT THIS FILE MANUALLY * ------------------------------ * This file has been generated automatically from scripts in the $base/auto dir and * data in the $base/auto/data dir. If you wish to edit the output of this file, then * you should edit these files instead. * */ debian/modules/nginx-development-kit/docs/0000775000000000000000000000000012705233614016023 5ustar debian/modules/nginx-development-kit/docs/upstream/0000775000000000000000000000000012705233614017663 5ustar debian/modules/nginx-development-kit/docs/upstream/list0000664000000000000000000000215212705233614020561 0ustar NDK_UPSTREAM_LIST ----------------- This submodule provides a directive that creates a list of upstreams, with optional weighting. This list can then be used by other modules to hash over the upstreams however they choose. USAGE IN CONF FILE ------------------ e.g. upstream_list name backend1 4:backend2 3:backend3; USAGE WITH OTHER MODULES ------------------------ Add a line like CFLAGS="$CFLAGS -DNDK_UPSTREAM_LIST" to the config file of your module. INTEGRATING WITH YOUR MODULE ---------------------------- The upstream lists are stored in the array given in the lists.h file, which is an array of ndk_upstream_list_t elts. The elts are currently all pointers to strings which have been distributed according to the weight - so if there are two backends, with weight 3 and 4 respectively, there will be 7 pointers in total with the first 3 pointing to the first backend and the last 4 to the second. TODO ---- - replace strings with pointers to upstreams if they are available (and if this is possible) - add additional 'http://' to strings if necessary - improve this documentation debian/modules/nginx-development-kit/docs/patches/0000775000000000000000000000000012705233614017452 5ustar debian/modules/nginx-development-kit/docs/patches/more_logging_info0000664000000000000000000000472012705233614023063 0ustar When tracking down some potential issues in the nginx constellation, we've found it useful to understand where particular error messages are coming from, since many of the same messages are repeated in various places. This patch will write the source file from which the message originated, the function name, and the line number if you're using GCC to compile nginx. Here's an example: Old Output: 2010/01/12 14:43:10 [notice] 67772#0: nginx/0.7.64 2010/01/12 14:43:10 [notice] 67772#0: built by gcc 4.0.1 (Apple Inc. build 5490) 2010/01/12 14:43:10 [notice] 67772#0: OS: Darwin 9.8.0 2010/01/12 14:43:10 [notice] 67772#0: hw.ncpu: 2 2010/01/12 14:43:10 [notice] 67772#0: net.inet.tcp.sendspace: 65536 2010/01/12 14:43:10 [notice] 67772#0: kern.ipc.somaxconn: 128 2010/01/12 14:43:10 [notice] 67772#0: getrlimit(RLIMIT_NOFILE): 256:9223372036854775807 2010/01/12 14:43:10 [notice] 67772#0: start worker processes 2010/01/12 14:43:10 [notice] 67772#0: start worker process 67785 2010/01/12 14:43:16 [notice] 67772#0: signal 20 (SIGCHLD) received New Output: 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_posix_init.c ngx_os_status( 80) nginx/0.7.64 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_posix_init.c ngx_os_status( 83) built by gcc 4.0.1 (Apple Inc. build 5490) 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_darwin_init.c ngx_os_specific_status( 153) OS: Darwin 9.8.0 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_darwin_init.c ngx_os_specific_status( 166) hw.ncpu: 2 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_darwin_init.c ngx_os_specific_status( 166) net.inet.tcp.sendspace: 65536 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_darwin_init.c ngx_os_specific_status( 166) kern.ipc.somaxconn: 128 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_posix_init.c ngx_os_status( 92) getrlimit(RLIMIT_NOFILE): 2560:9223372036854775807 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_process_cycle.c ngx_start_worker_processes( 337) start worker processes 2010/01/14 16:35:09 [notice] 27241#0: src/os/unix/ngx_process.c ngx_spawn_process( 201) start worker process 27254 2010/01/14 16:35:14 [notice] 27241#0: src/os/unix/ngx_process.c ngx_signal_handler( 420) signal 20 (SIGCHLD) received Formatting the filename and function name fields into fixed-width fields would be nicer, however that would require further changes in src/core/ngx_string.c (C) Brian Moran - bmoran@onehub.com (posted to nginx-devel mailing list on 15/01/10) debian/modules/nginx-development-kit/docs/core/0000775000000000000000000000000012705233614016753 5ustar debian/modules/nginx-development-kit/docs/core/action_macros0000664000000000000000000000455312705233614021526 0ustar GENERAL NOTES ------------- These functions and macros have been provided as a tool for Nginx module developers. They have been created with four main purposes: - to speed up code-writing - to reduce the code you have to read on file - to add additional generic functionality similar to exising Nginx functions - to reduce code errors Most of the utility macros are just wrappers around commonly used code, especially checking for NULL and returning a value, zeroing data etc. The functions add things like extra conf_set_X_slot functions that don't exist in the standard Nginx distribution, but which might be useful in more than one module. A consistent approach has been taken to creating the macros, so that in theory you should be able to 'know' the macro name from using the few rules below and your knowledge of the existing Nginx functions. As much as possible, the ordering of variables used within the underlying functions remain the same, to reduce the learning time. Also, a constent naming pattern has been used to make it easier to read the macros above. Obviously not all programmers will want to use all or any of these macros, but they are provided as a tool for those who wish to use them. If you have any comments about them, including any additions or errors please let me know at 'eugaia at gmail dot com'. I don't promise to include all additions people send, but if they seem like they could be of use to multiple developers, I will. UTILITY MACRO PARAMS -------------------- p pointer - used to set the result of a function to a pointer a array pl pool n multiplication factor - for allocating multiple pointers & pushing 'n' elts in arrays etc sz size l log rv return value UTILITY MACRO FUNCTION SUFFIXES ------------------------------- - general p p = [FUNCTION] () _r [ if result of function is NULL | NGX_ERROR (as appropriate) ] return rv _rce rv = NGX_CONF_ERROR _re rv = NGX_ERROR _rn rv = NULL - (p)(c)alloc functions p p = [function] (pool, sizeof (*p)) pn p = [function] (pool, sizeof (*p) * n) UTILITY MACRO PARAMS ORDER -------------------------- p, pl|a, sz|n, l, rv debian/modules/nginx-development-kit/docs/core/conf_cmds0000664000000000000000000000300612705233614020630 0ustar Conf command macros ------------------- The build script generates a large number of macros for reducing the code required for command definitions. There are basically three types of macros : - combination bitmasks e.g. NDK_HTTP_MAIN_SRV_CONF = (NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF) - base command structures e.g. NDK_HTTP_MAIN_CONF_TAKE1 - conf-set command structures e.g. NDK_HTTP_CONF_STR Combination bitmasks -------------------- Basically combinations of existing bitmasks for locations, with general > specific order NDK_HTTP_CONF = (NGX_HTTP_MAIN_CONF | NGX_HTTP_SVR_CONF | NGX_HTTP_SIF_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF) Base command structures ----------------------- These macros are basically there as wrappers for the conf-set command structures, and but incorporate the bitmask element into the name of the macro. Conf-set command structures --------------------------- These macros simplify creating commands that use any of the build-in conf-set functions or any of those added by the NDK. e.g. NGX_HTTP_MAIN_SRV_STR ("name", prop, NULL) where prop is the name of the property that is a ngx_str_t. Whether this is in the loc conf, main conf or svr conf is generated automatically in by the macro. NOTE : you need to set the following if they will be used (using macro definitions) : ndk_module_main_conf_t ndk_module_srv_conf_t ndk_module_loc_conf_t e.g #define ndk_module_loc_conf_t ngx_http_my_module_loc_conf_t TODO ---- Much better documentation for this debian/modules/nginx-development-kit/docs/modules/0000775000000000000000000000000012705233614017473 5ustar debian/modules/nginx-development-kit/docs/modules/set_var0000664000000000000000000001157412705233614021071 0ustar set var tools ============= OVERVIEW -------- This collection of tools is designed to make it easier to set Nginx variables using a common interface. It works by plugging into and extending the features of the internal rewrite module, and operations performed by this module are therefore done at the rewrite phase of handling. ADVANTAGES OF USING THIS MODULE ------------------------------- - simple interface - you don't have to worry about lots of http script compiling - it plugs into the rewrite module, so setting (and getting) vars will happen in the order you expect based on how they appear in the configuration file - you do not have to worry about overriding the v->get_handler (useful if a variable of a specific name could be set in multiple different ways) WHEN TO USE THIS AND WHEN TO USE v->get_handler = my_func --------------------------------------------------------- - if you want a variable to always be generated using a specific function, and should not be over-ridden by 'set' functions (e.g. $request_uri, $document_root), then you should use v->get_handler - if you want to allow a variable to be set using many possible methods, including using the 'set' directive, then this module provides an easy way for you to do so (if you use the v->get_handler method in this case, you may run into problems because the get_handler may over-ride previous uses of the set directive) USAGE ----- - decide on the type of function you'll need to write type use when there are these requirements ---- ------------------------------------- NDK_SET_VAR_BASIC 0 variable values, no extra data NDK_SET_VAR_DATA 0 variable values, extra data NDK_SET_VAR_VALUE 1 variable value, no extra data NDK_SET_VAR_VALUE_DATA 1 variable value, extra data NDK_SET_VAR_MULTI_VALUE 2+ variable values, no extra data NDK_SET_VAR_MULTI_VALUE_DATA 2+ variable values, extra data NDK_SET_VAR_HASH the space needed for the result string value is known in advance (usually used in a hash function) NOTE : if none of these generic calling types suit your needs, it is easy to extend the list of types in the .c file (and you if you let me know I'll add them to the list - define the filter function with the respective prototype type prototype ---- --------- NDK_SET_VAR_BASIC ndk_set_var_pt NDK_SET_VAR_DATA ndk_set_var_data_pt NDK_SET_VAR_VALUE ndk_set_var_value_pt NDK_SET_VAR_DATA_VALUE ndk_set_var_value_data_pt NDK_SET_VAR_MULTI_VALUE ndk_set_var_value_pt NDK_SET_VAR_MULTI_VALUE_DATA ndk_set_var_value_data_pt NDK_SET_VAR_HASH ndk_set_var_hash_pt (See ngx_tools_module.h for the prototype definitions.) Note : For the multi_value functions, the variable value pointer is to the first value (with the others being in an array following it) to use one of the default setup functions ----------------------------------------- - define one or multiple ngx_http_var_filter_t's at the global scope, setting : type = (one of types above) func = function to call size = (for multi value) the number of variable values (for hash) length of buffer to allocate data = (for data functions) additional data (see note below) - define a configuration directive (see in the .c file for examples), where the function is 'ngx_http_set_var' and the 'post' is a pointer your filter definition to setup in a customized way ---------------------------- - define a configuration directive which has your own specific configuration function - inside your config function, define one or several ngx_http_var_filter_t's like above, and call one of the ngx_http_set_var_..._core functions, passing the variable name and value pointers as appropriate - see examples section Note : if you're passing extra data to the function, then you will probably want to use this second method and store the data either in the loc conf, or just allocate the space for it using one of the ngx_palloc functions. If the values that will be used for processing are in the same order as in the config file and there aren't any additional values that are input, then you can just use the (ngx_str_t *) (cf->args->elts) + 1 as your base for the values or possibly not use the _core versions of the functions. That's it! FEEDBACK -------- If you have any comments (good/bad), or have found any bugs, please let me know at: ngx.eugaia AT gmail DOT com TODO ---- - add more documentation/examples debian/modules/nginx-development-kit/config0000664000000000000000000000262412705233614016267 0ustar ############### ## FUNCTIONS ## ############### # TODO : provide information about checking versions of sed etc # TODO : an optional patch function ndk_generate_files() { echo "building Nginx Development Kit utility functions and macros ..." autobuild="$ngx_addon_dir/auto/build" chmod +x $autobuild $autobuild `pwd` $NGX_OBJS/addon/ndk || exit 1 } ndk_get_nginx_version() { # We get the Nginx version number from the string form rather than # nginx_version because it is available in more (every?) version cat src/core/nginx.h | grep '#define NGINX_VERSION' | sed -r \ -e 's/[^0-9.]*([0-9.]+).*/\1/' \ -e 's/([0-9]+\.[0-9]+\.)([0-9]{1})$/\100\2/' \ -e 's/([0-9]+\.[0-9]+\.)([0-9]{2})$/\10\2/' \ -e 's/\.//g' \ -e 's/^0+(.*)/\1/' } ##################### ## CONFIG SETTINGS ## ##################### ngx_addon_name=ngx_devel_kit ngx_objs_dirs="$ngx_addon_dir/objs $NGX_OBJS/addon/ndk" CORE_INCS="$CORE_INCS $ngx_objs_dirs" HTTP_INCS="$HTTP_INCS $ngx_addon_dir/src $ngx_objs_dir" HTTP_MODULES="$HTTP_MODULES ndk_http_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ndk.c" have=NDK . auto/have ############## ## INCLUDES ## ############## . $ngx_addon_dir/ngx_auto_lib_coredebian/modules/nginx-development-kit/patches/0000775000000000000000000000000012705233614016522 5ustar debian/modules/nginx-development-kit/patches/rewrite_phase_handler0000664000000000000000000000120312705233614022777 0ustar diff -p -r a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c *** a/src/http/ngx_http_core_module.c 2010-09-27 12:48:12.000000000 +0100 --- b/src/http/ngx_http_core_module.c 2010-10-09 13:44:09.000000000 +0100 *************** ngx_http_core_rewrite_phase(ngx_http_req *** 910,915 **** --- 910,922 ---- return NGX_AGAIN; } + #if defined(nginx_version) && nginx_version >= 8042 && (NDK_REWRITE_PHASE) + + if (rc == NGX_AGAIN || rc == NGX_DONE) { + return NGX_OK; + } + + #endif /* rc == NGX_OK || rc == NGX_ERROR || rc == NGX_HTTP_... */ ngx_http_finalize_request(r, rc); debian/modules/nginx-development-kit/patches/expose_rewrite_functions0000664000000000000000000001757012705233614023613 0ustar diff -rNp a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c *** a/src/http/modules/ngx_http_rewrite_module.c 2010-06-18 16:15:20.000000000 +0100 --- b/src/http/modules/ngx_http_rewrite_module.c 2010-10-09 14:47:10.000000000 +0100 *************** *** 8,14 **** #include #include ! typedef struct { ngx_array_t *codes; /* uintptr_t */ --- 8,14 ---- #include #include ! #if !(NDK_EXPOSE_REWRITE_FUNCTIONS) typedef struct { ngx_array_t *codes; /* uintptr_t */ *************** typedef struct { *** 17,23 **** ngx_flag_t log; ngx_flag_t uninitialized_variable_warn; } ngx_http_rewrite_loc_conf_t; ! static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, --- 17,23 ---- ngx_flag_t log; ngx_flag_t uninitialized_variable_warn; } ngx_http_rewrite_loc_conf_t; ! #endif static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, *************** static char *ngx_http_rewrite_return(ngx *** 28,44 **** void *conf); static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf); static char *ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); ! static ngx_command_t ngx_http_rewrite_commands[] = { --- 28,47 ---- void *conf); static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + #if !(NDK_EXPOSE_REWRITE_FUNCTIONS) static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf); static char *ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); + #endif static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + #if !(NDK_EXPOSE_REWRITE_FUNCTIONS) static char * ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); ! #endif static ngx_command_t ngx_http_rewrite_commands[] = { *************** ngx_http_rewrite_handler(ngx_http_reques *** 178,185 **** return r->err_status; } ! ! static ngx_int_t ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { --- 181,190 ---- return r->err_status; } ! #if !(NDK_EXPOSE_REWRITE_FUNCTIONS) ! static ! #endif ! ngx_int_t ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { *************** ngx_http_rewrite_break(ngx_conf_t *cf, n *** 511,517 **** } ! static char * ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_rewrite_loc_conf_t *lcf = conf; --- 516,525 ---- } ! #if !(NDK_EXPOSE_REWRITE_FUNCTIONS) ! static ! #endif ! char * ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_rewrite_loc_conf_t *lcf = conf; *************** ngx_http_rewrite_if(ngx_conf_t *cf, ngx_ *** 627,633 **** } ! static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) { u_char *p; --- 635,644 ---- } ! #if !(NDK_EXPOSE_REWRITE_FUNCTIONS) ! static ! #endif ! char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) { u_char *p; *************** ngx_http_rewrite_if_condition(ngx_conf_t *** 847,853 **** } ! static char * ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value) { --- 858,867 ---- } ! #if !(NDK_EXPOSE_REWRITE_FUNCTIONS) ! static ! #endif ! char * ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value) { *************** ngx_http_rewrite_set(ngx_conf_t *cf, ngx *** 948,954 **** } ! static char * ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value) { --- 962,971 ---- } ! #if !(NDK_EXPOSE_REWRITE_FUNCTIONS) ! static ! #endif ! char * ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value) { diff -rNp a/src/http/modules/ngx_http_rewrite_module.h b/src/http/modules/ngx_http_rewrite_module.h *** a/src/http/modules/ngx_http_rewrite_module.h 1970-01-01 01:00:00.000000000 +0100 --- b/src/http/modules/ngx_http_rewrite_module.h 2010-10-09 14:38:04.000000000 +0100 *************** *** 0 **** --- 1,47 ---- + + /* + * Copyright (C) Marcus Clyne + * + * Note : this file has been created by the Nginx Development Kit using + * some code from ngx_http_rewrite_module.c + */ + + #if (NDK_EXPOSE_REWRITE_FUNCTIONS) + + #ifndef _NGX_HTTP_REWRITE_H_INCLUDED_ + #define _NGX_HTTP_REWRITE_H_INCLUDED_ + + #include + #include + #include + + + extern ngx_module_t ngx_http_rewrite_module; + + + typedef struct { + ngx_array_t *codes; /* uintptr_t */ + + ngx_uint_t stack_size; + + ngx_flag_t log; + ngx_flag_t uninitialized_variable_warn; + } ngx_http_rewrite_loc_conf_t; + + + char * + ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + char * + ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf); + char * + ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, + ngx_str_t *value); + char * + ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, + ngx_str_t *value); + ngx_int_t + ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data); + + #endif + #endif diff -rNp a/src/http/ngx_http.h b/src/http/ngx_http.h *** a/src/http/ngx_http.h 2010-06-15 16:13:34.000000000 +0100 --- b/src/http/ngx_http.h 2010-10-09 14:25:56.000000000 +0100 *************** typedef u_char *(*ngx_http_log_handler_p *** 43,48 **** --- 43,52 ---- #include #endif + #if (NDK_EXPOSE_REWRITE_FUNCTIONS) + #include + #endif + struct ngx_http_log_ctx_s { ngx_connection_t *connection; diff -rNp a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c *** a/src/http/ngx_http_script.c 2010-09-13 13:44:43.000000000 +0100 --- b/src/http/ngx_http_script.c 2010-10-09 14:36:10.000000000 +0100 *************** static size_t ngx_http_script_full_name_ *** 26,35 **** --- 26,43 ---- static void ngx_http_script_full_name_code(ngx_http_script_engine_t *e); + #if (NDK_EXPOSE_REWRITE_FUNCTIONS) + + uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL; + + #else + #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL; + #endif + void ngx_http_script_flush_complex_value(ngx_http_request_t *r, diff -rNp a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h *** a/src/http/ngx_http_script.h 2010-09-13 13:44:43.000000000 +0100 --- b/src/http/ngx_http_script.h 2010-10-09 14:33:40.000000000 +0100 *************** *** 12,17 **** --- 12,25 ---- #include #include + #if (NDK_EXPOSE_REWRITE_FUNCTIONS) + + #define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code + + extern uintptr_t ngx_http_script_exit_code; + + #endif + typedef struct { u_char *ip; debian/modules/nginx-development-kit/patches/auto_config0000664000000000000000000000077712705233614020755 0ustar diff -pNr a/src/core/ngx_config.h b/src/core/ngx_config.h *** a/src/core/ngx_config.h 2008-09-19 13:47:13.000000000 +0100 --- b/src/core/ngx_config.h 2010-10-09 17:14:13.000000000 +0100 *************** typedef intptr_t ngx_flag_t; *** 127,131 **** #define NGX_MAX_UINT32_VALUE (uint32_t) 0xffffffff #endif ! #endif /* _NGX_CONFIG_H_INCLUDED_ */ --- 127,131 ---- #define NGX_MAX_UINT32_VALUE (uint32_t) 0xffffffff #endif ! #include #endif /* _NGX_CONFIG_H_INCLUDED_ */ debian/modules/nginx-development-kit/README_AUTO_LIB0000664000000000000000000004207612705233614017302 0ustar Nginx Auto Lib Core =================== Nginx Auto Lib Core is a generic external library-handler that has been designed to facilitate the inclusion of external libraries in modules for the Nginx web server. It has been written both for the benefit of Nginx module developers and for the end users of those Nginx modules, and can provide a consistent, intelligent, flexible cross-platform way to include external libraries. Any developers of Nginx modules are encouraged to use Auto Lib Core to handle library dependencies for their modules rather than writing their own custom handler from scratch. Note : the latest version can be found at github.com/simpl/ngx_auto_lib Information for end users ========================= To include external libraries using Auto Lib to you may need or wish to export some variables before you run configure. e.g. $ export MOZJS=/path/to/mozjs $ export MOZJS_SHARED=NO $ ./configure ... In all cases below [PFX] should be replaced with the name of the library (e.g. MOZJS). The specific value for [PFX] should be mentioned in the README file for the module that uses Auto Lib Core. Search order for paths ---------------------- (1) [PFX]_INC and [PFX]_LIB (2) [PFX] (source or install dir) (3) any dirs under [PFX]_BASE (see below) (4) any dirs under the parent directory of the Nginx source dir beginning with '[pfx]-' (5) standard system paths (including /usr/local, /usr, /opt/local, /opt, /usr/pkg) If any of 1-3 are specified, then any set values will be searched, and the the Nginx source's parent directory and system paths are not searched unless [PFX]_SEARCH_[PLACE] variable is set to YES, where PLACE ::= PARENT | SYSTEM. e.g. $ export OPENSSL_LIB=/path/to/openssl/lib $ export OPENSSL_INC=/path/to/openssl/inc $ ./configure will search only in the lib and include paths specified, and $ export OPENSSL_LIB=/path/to/openssl/lib $ export OPENSSL_INC=/path/to/openssl/inc $ export OPENSSL_BASE=/path/to/openssl/base $ export OPENSSL_SEARCH_PARENT=YES $ ./configure --with-openssl=/path/to/openssl will search first in the lib & inc dirs specified, then in /path/to/openssl, then will look for directories in /path/to/openssl/base and then in the Nginx source parent directory, but will skip checking the system paths. Note : apart from system paths, all dirs are checked as both source and install directories, so static versions of installed OpenSSL, PCRE, Zlib etc libraries can be used with Nginx if desired. Specifying a path to find a library ----------------------------------- If the version of a library you wish to include is in any of the standard paths (e.g. /usr/local, /usr ...), you will not need to specify a path to include the library. If you do wish to specify a specific path, in most cases just specifying [PFX]=/path/to/library will be sufficient. e.g. $ export MOZJS=/path/to/mozjs $ ./configure ... The path can be either a source directory or an install directory. Auto Lib will search Searching under base paths -------------------------- Rather than specifying a specific path to find new libraries in non-standard locations, you may wish to specify a base path (or just let Auto Lib search the directory that the Nginx source is located in). This will then automatically find the most recent versions of libraries and check them before older versions. e.g. You have installations /openssl/version/0.9.8m /openssl/version/1.0.0a ... $ export OPENSSL_BASE=/openssl/version $ ./configure ... Any directories under /openssl/version will be searched IN REVERSE ORDER, i.e. most recent version first. Here /openssl/version/1.0.0a would be searched before /openssl/version/0.9.8m. If [PFX]_BASE_SEARCH_PREFIX=YES, then only directories beginning with '[pfx]-' are searched. If [PFX]_BASE_SEARCH_PREFIX=something, then only directories beginning with 'something' are searched. When searching under [PFX]_BASE no prefix is added to the search, but when searching under the directory that the Nginx source is located in, the prefix [pfx]- is automatically added. Note : there is currently a minor bug (due to the implementation of the 'sort' command) means versions that include hyphens (e.g. 1.0.0-beta5) are checked before versions like 1.0.0a. This will be fixed soon, and searching of -build folders before normal source ones will be added too. Shared or static? ----------------- The default for most libraries is to look for shared libraries, though this can be overridden by the user by setting [PFX]_SHARED=NO. In the near future the default action will be to look for shared libraries then to look for static libraries in each directory searched unless one of [PFX]_SHARED and/or [PFX]_STATIC = NO. If both are set to NO, then Auto Lib will not be used at all. Variables that users can set to help find libraries --------------------------------------------------- [PFX] Location of dir where the library can be found (PATH, see below) [PFX]_INC Include dir for library headers (PATH) [PFX]_LIB Lib dir for library archive/shared objects (PATH) [PFX]_BASE Base dir under which to search for other dirs (PATH) [PFX]_SEARCH_LIB_INC Search in [PFX]_INC and [PFX]_LIB if set (YES|NO, def=YES) [PFX]_SEARCH_DIR Search [PFX] if set (YES|NO, def=YES) [PFX]_SEARCH_BASE Search under [PFX]_BASE if set (YES|NO, def=YES) [PFX]_SEARCH_PARENT Search under the dir that the Nginx source is in (YES|NO, see above) [PFX]_SEARCH_SYSTEM Search in standard system paths (YES|NO, see above) [PFX]_SHARED Use shared library rather than static (YES|NO, def=YES) [PFX]_SYSTEM_DIRS System dirs to search in (PATHS, space-separated, overrides the defaults) USE_[PFX] Whether or not to install the library (YES|NO, def=YES) Note : for libraries that have configure options (e.g. --with-openssl=/path), the [PFX] variable is set automatically by configure, so will not be used if exported. Information for module developers ================================= How Auto Lib Core works ----------------------- Auto Lib Core works as an interface layer between the module and the auto/feature part of the Nginx source. This is the file that results in the 'checking for ...' lines that you see when you call ./configure. auto/feature works by using a few key variables (see below) to generate some C code, trying to compile it to see if it works and optionally running the code. This output file is called autotest.c (located under the objs/ directory whilst configure is running, but is deleted after each call to auto/feature). Normally, whenever an external library is required, a module developer will write a number of calls to auto/feature manually in their config files - e.g. to check under a range of different possible locations to find a library. Apart from being tedious, this is obviously potentially error-prone. Auto Lib Core will automatically generate all the calls to auto/feature for you, and will take into account different operating systems etc in a consistent way, 'intelligent' way. Including Nginx Auto Lib Core with custom modules ------------------------------------------------- Option 1 : - include ngx_auto_lib_core in the same directory that your module config file is located - add the following line to your config file . $ngx_addon_dir/ngx_auto_lib_core NOTE : if you want to include the file in a different directory to your config file, you will need to change both the include line in your config file AND the line in the ngx_auto_lib_core file that points to the file (it's the line that has $ngx_addon_dir/ngx_auto_lib_core in it) Option 2 : - make the Nginx Development Kit (github.com/simpl-it/ngx_devel_kit) a dependency for your module (Auto Lib Core is included automatically with it) Recommended way of including Auto Lib Core ------------------------------------------ If the Nginx Development Kit (NDK) is already a dependency for your module, then you do not need to do anything - just follow the 'using Auto Lib Core' instructions below. If the NDK is not a dependency for your module, then it is recommended to include a copy of ngx_auto_lib_core with your module, but to recommend to users of your module to include the NDK when compiling. If the module is not required for anything else, this will not make any difference to the Nginx binary that they compile, but will mean they will get the latest version of Auto Lib Core (which probably won't change much anyway, but you never know). You will also probably want to include a copy of this readme file for Auto Lib Core (at least the user section), and mention what the relevant [PFX] you use for your module is in your module's readme file so that users will know what to write for any variables that they might use to control the search paths for libraries (see above user section). Using Auto Lib Core ------------------- To use Auto Lib Core, you should do the following in your config file for each external library that you want to include : 1 - Call ngx_auto_lib_init 2 - Define any variables used for testing 3 - Define any hooks (custom functions) 4 - Call ngx_auto_lib_run Calling ngx_auto_lib_init() and ngx_auto_lib_run() -------------------------------------------------- You can pass either one or two variables to ngx_auto_lib_init(). The first is the name of the library as it will appear when running ./configure, the second is the prefix that is used for internal variables and looking for directory prefixes. If the second is not specified, it defaults to the first. The init function resets all key variables and functions, so it must be called before setting any other variables or functions that are to be used as hooks (see the notes below). ngx_auto_lib_run() should be called in the config files after all the variables and hooks have been defined. This will then run through all the tests to try to find the external library. Variables you can set in your config files ------------------------------------------ All the variables that you set in Auto Lib Core are similar to the ones you set for including libraries in the normal way. name description ---------------------------------------------------------------------------------------- core variables (i.e. the ones in the core Nginx source) ngx_feature_inc_path CFLAGS and include path info (including -I) ngx_feature_incs Include/define code inserted before main() in autotest.c ngx_feature_libs External libraries to add (see below) ngx_feature_path Space-separated include path ngx_feature_run Whether to run the autotest binary (default = no) ngx_feature_test C-code inserted inside main() in autotest.c extended variables (only work in NALC) : ngx_feature_add_libs Add libraries (but do not add include files) ngx_feature_add_path Add extra directories to include path ngx_feature_build_dirs Sub dirs that builds might be found ngx_feature_build_inc_dirs Sub dirs that include files might be found ngx_feature_build_lib_dirs Sub dirs that lib files might be found ngx_feature_check_macros_defined Lib required only if one of these macros is defined ngx_feature_check_macros_non_zero Lib required only if one of these macros is non-zero ngx_feature_defines Define these macros if the library is found ngx_feature_deps Deps to add (e.g. to CORE_DEPS) if the library is found ngx_feature_exit_if_not_found Quit configure if the library is not found ngx_feature_haves Set these macros to 1 if the library is found ngx_feature_inc_names Names for include files (not including the .h) ngx_feature_lib_files Add these files under the lib dir for static inclusions ngx_feature_lib_names Names for lib files (not including -l or .a) ngx_feature_modules Modules to add if the library is found ngx_feature_srcs Sources to add (e.g. to ADDON_SRCS) if the lib is found ngx_feature_shared If set to 'no', then only use static lib versions ngx_feature_test_libs Add these libs when testing, but not to the final binary ngx_feature_variables Set these variables if the library is found standard variables that are completely over-written (i.e. they won't work with NALC) : ngx_feature_name Message that is displayed after 'checking for' in configure Using these variables --------------------- You do not need to set most of these variables, since 'intelligent' guesses are made that will work for most cases. With the exception of ngx_feature_test, you should generally use the extended variables rather than the core ones, since sensible core variables will be automatically generated from them, and will work for both static and shared libraries. Variable defaults ----------------- ngx_feature_incs for i in $ngx_feature_inc_names { #include <$i.h> } ngx_feature_libs for l in $ngx_feature_lib_names { -l$l or $LIB/lib$l.a } + $ngx_feature_add_libs ngx_feature_inc_names $ngx_feature_lib_names ngx_feature_lib_names $pfx pfx str_to_lower (if two variables are passed to ngx_auto_lib_init, then then $2, otherwise, $1) The easiest way to understand how all the defaults work is probably to look at the source code of ngx_auto_lib_test_setup() and to look at the examples in the standard Nginx Auto Lib module which has code for OpenSSL, PCRE, Zlib, MD5 and SHA1. Hooks ----- To facilitate using Auto Lib Core in a flexible way, a number of 'hooks' have been placed in the testing cycle. These hooks are implemented as functions that you define in your config file which are called if required by the core library. In the core library they are left as empty functions that return either 0 or 1. Any functions you write will Note : ngx_auto_lib_init() resets the variables and functions each time it is called, so you must DEFINE HOOKS AFTER YOU CALL ngx_auto_lib_init. Note : an update on what hooks are available will be added later. To see what hooks are available, just look in the source code of ngx_auto_lib_core for any functions that just return 0 or 1. See the MD5 and SHA1 libraries of Nginx Auto Lib module for examples. Checking that a library is required ----------------------------------- Although in most cases Auto Lib Core will be used where external libraries are definitely required (for a module to work), this may not always be the case. In the standard Nginx Auto Lib module (github.com/simpl-it/ngx_auto_lib) - which is designed to improve the inclusion of OpenSSL, PCRE and Zlib libraries and increase compilation speed where possible - the libraries are not always required, so checks are made to see if it is necessary. How Auto Lib Core checks if a library is required - ngx_auto_lib_check_require() ------------------------------------------------------------------------------------ - search for USE_[PFX]=YES (it is set to YES by default for most modules) - search for any external libraries that have been included in the CORE_LIBS or ADDON_LIBS variables that use the same lib name as any set in ngx_feature_lib_names - search for any macros that have been defined either in the CFLAGS variable or using auto/have or auto/define as set in the ngx_feature_check_macros_defined and ngx_feature_ngx_macros_non_zero variables - any custom checks implemented by creating an ngx_auto_lib_check hook function (which should return 0 if the library is required and return 1 at the end if the module is not required) Guaranteeing that the correct version of a shared library is linked at run time ------------------------------------------------------------------------------- Sometimes users will want to use shared libraries that are in non-standard locations that the linker may have a problem in locating at run time - even if the correct linker path (-L/path/to/lib) is supplied when checking. To make sure that the linker can find the library at run time, and to make sure that the linker will use the correct version of a library if the library is also located in a standard directory, a run path is added to the linker flags (using -Wl,--rpath -Wl,/path/to/lib/dir). In most cases this will guarantee that the correct library is used when linking - though care should be taken by any users specifying specific paths for libraries that the correct version of the library has been linked at run time (e.g. using ldd etc). As an additional check when running auto/feature, as well as the compilation of the autotest.c file, a check is made by ldd to see that the path of the shared library that the linker links to is the same as the one specified. This is done because To do ----- - change how library paths are searched to include both shared and static libraries - touch up documentation License ------- BSD Copyright --------- Marcus Clyne (c) 2010 (http://simpl.it) debian/modules/nginx-development-kit/TODO0000664000000000000000000000006212705233614015561 0ustar - for backward compatability, add the ndk_macros debian/modules/nginx-development-kit/src/0000775000000000000000000000000012705233614015662 5ustar debian/modules/nginx-development-kit/src/ndk_regex.c0000664000000000000000000001103212705233614017771 0ustar char * ndk_conf_set_regex_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *value; ngx_conf_post_t *post; ngx_regex_elt_t *re; ngx_regex_compile_t rc; u_char errstr[NGX_MAX_CONF_ERRSTR]; re = (ngx_regex_elt_t *) (p + cmd->offset); if (re->name) { return "is duplicate"; } value = cf->args->elts; value++; ndk_zerov (rc); rc.pool = cf->pool; rc.err.len = NGX_MAX_CONF_ERRSTR; rc.err.data = errstr; rc.pattern = *value; if (ngx_regex_compile(&rc) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); return NGX_CONF_ERROR; } re->regex = rc.regex; re->name = value->data; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, re); } return NGX_CONF_OK; } char * ndk_conf_set_regex_caseless_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *value; ngx_conf_post_t *post; ngx_regex_elt_t *re; ngx_regex_compile_t rc; u_char errstr[NGX_MAX_CONF_ERRSTR]; re = (ngx_regex_elt_t *) (p + cmd->offset); if (re->name) { return "is duplicate"; } value = cf->args->elts; value++; ndk_zerov (rc); rc.pool = cf->pool; rc.err.len = NGX_MAX_CONF_ERRSTR; rc.err.data = errstr; rc.pattern = *value; rc.options = NGX_REGEX_CASELESS; if (ngx_regex_compile(&rc) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); return NGX_CONF_ERROR; } re->regex = rc.regex; re->name = value->data; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, re); } return NGX_CONF_OK; } char * ndk_conf_set_regex_array_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *value; ngx_conf_post_t *post; ngx_array_t **a; ngx_regex_elt_t *re; ngx_regex_compile_t rc; ngx_uint_t i, n; u_char errstr[NGX_MAX_CONF_ERRSTR]; a = (ngx_array_t **) (p + cmd->offset); if (*a != NGX_CONF_UNSET_PTR) { n = cf->args->nelts > 4 ? cf->args->nelts : 4; *a = ngx_array_create (cf->pool, n, sizeof (ngx_regex_elt_t)); if (*a == NULL) { return NGX_CONF_ERROR; } } ndk_zerov (rc); rc.pool = cf->pool; rc.err.len = NGX_MAX_CONF_ERRSTR; rc.err.data = errstr; value = cf->args->elts; value++; for (i=0; iregex = rc.regex; re->name = value->data; } if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, a); } return NGX_CONF_OK; } char * ndk_conf_set_regex_array_caseless_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *value; ngx_conf_post_t *post; ngx_array_t **a; ngx_regex_elt_t *re; ngx_regex_compile_t rc; ngx_uint_t i, n; u_char errstr[NGX_MAX_CONF_ERRSTR]; a = (ngx_array_t **) (p + cmd->offset); if (*a != NGX_CONF_UNSET_PTR) { n = cf->args->nelts > 4 ? cf->args->nelts : 4; *a = ngx_array_create (cf->pool, n, sizeof (ngx_regex_elt_t)); if (*a == NULL) { return NGX_CONF_ERROR; } } ndk_zerov (rc); rc.pool = cf->pool; rc.err.len = NGX_MAX_CONF_ERRSTR; rc.err.data = errstr; value = cf->args->elts; value++; for (i=0; iregex = rc.regex; re->name = value->data; } if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, a); } return NGX_CONF_OK; } debian/modules/nginx-development-kit/src/ndk_complex_value.c0000664000000000000000000001002612705233614021524 0ustar ngx_int_t ndk_http_complex_value_compile (ngx_conf_t *cf, ngx_http_complex_value_t *cv, ngx_str_t *value) { ngx_http_compile_complex_value_t ccv; ngx_memzero (&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = value; ccv.complex_value = cv; return ngx_http_compile_complex_value (&ccv); } ngx_array_t * ndk_http_complex_value_array_create (ngx_conf_t *cf, char **s, ngx_int_t n) { ngx_int_t i; ngx_http_complex_value_t *cv; ngx_array_t *a; ngx_str_t value; a = ngx_array_create (cf->pool, n, sizeof (ngx_http_complex_value_t)); if (a == NULL) return NULL; for (i=0; ielts; for (i=0; inelts; i++, cv++) { if (ndk_http_complex_value_compile (cf, cv, &cv->value)) return NGX_ERROR; } return NGX_OK; } char * ndk_conf_set_http_complex_value_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_http_complex_value_t *cv; ngx_str_t *value; ngx_conf_post_t *post; cv = (ngx_http_complex_value_t *) (p + cmd->offset); if (cv->value.data) { return "is duplicate"; } value = cf->args->elts; if (ndk_http_complex_value_compile (cf, cv, value + 1)) return NGX_CONF_ERROR; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, cv); } return NGX_CONF_OK; } char * ndk_conf_set_http_complex_value_array_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *value; ngx_http_complex_value_t *cv; ngx_array_t **a; ngx_conf_post_t *post; ngx_int_t i, alloc; a = (ngx_array_t **) (p + cmd->offset); if (*a == NULL || *a == NGX_CONF_UNSET_PTR) { alloc = cf->args->nelts > 4 ? cf->args->nelts : 4; *a = ngx_array_create (cf->pool, alloc, sizeof (ngx_http_complex_value_t)); if (*a == NULL) { return NGX_CONF_ERROR; } } value = cf->args->elts; for (i=1; iargs->nelts; i++) { cv = ngx_array_push (*a); if (cv == NULL) { return NGX_CONF_ERROR; } if (ndk_http_complex_value_compile (cf, cv, &value[i]) == NGX_ERROR) return NGX_CONF_ERROR; } if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, a); } return NGX_CONF_OK; } char * ndk_conf_set_http_complex_keyval_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *value; ndk_http_complex_keyval_t *ckv; ngx_array_t **a; ngx_conf_post_t *post; ngx_int_t alloc; a = (ngx_array_t **) (p + cmd->offset); if (*a == NULL || *a == NGX_CONF_UNSET_PTR) { alloc = cf->args->nelts > 4 ? cf->args->nelts : 4; *a = ngx_array_create (cf->pool, alloc, sizeof (ndk_http_complex_keyval_t)); if (*a == NULL) { return NGX_CONF_ERROR; } } ckv = ngx_array_push (*a); if (ckv == NULL) { return NGX_CONF_ERROR; } value = cf->args->elts; ckv->key = value[1]; if (ndk_http_complex_value_compile (cf, &ckv->value, &value[2]) == NGX_ERROR) return NGX_CONF_ERROR; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, a); } return NGX_CONF_OK; } /* TODO : complex keyval1 */ debian/modules/nginx-development-kit/src/ndk_buf.c0000664000000000000000000000146612705233614017445 0ustar ngx_int_t ndk_copy_chain_to_str (ngx_pool_t *pool, ngx_chain_t *in, ngx_str_t *str) { ngx_chain_t *cl; size_t len; u_char *p; ngx_buf_t *b; len = 0; for (cl = in; cl; cl = cl->next) len += ngx_buf_size (cl->buf); ndk_palloc_re (p, pool, len + 1); str->data = p; str->len = len; for (cl = in; cl; cl = cl->next) { b = cl->buf; if (ngx_buf_in_memory (b)) { p = ngx_cpymem (p, b->pos, b->last - b->pos); } } *p = '\0'; return NGX_OK; } char * ndk_copy_chain_to_charp (ngx_pool_t *pool, ngx_chain_t *in) { ngx_str_t str; if (ndk_copy_chain_to_str (pool, in, &str) != NGX_OK) return NULL; return (char *) str.data; }debian/modules/nginx-development-kit/src/hash/0000775000000000000000000000000012705233614016605 5ustar debian/modules/nginx-development-kit/src/hash/sha.h0000664000000000000000000001620312705233614017533 0ustar /* crypto/sha/sha.h */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #ifndef HEADER_SHA_H #define HEADER_SHA_H #include #include #ifdef __cplusplus extern "C" { #endif #if defined(OPENSSL_NO_SHA) || (defined(OPENSSL_NO_SHA0) && defined(OPENSSL_NO_SHA1)) #error SHA is disabled. #endif #if defined(OPENSSL_FIPS) #define FIPS_SHA_SIZE_T size_t #endif /* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! * ! SHA_LONG_LOG2 has to be defined along. ! * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ #if defined(__LP32__) #define SHA_LONG unsigned long #elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) #define SHA_LONG unsigned long #define SHA_LONG_LOG2 3 #else #define SHA_LONG unsigned int #endif #define SHA_LBLOCK 16 #define SHA_CBLOCK (SHA_LBLOCK*4) /* SHA treats input data as a * contiguous array of 32 bit * wide big-endian values. */ #define SHA_LAST_BLOCK (SHA_CBLOCK-8) #define SHA_DIGEST_LENGTH 20 typedef struct SHAstate_st { SHA_LONG h0,h1,h2,h3,h4; SHA_LONG Nl,Nh; SHA_LONG data[SHA_LBLOCK]; unsigned int num; } SHA_CTX; #ifndef OPENSSL_NO_SHA0 int SHA_Init(SHA_CTX *c); int SHA_Update(SHA_CTX *c, const void *data, size_t len); int SHA_Final(unsigned char *md, SHA_CTX *c); unsigned char *SHA(const unsigned char *d, size_t n, unsigned char *md); void SHA_Transform(SHA_CTX *c, const unsigned char *data); #endif #ifndef OPENSSL_NO_SHA1 int SHA1_Init(SHA_CTX *c); int SHA1_Update(SHA_CTX *c, const void *data, size_t len); int SHA1_Final(unsigned char *md, SHA_CTX *c); unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md); void SHA1_Transform(SHA_CTX *c, const unsigned char *data); #endif #define SHA256_CBLOCK (SHA_LBLOCK*4) /* SHA-256 treats input data as a * contiguous array of 32 bit * wide big-endian values. */ #define SHA224_DIGEST_LENGTH 28 #define SHA256_DIGEST_LENGTH 32 typedef struct SHA256state_st { SHA_LONG h[8]; SHA_LONG Nl,Nh; SHA_LONG data[SHA_LBLOCK]; unsigned int num,md_len; } SHA256_CTX; #ifndef OPENSSL_NO_SHA256 int SHA224_Init(SHA256_CTX *c); int SHA224_Update(SHA256_CTX *c, const void *data, size_t len); int SHA224_Final(unsigned char *md, SHA256_CTX *c); unsigned char *SHA224(const unsigned char *d, size_t n,unsigned char *md); int SHA256_Init(SHA256_CTX *c); int SHA256_Update(SHA256_CTX *c, const void *data, size_t len); int SHA256_Final(unsigned char *md, SHA256_CTX *c); unsigned char *SHA256(const unsigned char *d, size_t n,unsigned char *md); void SHA256_Transform(SHA256_CTX *c, const unsigned char *data); #endif #define SHA384_DIGEST_LENGTH 48 #define SHA512_DIGEST_LENGTH 64 #ifndef OPENSSL_NO_SHA512 /* * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 * being exactly 64-bit wide. See Implementation Notes in sha512.c * for further details. */ #define SHA512_CBLOCK (SHA_LBLOCK*8) /* SHA-512 treats input data as a * contiguous array of 64 bit * wide big-endian values. */ #if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) #define SHA_LONG64 unsigned __int64 #define U64(C) C##UI64 #elif defined(__arch64__) #define SHA_LONG64 unsigned long #define U64(C) C##UL #else #define SHA_LONG64 unsigned long long #define U64(C) C##ULL #endif typedef struct SHA512state_st { SHA_LONG64 h[8]; SHA_LONG64 Nl,Nh; union { SHA_LONG64 d[SHA_LBLOCK]; unsigned char p[SHA512_CBLOCK]; } u; unsigned int num,md_len; } SHA512_CTX; #endif #ifndef OPENSSL_NO_SHA512 int SHA384_Init(SHA512_CTX *c); int SHA384_Update(SHA512_CTX *c, const void *data, size_t len); int SHA384_Final(unsigned char *md, SHA512_CTX *c); unsigned char *SHA384(const unsigned char *d, size_t n,unsigned char *md); int SHA512_Init(SHA512_CTX *c); int SHA512_Update(SHA512_CTX *c, const void *data, size_t len); int SHA512_Final(unsigned char *md, SHA512_CTX *c); unsigned char *SHA512(const unsigned char *d, size_t n,unsigned char *md); void SHA512_Transform(SHA512_CTX *c, const unsigned char *data); #endif #ifdef __cplusplus } #endif #endif debian/modules/nginx-development-kit/src/hash/murmurhash2.c0000664000000000000000000000271212705233614021230 0ustar #ifndef MURMURHASH2_C #define MURMURHASH2_C #define MURMURHASH2_DIGEST_LENGTH 4 /* * ----------------------------------------------------------------------------- * MurmurHash2, by Austin Appleby * Note - This code makes a few assumptions about how your machine behaves - * 1. We can read a 4-byte value from any address without crashing * 2. sizeof(int) == 4 * And it has a few limitations - * 1. It will not work incrementally. * 2. It will not produce the same results on little-endian and big-endian * machines. */ unsigned int MurmurHash2 ( const void * key, int len, unsigned int seed ) { /* * 'm' and 'r' are mixing constants generated offline. * They're not really 'magic', they just happen to work well. */ const unsigned int m = 0x5bd1e995; const int r = 24; /* Initialize the hash to a 'random' value */ unsigned int h = seed ^ len; /* Mix 4 bytes at a time into the hash */ const unsigned char * data = (const unsigned char *)key; while(len >= 4) { unsigned int k = *(unsigned int *)data; k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; data += 4; len -= 4; } /* Handle the last few bytes of the input array */ switch(len) { case 3: h ^= data[2] << 16; case 2: h ^= data[1] << 8; case 1: h ^= data[0]; h *= m; }; /* Do a few final mixes of the hash to ensure the last few * bytes are well-incorporated. */ h ^= h >> 13; h *= m; h ^= h >> 15; return h; } #endif debian/modules/nginx-development-kit/src/hash/md5.h0000664000000000000000000001102712705233614017444 0ustar /* crypto/md5/md5.h */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ #ifndef HEADER_MD5_H #define HEADER_MD5_H #include #include #ifdef __cplusplus extern "C" { #endif #ifdef OPENSSL_NO_MD5 #error MD5 is disabled. #endif /* * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then ! * ! MD5_LONG_LOG2 has to be defined along. ! * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ #if defined(__LP32__) #define MD5_LONG unsigned long #elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) #define MD5_LONG unsigned long #define MD5_LONG_LOG2 3 /* * _CRAY note. I could declare short, but I have no idea what impact * does it have on performance on none-T3E machines. I could declare * int, but at least on C90 sizeof(int) can be chosen at compile time. * So I've chosen long... * */ #else #define MD5_LONG unsigned int #endif #define MD5_CBLOCK 64 #define MD5_LBLOCK (MD5_CBLOCK/4) #define MD5_DIGEST_LENGTH 16 typedef struct MD5state_st { MD5_LONG A,B,C,D; MD5_LONG Nl,Nh; MD5_LONG data[MD5_LBLOCK]; unsigned int num; } MD5_CTX; int MD5_Init(MD5_CTX *c); int MD5_Update(MD5_CTX *c, const void *data, size_t len); int MD5_Final(unsigned char *md, MD5_CTX *c); unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md); void MD5_Transform(MD5_CTX *c, const unsigned char *b); #ifdef __cplusplus } #endif #endif debian/modules/nginx-development-kit/src/ndk_path.c0000664000000000000000000002615712705233614017631 0ustar /* This function cleans a path to its most basic form, performing the following transformations : * * - ./ -> [empty] * - // -> / * - /base/parent/../ -> /base/ * * If possible, it leaves the original string in place and does not copy characters, otherwise * characters are copied. */ void ndk_clean_path (ngx_str_t *path, ngx_uint_t complex, size_t off) { u_char *s, *p, *m, *e, c, *l; ngx_uint_t root; if (path->len == 1) { if (path->data[0] == '.') { path->len = 0; } return; } /* strip initial './' */ s = path->data; e = s + path->len; if (off) { p = s + off; goto check_basic; } if (*s == '/') root = 1; else root = 0; while (s < e) { switch (*s) { case '/' : /* '//' => '/' */ s++; continue; case '.' : if (s == e-1) { if (root) { path->data[0] = '/'; path->len = 1; } else { path->len = 0; } return; } /* './' => '' */ if (s[1] == '/') { s += 2; if (s == e) { path->len = 0; return; } continue; } } break; } if (root && *s != '/') { s--; } p = s; check_basic : for ( ; p '/' */ m = p + 2; goto copy; case '.' : if (e - p == 2) break; switch (p[2]) { case '/' : /* './' => '' */ m = p + 2; goto copy; case '.' : if (e - p == 3 || p[3] == '/') { if (p == s) { s += 3; continue; } if (p - s >= 2) { if (p[-1] == '.' && p[-2] == '.') { if (p - s == 2 || p[-3] == '/') { /* = '../../' */ p += 2; /* 3? */ continue; } } } m = p + 4; if (complex) { for (p--; p >= s; p--) { switch (*p) { case '/' : goto copy; case '$' : p = m - 1; if (m == e) goto end_basic; goto new_dir_first; } } } else { for (p--; p > s; p--) { /* '/path/folder/../' => '/path/' */ if (*p == '/') break; } } goto copy; } } } } } end_basic : path->data = s; path->len = p - s; return; copy : p++; if (m < e) goto new_dir; while (m < e) { c = *m; *p = c; p++; if (c == '/') { m++; new_dir : for ( ; m '' */ m += 2; if (m == e) break; goto new_dir; case '.' : if (e - m == 2 || m[2] == '/') { if (m - s >= 3) { /* NOTE : this is one higher than above because m has moved on 1 */ if (p[-2] == '.' && p[-3] == '.') { if (m - s == 3 || p[-4] == '/') { /* = '../../' */ p[0] = '.'; p[1] = '.'; p[2] = '/'; p += 3; m += 3; goto new_dir; } } } if (complex) { l = p; for (p -= 2; p >= s; p--) { switch (*p) { case '/' : break; case '$' : l[0] = '.'; l[1] = '.'; l[2] = '/'; p = l + 4; break; default : continue; } break; } m += 3; if (m == e) goto end; goto new_dir; } else { for (p -= 2; p > s; p--) { /* '/path/folder/../' => '/path/' */ if (*p == '/') break; } m += 3; if (m == e) goto end; goto new_dir; } } } } } else { m++; } } end : path->data = s; path->len = p - s; } /* This function converts a path to its directory version, and assumes that there is always space * to allocatate an extra character on the end (which is only true if the provided strings always * have NULL's at the end (hence the 'safe'). */ void ndk_path_to_dir_safe (ngx_str_t *path, ngx_uint_t complex, size_t off) { size_t len; u_char *p, *m; ndk_clean_path (path, complex, off); len = path->len; if (!len) return; p = path->data; m = p + len - 1; if (*m != '/') { p [len] = '/'; path->len++; } } /* Divides a path given by path/to/path1:path/to/path2 into separate strings and returns an * array of these strings. */ ngx_array_t * ndk_split_path_create (ngx_conf_t *cf, ngx_str_t *path) { ngx_str_t *str; int n; u_char *m, *s, *e; ngx_array_t *a; if (path == NULL) return NULL; n = ndk_strcntc (path, ':'); a = ngx_array_create (cf->pool, n + 1, sizeof (ngx_str_t)); if (a == NULL) { return NULL; } s = path->data; e = s + path->len; while (s < e) { m = s; while (m < e && *m != ':') m++; if (m == s) { s = m+1; continue; } str = ngx_array_push (a); if (str == NULL) { return NULL; } str->data = s; str->len = m - s; if (ngx_conf_full_name (cf->cycle, str, 0) == NGX_ERROR) return NULL; s = m+1; } return a; } ngx_array_t * ndk_split_path_create_raw (ngx_conf_t *cf, char *path) { ngx_str_t *str; int n; char *m, *s; ngx_array_t *a; if (path == NULL) return NULL; n = ndk_strccnt (path, ':'); a = ngx_array_create (cf->pool, n + 1, sizeof (ngx_str_t)); if (a == NULL) { return NULL; } s = path; while (*s != '\0') { m = s; while (*m != '\0' && *m != ':') m++; if (m == s) { s = m+1; continue; } str = ngx_array_push (a); if (str == NULL) { return NULL; } str->data = (u_char *) s; str->len = m - s; if (ngx_conf_full_name (cf->cycle, str, 0) == NGX_ERROR) return NULL; if (*m == '\0') break; s = m+1; } return a; } char * ndk_conf_set_full_path_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *path, *value; ngx_conf_post_t *post; path = (ngx_str_t *) (p + cmd->offset); if (path->data) { return "is duplicate"; } value = cf->args->elts; *path = value[1]; if (ngx_conf_full_name (cf->cycle, path, 0) == NGX_ERROR) return NGX_CONF_ERROR; if (cmd->post) { post = cmd->post; return post->post_handler(cf, post, path); } return NGX_CONF_OK; } char * ndk_conf_set_split_path_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { /* TODO : change to use the path func above */ char *p = conf; ngx_str_t *value, *str; ngx_array_t **a; ngx_conf_post_t *post; int n; u_char *m, *s, *e; a = (ngx_array_t **) (p + cmd->offset); if (*a != NGX_CONF_UNSET_PTR) { return "is duplicate"; } value = cf->args->elts; value++; n = ndk_strcntc (value, ':') + 1; *a = ngx_array_create (cf->pool, n, sizeof (ngx_str_t)); if (*a == NULL) { return NGX_CONF_ERROR; } s = value->data; e = s + value->len; while (s < e) { m = s; while (m < e && *m != ':') m++; if (m == s) { s = m+1; continue; } str = ngx_array_push (*a); if (str == NULL) { return NGX_CONF_ERROR; } str->data = s; str->len = m - s; if (ngx_conf_full_name (cf->cycle, str, 0) == NGX_ERROR) return NGX_CONF_ERROR; s = m+1; } if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, a); } return NGX_CONF_OK; } char * ndk_conf_set_full_path (ngx_conf_t *cf, void *data, ngx_str_t *path) { if (ngx_conf_full_name (cf->cycle, path, 0) == NGX_ERROR) return NGX_CONF_ERROR; return NGX_CONF_OK; } char * ndk_conf_set_full_conf_path (ngx_conf_t *cf, void *data, ngx_str_t *path) { if (ngx_conf_full_name (cf->cycle, path, 1) == NGX_ERROR) return NGX_CONF_ERROR; return NGX_CONF_OK; } debian/modules/nginx-development-kit/src/ndk_http_headers.h0000664000000000000000000000460212705233614021343 0ustar /* TODO : organize and add */ /* TODO : check - should it be r->main? */ #define ndk_http_uri(r) (r)->uri #define ndk_http_request_uri(r) (r)->unparsed_uri #define ndk_http_header_in(r,name) ((r)->headers_in.name ? &(r)->headers_in.name->value : NULL) #define ndk_http_header_out(r,name) ((r)->headers_out.name ? &(r)->headers_out.name->value : NULL) #define ndk_http_host_header(r) ndk_http_header_in (r, host) #define ndk_http_connection_header(r) ndk_http_header_in (r, connection) #define ndk_http_if_modified_since_header(r) ndk_http_header_in (r, if_modified_since) #define ndk_http_user_agent_header(r) ndk_http_header_in (r, user_agent) #define ndk_http_referer_header(r) ndk_http_header_in (r, referer) #define ndk_http_content_length_header(r) ndk_http_header_in (r, content_length) #define ndk_http_content_type_header(r) ndk_http_header_in (r, content_type) #define ndk_http_range_header(r) ndk_http_header_in (r, range) #define ndk_http_if_range_header(r) ndk_http_header_in (r, if_range) #define ndk_http_transfer_encoding_header(r) ndk_http_header_in (r, transfer_encoding) #define ndk_http_expect_header(r) ndk_http_header_in (r, expect) #define ndk_http_accept_encoding_header(r) ndk_http_header_in (r, accept_encoding) #define ndk_http_via_header(r) ndk_http_header_in (r, via) #define ndk_http_authorization_header(r) ndk_http_header_in (r, authorization) #define ndk_http_keep_alive_header(r) ndk_http_header_in (r, keep_alive) #define ndk_http_x_forwarded_for_header(r) ndk_http_header_in (r, x_forwarded_for) #define ndk_http_x_real_ip_header(r) ndk_http_header_in (r, x_real_ip) #define ndk_http_accept_header(r) ndk_http_header_in (r, accept) #define ndk_http_accept_language_header(r) ndk_http_header_in (r, accept_language) #define ndk_http_depth_header(r) ndk_http_header_in (r, depth) #define ndk_http_destination_header(r) ndk_http_header_in (r, destination) #define ndk_http_overwrite_header(r) ndk_http_header_in (r, overwrite) #define ndk_http_date_header(r) ndk_http_header_in (r, date) debian/modules/nginx-development-kit/src/ndk_rewrite.c0000664000000000000000000000527112705233614020350 0ustar /* these have been taken from the rewrite module and http_script file * because those functions are defined as being static - a patch will * be provided later to un-define them as being static */ uintptr_t ndk_http_script_exit_code = (uintptr_t) NULL; char * ndk_http_rewrite_value (ngx_conf_t *cf, ndk_http_rewrite_loc_conf_t *lcf, ngx_str_t *value) { ngx_int_t n; ngx_http_script_compile_t sc; ngx_http_script_value_code_t *val; ngx_http_script_complex_value_code_t *complex; n = ngx_http_script_variables_count(value); if (n == 0) { val = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(ngx_http_script_value_code_t)); if (val == NULL) { return NGX_CONF_ERROR; } n = ngx_atoi(value->data, value->len); if (n == NGX_ERROR) { n = 0; } val->code = ngx_http_script_value_code; val->value = (uintptr_t) n; val->text_len = (uintptr_t) value->len; val->text_data = (uintptr_t) value->data; return NGX_CONF_OK; } complex = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(ngx_http_script_complex_value_code_t)); if (complex == NULL) { return NGX_CONF_ERROR; } complex->code = ngx_http_script_complex_value_code; complex->lengths = NULL; ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); sc.cf = cf; sc.source = value; sc.lengths = &complex->lengths; sc.values = &lcf->codes; sc.variables = n; sc.complete_lengths = 1; if (ngx_http_script_compile(&sc) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; } ngx_int_t ndk_http_rewrite_var (ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_variable_t *var; ngx_http_core_main_conf_t *cmcf; ndk_http_rewrite_loc_conf_t *rlcf; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); if (rlcf->uninitialized_variable_warn == 0) { *v = ngx_http_variable_null_value; return NGX_OK; } cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); var = cmcf->variables.elts; /* * the ngx_http_rewrite_module sets variables directly in r->variables, * and they should be handled by ngx_http_get_indexed_variable(), * so the handler is called only if the variable is not initialized */ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "using uninitialized \"%V\" variable", &var[data].name); *v = ngx_http_variable_null_value; return NGX_OK; } debian/modules/nginx-development-kit/src/ndk_rewrite.h0000664000000000000000000000146112705233614020352 0ustar /* TODO : should remove this when not needed */ /* used for plugging into the rewrite module (taken from the rewrite module) */ typedef struct { ngx_array_t *codes; /* uintptr_t */ ngx_uint_t stack_size; ngx_flag_t log; ngx_flag_t uninitialized_variable_warn; } ndk_http_rewrite_loc_conf_t; extern ngx_module_t ngx_http_rewrite_module; extern uintptr_t ndk_http_script_exit_code; char * ndk_http_rewrite_value (ngx_conf_t *cf, ndk_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); ngx_int_t ndk_http_rewrite_var (ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); #define ndk_http_script_exit (u_char *) &ndk_http_script_exit_code debian/modules/nginx-development-kit/src/ndk_path.h0000664000000000000000000000154612705233614017631 0ustar /* path conversion functions */ void ndk_clean_path (ngx_str_t *path, ngx_uint_t complex, size_t off); void ndk_path_to_dir_safe (ngx_str_t *path, ngx_uint_t complex, size_t off); /* path create functions */ ngx_array_t * ndk_split_path_create (ngx_conf_t *cf, ngx_str_t *path); ngx_array_t * ndk_split_path_create_raw (ngx_conf_t *cf, char *path); /* conf set functions */ char * ndk_conf_set_full_path_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_split_path_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); /* conf set post functions */ char * ndk_conf_set_full_path (ngx_conf_t *cf, void *data, ngx_str_t *path); char * ndk_conf_set_full_conf_path (ngx_conf_t *cf, void *data, ngx_str_t *path); debian/modules/nginx-development-kit/src/ndk_http.h0000664000000000000000000000022412705233614017644 0ustar ngx_uint_t ndk_http_count_phase_handlers (ngx_http_core_main_conf_t *cmcf); ngx_uint_t ndk_http_parse_request_method (ngx_str_t *m); debian/modules/nginx-development-kit/src/ndk_regex.h0000664000000000000000000000061312705233614020001 0ustar char * ndk_conf_set_regex_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_regex_caseless_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_regex_array_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_regex_array_caseless_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); debian/modules/nginx-development-kit/src/ndk_process.c0000664000000000000000000000074412705233614020345 0ustar ngx_int_t ndk_init_signals (ngx_signal_t *sig, ngx_log_t *log) { struct sigaction sa; for ( ; sig->signo != 0; sig++) { ndk_zerov (sa); sa.sa_handler = sig->handler; sigemptyset (&sa.sa_mask); if (sigaction (sig->signo, &sa, NULL) == -1) { ngx_log_error (NGX_LOG_EMERG, log, ngx_errno, "sigaction(%s) failed", sig->signame); return NGX_ERROR; } } return NGX_OK; } debian/modules/nginx-development-kit/src/ndk_set_var.h0000664000000000000000000000311612705233614020333 0ustar /* * 2010 (C) Marcus Clyne */ #ifndef _NDK_SET_VAR_H_INCLUDED_ #define _NDK_SET_VAR_H_INCLUDED_ typedef ngx_int_t (*ndk_set_var_pt) (ngx_http_request_t *r, ngx_str_t *val); typedef ngx_int_t (*ndk_set_var_data_pt) (ngx_http_request_t *r, ngx_str_t *val, void *data); typedef ngx_int_t (*ndk_set_var_value_pt) (ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *v); typedef ngx_int_t (*ndk_set_var_value_data_pt) (ngx_http_request_t *r, ngx_str_t *val, ngx_http_variable_value_t *v, void *data); typedef void (*ndk_set_var_hash_pt) (u_char *p, char *data, size_t len); typedef struct { ngx_uint_t type; void *func; size_t size; void *data; } ndk_set_var_t; enum { NDK_SET_VAR_BASIC = 0, NDK_SET_VAR_DATA, NDK_SET_VAR_VALUE, NDK_SET_VAR_VALUE_DATA, NDK_SET_VAR_MULTI_VALUE, NDK_SET_VAR_MULTI_VALUE_DATA, NDK_SET_VAR_HASH }; char * ndk_set_var (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_set_var_value (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_set_var_multi_value (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_set_var_core (ngx_conf_t *cf, ngx_str_t *name, ndk_set_var_t *filter); char * ndk_set_var_value_core (ngx_conf_t *cf, ngx_str_t *name, ngx_str_t *value, ndk_set_var_t *filter); char * ndk_set_var_multi_value_core (ngx_conf_t *cf, ngx_str_t *name, ngx_str_t *value, ndk_set_var_t *filter); #endif /* _NDK_SET_VAR_H_INCLUDED_ */ debian/modules/nginx-development-kit/src/ndk.c0000664000000000000000000000616412705233614016611 0ustar /* * 2010 (C) Marcus Clyne */ #include #include #if (NDK_HTTP_PRE_CONFIG) static ngx_int_t ndk_http_preconfiguration (ngx_conf_t *cf); #endif #if (NDK_HTTP_POST_CONFIG) static ngx_int_t ndk_http_postconfiguration (ngx_conf_t *cf); #endif #if (NDK_HTTP_CREATE_MAIN_CONF) static void * ndk_http_create_main_conf (ngx_conf_t *cf); #endif #if (NDK_HTTP_INIT_MAIN_CONF) static char * ndk_http_init_main_conf (ngx_conf_t *cf, void *conf); #endif #if (NDK_HTTP_CREATE_SRV_CONF) static void * ndk_http_create_srv_conf (ngx_conf_t *cf); #endif #if (NDK_HTTP_MERGE_SRV_CONF) static char * ndk_http_merge_srv_conf (ngx_conf_t *cf, void *parent, void *child); #endif #if (NDK_HTTP_CREATE_LOC_CONF) static void * ndk_http_create_loc_conf (ngx_conf_t *cf); #endif #if (NDK_HTTP_MERGE_LOC_CONF) static char * ndk_http_merge_loc_conf (ngx_conf_t *cf, void *parent, void *child); #endif #if (NDK_HTTP_INIT_MASTER) static ngx_int_t ndk_http_init_master (ngx_log_t *log); #endif #if (NDK_HTTP_INIT_MODULE) static ngx_int_t ndk_http_init_module (ngx_cycle_t *cycle); #endif #if (NDK_HTTP_INIT_PROCESS) static ngx_int_t ndk_http_init_process (ngx_cycle_t *cycle); #endif #if (NDK_HTTP_EXIT_PROCESS) static void ndk_http_exit_process (ngx_cycle_t *cycle); #endif #if (NDK_HTTP_EXIT_MASTER) static void ndk_http_exit_master (ngx_cycle_t *cycle); #endif ngx_http_module_t ndk_http_module_ctx = { #if (NDK_HTTP_PRE_CONFIG) ndk_http_preconfiguration, #else NULL, #endif #if (NDK_HTTP_POST_CONFIG) ndk_http_postconfiguration, #else NULL, #endif #if (NDK_HTTP_CREATE_MAIN_CONF) ndk_http_create_main_conf, #else NULL, #endif #if (NDK_HTTP_INIT_MAIN_CONF) ndk_http_merge_main_conf, #else NULL, #endif #if (NDK_HTTP_CREATE_SVR_CONF) ndk_http_create_srv_conf, #else NULL, #endif #if (NDK_HTTP_MERGE_SVR_CONF) ndk_http_merge_srv_conf, #else NULL, #endif #if (NDK_HTTP_CREATE_LOC_CONF) ndk_http_create_loc_conf, #else NULL, #endif #if (NDK_HTTP_MERGE_LOC_CONF) ndk_http_merge_loc_conf, #else NULL, #endif }; ngx_module_t ndk_http_module = { NGX_MODULE_V1, &ndk_http_module_ctx, /* module context */ ndk_http_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ #if (NDK_HTTP_INIT_MASTER) ndk_http_init_master, #else NULL, #endif #if (NDK_HTTP_INIT_MODULE) ndk_http_init_module, #else NULL, #endif #if (NDK_HTTP_INIT_PROCESS) ndk_http_init_process, #else NULL, #endif NULL, /* init thread */ NULL, /* exit thread */ #if (NDK_HTTP_EXIT_PROCESS) ndk_http_exit_process, #else NULL, #endif #if (NDK_HTTP_EXIT_MASTER) ndk_http_exit_master, #else NULL, #endif NGX_MODULE_V1_PADDING }; #if (NDK_HTTP_CREATE_MAIN_CONF) static void * ndk_http_create_main_conf (ngx_conf_t *cf) { ndk_http_main_conf_t *mcf; ndk_pcallocp_rce (mcf, cf->pool); return mcf; } #endif debian/modules/nginx-development-kit/src/ndk_hash.c0000664000000000000000000000330212705233614017603 0ustar #include /* openssl hashes */ #define NDK_OPENSSL_HASH(type,ctxt_type,upper) \ u_char md [ctxt_type ## _DIGEST_LENGTH]; \ ctxt_type ##_CTX c; \ \ type ## _Init (&c); \ type ## _Update (&c, data, len); \ type ## _Final (md, &c); \ \ ndk_hex_dump (p, (u_char *) md, ctxt_type ## _DIGEST_LENGTH); \ if (upper) { \ ndk_strtoupper (p, (ctxt_type ## _DIGEST_LENGTH) *2); \ } #ifdef NDK_MD5 void ndk_md5_hash (u_char *p, char *data, size_t len) { NDK_OPENSSL_HASH (MD5, MD5, 0); } void ndk_md5_hash_upper (u_char *p, char *data, size_t len) { NDK_OPENSSL_HASH (MD5, MD5, 1); } #endif #ifdef NDK_SHA1 void ndk_sha1_hash (u_char *p, char *data, size_t len) { NDK_OPENSSL_HASH (SHA1, SHA, 0); } void ndk_sha1_hash_upper (u_char *p, char *data, size_t len) { NDK_OPENSSL_HASH (SHA1, SHA, 1); } #endif /* non-openssl hashes */ #ifdef NDK_MURMUR2 #include "hash/murmurhash2.c" void ndk_murmur2_hash (u_char *p, char *data, size_t len) { uint32_t hash; hash = MurmurHash2 (data, len, 47); ndk_hex_dump (p, (u_char*) &hash, 4); } void ndk_murmur2_hash_upper (u_char *p, char *data, size_t len) { uint32_t hash; hash = MurmurHash2 (data, len, 47); ndk_hex_dump (p, (u_char*) &hash, 4); ndk_strtoupper (p, 8); } #endif debian/modules/nginx-development-kit/src/ndk_http.c0000664000000000000000000000615512705233614017650 0ustar ngx_uint_t ndk_http_count_phase_handlers (ngx_http_core_main_conf_t *cmcf) { ngx_http_phase_handler_t *ph; ngx_uint_t i; ph = cmcf->phase_engine.handlers; for (i=0; ph[i].checker; i++) /* void */; return i; } ngx_uint_t ndk_http_parse_request_method (ngx_str_t *m) { switch (m->len) { case 3: #if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) { u_char t[4]; ngx_memcpy (t, m->data, 3); t[3] = ' '; if (ndk_str3_cmp (t, 'G', 'E', 'T', ' ')) { return NGX_HTTP_GET; } if (ndk_str3_cmp (t, 'P', 'U', 'T', ' ')) { return NGX_HTTP_PUT; } } #else if (ndk_str3_cmp (m->data, 'G', 'E', 'T', ' ')) { return NGX_HTTP_GET; } if (ndk_str3_cmp (m->data, 'P', 'U', 'T', ' ')) { return NGX_HTTP_PUT; } #endif break; case 4: if (m->data[1] == 'O') { if (ndk_str3Ocmp (m->data, 'P', 'O', 'S', 'T')) { return NGX_HTTP_POST; } if (ndk_str3Ocmp (m->data, 'C', 'O', 'P', 'Y')) { return NGX_HTTP_COPY; } if (ndk_str3Ocmp (m->data, 'M', 'O', 'V', 'E')) { return NGX_HTTP_MOVE; } if (ndk_str3Ocmp (m->data, 'L', 'O', 'C', 'K')) { return NGX_HTTP_LOCK; } } else { if (ndk_str4cmp (m->data, 'H', 'E', 'A', 'D')) { return NGX_HTTP_HEAD; } } break; case 5: if (ndk_str5cmp (m->data, 'M', 'K', 'C', 'O', 'L')) { return NGX_HTTP_MKCOL; } if (ndk_str5cmp (m->data, 'P', 'A', 'T', 'C', 'H')) { return NGX_HTTP_PATCH; } if (ndk_str5cmp (m->data, 'T', 'R', 'A', 'C', 'E')) { return NGX_HTTP_TRACE; } break; case 6: if (ndk_str6cmp (m->data, 'D', 'E', 'L', 'E', 'T', 'E')) { return NGX_HTTP_DELETE; } if (ndk_str6cmp (m->data, 'U', 'N', 'L', 'O', 'C', 'K')) { return NGX_HTTP_UNLOCK; } break; case 7: if (ndk_str7_cmp (m->data, 'O', 'P', 'T', 'I', 'O', 'N', 'S', ' ')) { return NGX_HTTP_OPTIONS; } break; case 8: if (ndk_str8cmp (m->data, 'P', 'R', 'O', 'P', 'F', 'I', 'N', 'D')) { return NGX_HTTP_PROPFIND; } break; case 9: if (ndk_str9cmp (m->data, 'P', 'R', 'O', 'P', 'P', 'A', 'T', 'C', 'H')) { return NGX_HTTP_PROPPATCH; } break; } return 0; }debian/modules/nginx-development-kit/src/ndk_encoding.c0000664000000000000000000000216212705233614020451 0ustar char * ndk_conf_set_encoding_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ndk_encoding_t *ep; ngx_str_t *value; size_t len; iconv_t ic; ep = (ndk_encoding_t *) (p + cmd->offset); if (ep->from && ep->to) return "is duplicate"; value = cf->args->elts; if (ep->from) { ep->to = (char *) value[1].data; len = strlen (ep->from); } else if (ep->to) { ep->from = (char *) value[1].data; len = strlen (ep->to); } else { return "has no base encoding"; } if (len == value[1].len && !strncasecmp (ep->to, ep->from, len)) { ngx_log_error (NGX_LOG_WARN, cf->log, 0, "\"%V\" '%V' encoding is ignored (no conversion)", &value[0], &value[1]); return NGX_CONF_OK; } ic = iconv_open (ep->to, ep->from); if (ic == (iconv_t)-1) return "has an invalid encoding"; if (iconv_close (ic)) { ngx_log_error (NGX_LOG_EMERG, cf->log, errno, "iconv_close()"); return NGX_CONF_ERROR; } return NGX_CONF_OK; } debian/modules/nginx-development-kit/src/ndk_complex_path.c0000664000000000000000000000477612705233614021363 0ustar ndk_http_complex_path_value_t ndk_empty_http_complex_path_value = {{0,NULL},0}; ngx_int_t ndk_http_complex_path_value_compile (ngx_conf_t *cf, ngx_http_complex_value_t *cv, ngx_str_t *value, ngx_uint_t prefix) { ngx_http_compile_complex_value_t ccv; ngx_memzero (&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = value; ccv.complex_value = cv; switch (prefix) { case 1 : ccv.root_prefix = 1; break; case 2 : ccv.conf_prefix = 1; break; } ndk_path_to_dir_safe (value, 1, 0); if (!value->len) return NGX_OK; return ngx_http_compile_complex_value (&ccv); } ngx_array_t * ndk_http_complex_path_create_compile (ngx_conf_t *cf, ngx_str_t *path, ngx_uint_t prefix) { ndk_http_complex_path_elt_t *cpe; ngx_array_t *a; ngx_int_t n; u_char *m, *s, *e; ngx_str_t value; n = ndk_strcntc (path, ':') + 1; a = ngx_array_create (cf->pool, n, sizeof (ndk_http_complex_path_elt_t)); if (a == NULL) { return NULL; } s = path->data; e = s + path->len; while (s < e) { m = s; while (m < e && *m != ':') m++; if (m == s) { s = m+1; continue; } cpe = ngx_array_push (a); if (cpe == NULL) { return NULL; } if (*s == '#') { s++; cpe->dynamic = 1; } else { cpe->dynamic = 0; } value.data = s; value.len = m - s; if (ndk_http_complex_path_value_compile (cf, &cpe->val, &value, prefix) == NGX_ERROR) return NULL; s = m+1; } return a; } char * ndk_conf_set_http_complex_path_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *path; ngx_array_t *a; ngx_conf_post_t *post; ndk_http_complex_path_t *cp; cp = (ndk_http_complex_path_t *) (p + cmd->offset); if (cp->a != NGX_CONF_UNSET_PTR) { return "is duplicate"; } path = cf->args->elts; path++; cp->a = ndk_http_complex_path_create_compile (cf, path, cp->prefix); if (cp->a == NULL) /* TODO : log */ return NGX_CONF_ERROR; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, a); } return NGX_CONF_OK; } debian/modules/nginx-development-kit/src/ndk_complex_path.h0000664000000000000000000000203012705233614021345 0ustar typedef struct { ngx_array_t *a; ngx_uint_t prefix; } ndk_http_complex_path_t; typedef struct { ngx_http_complex_value_t val; ngx_flag_t dynamic; } ndk_http_complex_path_elt_t; typedef struct { ngx_str_t val; ngx_flag_t dynamic; } ndk_http_complex_path_value_t; typedef struct { ndk_http_complex_path_value_t *elts; ngx_uint_t nelts; } ndk_http_complex_path_values_t; extern ndk_http_complex_path_value_t ndk_empty_http_complex_path_value; ngx_array_t * ndk_http_complex_path_create_compile (ngx_conf_t *cf, ngx_str_t *path, ngx_uint_t prefix); ngx_int_t ndk_http_complex_path_value_compile (ngx_conf_t *cf, ngx_http_complex_value_t *cv, ngx_str_t *value, ngx_uint_t prefix); char * ndk_conf_set_http_complex_path_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); debian/modules/nginx-development-kit/src/ndk_encoding.h0000664000000000000000000000030112705233614020447 0ustar #include typedef struct { char *from; char *to; } ndk_encoding_t; char * ndk_conf_set_encoding_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); debian/modules/nginx-development-kit/src/ndk_uri.h0000664000000000000000000000017312705233614017467 0ustar u_char * ndk_map_uri_to_path_add_suffix (ngx_http_request_t *r, ngx_str_t *path, ngx_str_t *suffix, ngx_int_t dot); debian/modules/nginx-development-kit/src/ndk_buf.h0000664000000000000000000000024512705233614017444 0ustar ngx_int_t ndk_copy_chain_to_str (ngx_pool_t *pool, ngx_chain_t *in, ngx_str_t *str); char * ndk_copy_chain_to_charp (ngx_pool_t *pool, ngx_chain_t *in); debian/modules/nginx-development-kit/src/ndk_complex_value.h0000664000000000000000000000144112705233614021532 0ustar typedef struct { ngx_str_t key; ngx_http_complex_value_t value; } ndk_http_complex_keyval_t; /* create/compile functions */ ngx_int_t ndk_http_complex_value_compile (ngx_conf_t *cf, ngx_http_complex_value_t *cv, ngx_str_t *value); ngx_array_t * ndk_http_complex_value_array_create (ngx_conf_t *cf, char **s, ngx_int_t n); ngx_int_t ndk_http_complex_value_array_compile (ngx_conf_t *cf, ngx_array_t *a); /* conf set slot functions */ char * ndk_conf_set_http_complex_keyval_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_http_complex_value_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_http_complex_value_array_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); debian/modules/nginx-development-kit/src/ndk_conf_file.c0000664000000000000000000001721312705233614020612 0ustar /* NOTE : you will find other conf_set functions in the following files : * * complex_value.c * encoding.c * path.c * */ char * ndk_conf_set_true_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_flag_t *fp; ngx_conf_post_t *post; fp = (ngx_flag_t*) (p + cmd->offset); if (*fp != NGX_CONF_UNSET) { return "is duplicate"; } *fp = 1; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, fp); } return NGX_CONF_OK; } char * ndk_conf_set_false_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_flag_t *fp; ngx_conf_post_t *post; fp = (ngx_flag_t*) (p + cmd->offset); if (*fp != NGX_CONF_UNSET) { return "is duplicate"; } *fp = 0; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, fp); } return NGX_CONF_OK; } char * ndk_conf_set_ptr_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; void **ptr; ptr = (void**) (p + cmd->offset); if (*ptr != NGX_CONF_UNSET_PTR) { return "is duplicate"; } *ptr = cmd->post; return NGX_CONF_OK; } char * ndk_conf_set_null_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; void **pp; ngx_conf_post_t *post; pp = (void **) (p + cmd->offset); if (*pp != NGX_CONF_UNSET_PTR) { return "is duplicate"; } *pp = NULL; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, pp); } return NGX_CONF_OK; } char * ndk_conf_set_num64_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; int64_t *np; ngx_str_t *value; ngx_conf_post_t *post; np = (int64_t *) (p + cmd->offset); if (*np != NGX_CONF_UNSET) { return "is duplicate"; } value = cf->args->elts; *np = ndk_atoi64 (value[1].data, value[1].len); if (*np == NGX_ERROR) { return "invalid number"; } if (cmd->post) { post = cmd->post; return post->post_handler(cf, post, np); } return NGX_CONF_OK; } char * ndk_conf_set_str_array_multi_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *value, *s; ngx_array_t **a; ngx_conf_post_t *post; ngx_uint_t i; a = (ngx_array_t **) (p + cmd->offset); if (*a == NGX_CONF_UNSET_PTR) { *a = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); if (*a == NULL) { return NGX_CONF_ERROR; } } s = NULL; for (i=cf->args->nelts-1; i; i--) { s = ngx_array_push(*a); if (s == NULL) { return NGX_CONF_ERROR; } value = cf->args->elts; *s = value[i]; } if (cmd->post) { post = cmd->post; return post->post_handler(cf, post, s); } return NGX_CONF_OK; } char * ndk_conf_set_keyval1_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_str_t *value; ngx_keyval_t *kv; ngx_conf_post_t *post; kv = (ngx_keyval_t *) (p + cmd->offset); if (kv->key.data) return "is duplicate"; value = cf->args->elts; kv->key = value[1]; kv->value = value[2]; if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, kv); } return NGX_CONF_OK; } char * ndk_conf_set_num_flag_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; ngx_int_t *np; ngx_str_t *value; ngx_conf_post_t *post; np = (ngx_int_t *) (p + cmd->offset); if (*np != NGX_CONF_UNSET) { return "is duplicate"; } value = cf->args->elts; if (ngx_strcasecmp (value[1].data, (u_char *) "on") == 0) { *np = NDK_CONF_SET_TRUE; } else if (ngx_strcasecmp (value[1].data, (u_char *) "off") == 0) { *np = NDK_CONF_SET_FALSE; } else { *np = ngx_atoi (value[1].data, value[1].len); if (*np == NGX_ERROR) { return "invalid number and not 'on'/'off'"; } } if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, np); } return NGX_CONF_OK; } char * ndk_conf_set_sec_flag_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; time_t *tp; ngx_str_t *value; ngx_conf_post_t *post; tp = (time_t *) (p + cmd->offset); if (*tp != NGX_CONF_UNSET) { return "is duplicate"; } value = cf->args->elts; if (ngx_strcasecmp (value[1].data, (u_char *) "on") == 0) { *tp = NDK_CONF_SET_TRUE; } else if (ngx_strcasecmp (value[1].data, (u_char *) "off") == 0) { *tp = NDK_CONF_SET_FALSE; } else { *tp = ngx_parse_time (&value[1], 1); if (*tp == NGX_ERROR) { return "has an invalid time and not 'on'/'off'"; } } if (cmd->post) { post = cmd->post; return post->post_handler (cf, post, tp); } return NGX_CONF_OK; } ngx_http_conf_ctx_t * ndk_conf_create_http_location (ngx_conf_t *cf) { ngx_http_conf_ctx_t *ctx, *pctx; void *mconf; ngx_http_core_loc_conf_t *clcf, *pclcf; ngx_uint_t i; ngx_http_module_t *module; ndk_pcallocp_rce (ctx, cf->pool); pctx = cf->ctx; ctx->main_conf = pctx->main_conf; ctx->srv_conf = pctx->srv_conf; ndk_pcalloc_rce (ctx->loc_conf, cf->pool, sizeof(void *) * ngx_http_max_module); for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_HTTP_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_loc_conf) { mconf = module->create_loc_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; } } pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; clcf->loc_conf = ctx->loc_conf; clcf->name = pclcf->name; clcf->noname = 1; if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { return NGX_CONF_ERROR; } return ctx; } ngx_http_conf_ctx_t * ngx_conf_create_http_named_location (ngx_conf_t *cf, ngx_str_t *name) { ngx_http_conf_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; ctx = ndk_conf_create_http_location (cf); if (ctx == NGX_CONF_ERROR) return NGX_CONF_ERROR; clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; /* in case the developer forgets to add '@' at the beginning of the named location */ if (name->data[0] != '@' && ndk_catstrf (cf->pool, name, "sS", "@", name) == NULL) return NGX_CONF_ERROR; clcf->name = *name; /* TODO : copy? */ clcf->noname = 0; clcf->named = 1; return ctx; } ngx_int_t ndk_replace_command (ngx_command_t *new_cmd, ngx_uint_t module_type) { ngx_uint_t i; ngx_command_t *cmd; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != module_type) continue; cmd = ngx_modules[i]->commands; if (cmd == NULL) { continue; } for ( /* void */ ; cmd->name.len; cmd++) { if (ndk_cmpstr (&new_cmd->name, &cmd->name) == 0) { ndk_memcpyp (cmd, new_cmd); return NGX_OK; } } } return NGX_DECLINED; } debian/modules/nginx-development-kit/src/ndk_string.c0000664000000000000000000001660112705233614020174 0ustar int64_t ndk_atoi64 (u_char *line, size_t n) { int64_t value; if (n == 0ll) { return NGX_ERROR; } for (value = 0ll; n--; line++) { if (*line < '0' || *line > '9') { return NGX_ERROR; } value = value * 10ll + (*line - '0'); } if (value < 0ll) { return NGX_ERROR; } return value; } ngx_int_t ndk_strcntc (ngx_str_t *s, char c) { ngx_int_t n; size_t i; u_char *p; i = s->len; p = s->data; for (n=0; i; i--, p++) { if (*p == (u_char) c) n++; } return n; } ngx_int_t ndk_strccnt (char *s, char c) { ngx_int_t n; n = 0; while (*s != '\0') { if (*s == 'c') n++; s++; } return n; } ngx_array_t * ndk_str_array_create (ngx_pool_t *pool, char **s, ngx_int_t n) { ngx_int_t i; ngx_str_t *str; ngx_array_t *a; a = ngx_array_create (pool, n, sizeof (ngx_str_t)); if (a == NULL) return NULL; for (i=0; idata = (u_char *) *s; str->len = strlen (*s); } return a; } u_char * ndk_vcatstrf (ngx_pool_t *pool, ngx_str_t *dest, const char *fmt, va_list args) { size_t len, l, el; int argc; u_char *p, *m, *e, c, c1, *cp; argc = strlen (fmt); ngx_str_t *s; ndk_estr_t *sp, *sp2, ss [argc]; u_char cs [argc]; sp = sp2 = ss; cp = cs; len = 0; /* TODO : maybe have 'e' at the beginning? */ /* parse format to get strings */ while (*fmt) { switch (*fmt) { case 'S' : s = va_arg (args, ngx_str_t *); sp->data = s->data; sp->len = s->len; sp->escaped = 0; len += sp->len; break; case 's' : sp->data = va_arg (args, u_char *); sp->len = (size_t) ngx_strlen (sp->data); sp->escaped = 0; len += sp->len; break; case 'l' : sp->data = va_arg (args, u_char *); sp->len = (size_t) va_arg (args, int); sp->escaped = 0; len += sp->len; break; case 'L' : sp->data = va_arg (args, u_char *); sp->len = va_arg (args, size_t); sp->escaped = 0; len += sp->len; break; case 'e' : p = va_arg (args, u_char *); sp->data = p; l = 0; el = 0; c = *p; while (c != '\0') { if (c == '\\') { l += 2; p += 2; } else { l++; p++; } el++; c = *p; } sp->len = l; sp->escaped = 1; len += el; break; case 'E' : s = va_arg (args, ngx_str_t *); sp->data = s->data; sp->len = s->len; p = sp->data; el = 0; e = p + sp->len; while (p < e) { c = *p; if (c == '\\') { p += 2; } else { p++; } el++; } sp->escaped = 1; len += el; break; case 'n' : sp->data = va_arg (args, u_char *); sp->len = (size_t) va_arg (args, int); p = sp->data; el = 0; e = p + sp->len; while (p < e) { c = *p; if (c == '\\') { p += 2; } else { p++; } el++; } sp->escaped = 1; len += el; break; case 'c' : *cp = (u_char) va_arg (args, int); sp->data = cp; sp->len = (size_t) 1; len++; cp++; break; default : ndk_log_alert (pool->log, 0, "catstrf () : format [%s] incorrect", fmt); return NULL; } sp++; fmt++; } /* create space for string (assumes no NULL's in strings) */ ndk_palloc_rn (p, pool, len + 1); dest->data = p; dest->len = len; /* copy other strings */ if (len) { while (sp2 < sp) { if (sp2->escaped) { m = sp2->data; e = m + sp2->len; while (m < e) { c = *m; if (c == '\\') { if (m == e - 1) { *p = '\\'; p++; break; } c1 = m[1]; switch (c1) { case 'n' : *p = '\n'; break; case 't' : *p = '\t'; break; case '0' : *p = '\0'; break; case '\\' : *p = '\\'; break; case 's' : *p = ' '; break; case 'b' : *p = '\b'; break; case 'r' : *p = '\r'; break; default : *p = c1; break; } m += 2; } else { *p = c; m++; } p++; } } else { p = ngx_cpymem (p, sp2->data, sp2->len); } sp2++; } } *p = '\0'; return dest->data; } u_char * ndk_catstrf (ngx_pool_t *pool, ngx_str_t *dest, const char *fmt, ...) { u_char *p; va_list args; va_start (args, fmt); p = ndk_vcatstrf (pool, dest, fmt, args); va_end (args); return p; } ngx_int_t ndk_cmpstr (ngx_str_t *s1, ngx_str_t *s2) { ngx_int_t rv; size_t len1, len2; len1 = s1->len; len2 = s2->len; if (len1 == len2) { return ngx_strncmp (s1->data, s2->data, len1); } if (len1 > len2) { rv = ngx_strncmp (s1->data, s2->data, len2); if (rv == 0) return 1; return rv; } rv = ngx_strncmp (s1->data, s2->data, len1); if (rv == 0) return -1; return rv; } u_char * ndk_dupstr (ngx_pool_t *pool, ngx_str_t *dest, ngx_str_t *src) { u_char *d; size_t n; n = src->len; ndk_palloc_rn (d, pool, n + 1); ndk_strncpy (d, src->data, n); dest->data = d; dest->len = n; return d; } /* ngx_keyval_t * ndk_url_args_to_keyval_list (ngx_pool_t *pool, ngx_str_t *str) { ngx_keyval_t *kv; ngx_st } */ debian/modules/nginx-development-kit/src/ndk_log.h0000664000000000000000000002546012705233614017457 0ustar /* TODO : fix the conf_log macros */ #define NGX_LOG_DEBUG_SCRIPT NGX_LOG_DEBUG_HTTP /* TODO : add new section to log/conf directives */ #define ndk_conf_to_log(cf) ((cf)->log) #ifndef ndk_request_to_log #define ndk_request_to_log(r) ((r)->connection->log) #endif /*********************************/ #if (NGX_HAVE_C99_VARIADIC_MACROS) #define ndk_log_stderr(log,...) ngx_log_error (NGX_LOG_STDERR, log, 0, __VA_ARGS__) #define ndk_log_emerg(log,...) ngx_log_error (NGX_LOG_EMERG, log, 0, __VA_ARGS__) #define ndk_log_alert(log,...) ngx_log_error (NGX_LOG_ALERT, log, 0, __VA_ARGS__) #define ndk_log_crit(log,...) ngx_log_error (NGX_LOG_CRIT, log, 0, __VA_ARGS__) #define ndk_log_err(log,...) ngx_log_error (NGX_LOG_ERR, log, 0, __VA_ARGS__) #define ndk_log_warning(log,...) ngx_log_error (NGX_LOG_WARN, log, 0, __VA_ARGS__) #define ndk_log_notice(log,...) ngx_log_error (NGX_LOG_NOTICE, log, 0, __VA_ARGS__) #define ndk_log_info(log,...) ngx_log_error (NGX_LOG_INFO, log, 0, __VA_ARGS__) #define ndk_conf_log_stderr(cf,...) ngx_conf_log_error (NGX_LOG_STDERR, cf, 0, __VA_ARGS__) #define ndk_conf_log_emerg(cf,...) ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, __VA_ARGS__) #define ndk_conf_log_alert(cf,...) ngx_conf_log_error (NGX_LOG_ALERT, cf, 0, __VA_ARGS__) #define ndk_conf_log_crit(cf,...) ngx_conf_log_error (NGX_LOG_CRIT, cf, 0, __VA_ARGS__) #define ndk_conf_log_err(cf,...) ngx_conf_log_error (NGX_LOG_ERR, cf, 0, __VA_ARGS__) #define ndk_conf_log_warning(cf,...) ngx_conf_log_error (NGX_LOG_WARN, cf, 0, __VA_ARGS__) #define ndk_conf_log_notice(cf,...) ngx_conf_log_error (NGX_LOG_NOTICE, cf, 0, __VA_ARGS__) #define ndk_conf_log_info(cf,...) ngx_conf_log_error (NGX_LOG_INFO, cf, 0, __VA_ARGS__) #define ndk_request_log_stderr(r,...) ndk_log_stderr (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_emerg(r,...) ndk_log_emerg (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_alert(r,...) ndk_log_alert (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_crit(r,...) ndk_log_crit (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_err(r,...) ndk_log_err (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_warning(r,...) ndk_log_warning (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_notice(r,...) ndk_log_notice (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_info(r,...) ndk_log_info (ndk_request_to_log(r), __VA_ARGS__) #if (NGX_DEBUG) #define ndk_log_debug_core(log,...) ngx_log_debug (NGX_LOG_DEBUG_CORE, log, 0, __VA_ARGS__) #define ndk_log_debug_alloc(log,...) ngx_log_debug (NGX_LOG_DEBUG_ALLOC, log, 0, __VA_ARGS__) #define ndk_log_debug_mutex(log,...) ngx_log_debug (NGX_LOG_DEBUG_MUTEX, log, 0, __VA_ARGS__) #define ndk_log_debug_event(log,...) ngx_log_debug (NGX_LOG_DEBUG_EVENT, log, 0, __VA_ARGS__) #define ndk_log_debug_http(log,...) ngx_log_debug (NGX_LOG_DEBUG_HTTP, log, 0, __VA_ARGS__) #define ndk_log_debug_mail(log,...) ngx_log_debug (NGX_LOG_DEBUG_MAIL, log, 0, __VA_ARGS__) #define ndk_log_debug_mysql(log,...) ngx_log_debug (NGX_LOG_DEBUG_MYSQL, log, 0, __VA_ARGS__) #define ndk_conf_log_debug_core(r,...) ndk_log_debug_core (ndk_conf_to_log(r), __VA_ARGS__) #define ndk_conf_log_debug_alloc(r,...) ndk_log_debug_alloc (ndk_conf_to_log(r), __VA_ARGS__) #define ndk_conf_log_debug_mutex(r,...) ndk_log_debug_mutex (ndk_conf_to_log(r), __VA_ARGS__) #define ndk_conf_log_debug_event(r,...) ndk_log_debug_event (ndk_conf_to_log(r), __VA_ARGS__) #define ndk_conf_log_debug_http(r,...) ndk_log_debug_http (ndk_conf_to_log(r), __VA_ARGS__) #define ndk_conf_log_debug_mail(r,...) ndk_log_debug_mail (ndk_conf_to_log(r), __VA_ARGS__) #define ndk_conf_log_debug_mysql(r,...) ndk_log_debug_mysql (ndk_conf_to_log(r), __VA_ARGS__) #define ndk_request_log_debug_core(r,...) ndk_log_debug_core (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_debug_alloc(r,...) ndk_log_debug_alloc (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_debug_mutex(r,...) ndk_log_debug_mutex (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_debug_event(r,...) ndk_log_debug_event (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_debug_http(r,...) ndk_log_debug_http (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_debug_mail(r,...) ndk_log_debug_mail (ndk_request_to_log(r), __VA_ARGS__) #define ndk_request_log_debug_mysql(r,...) ndk_log_debug_mysql (ndk_request_to_log(r), __VA_ARGS__) #else #define ndk_log_debug_core(log,...) #define ndk_log_debug_alloc(log,...) #define ndk_log_debug_mutex(log,...) #define ndk_log_debug_event(log,...) #define ndk_log_debug_http(log,...) #define ndk_log_debug_mail(log,...) #define ndk_log_debug_mysql(log,...) #define ndk_conf_log_debug_core(r,...) #define ndk_conf_log_debug_alloc(r,...) #define ndk_conf_log_debug_mutex(r,...) #define ndk_conf_log_debug_event(r,...) #define ndk_conf_log_debug_http(r,...) #define ndk_conf_log_debug_mail(r,...) #define ndk_conf_log_debug_mysql(r,...) #define ndk_request_log_debug_core(r,...) #define ndk_request_log_debug_alloc(r,...) #define ndk_request_log_debug_mutex(r,...) #define ndk_request_log_debug_event(r,...) #define ndk_request_log_debug_http(r,...) #define ndk_request_log_debug_mail(r,...) #define ndk_request_log_debug_mysql(r,...) #endif /*********************************/ #elif (NGX_HAVE_GCC_VARIADIC_MACROS) #define ndk_log_stderr(log,args...) ngx_log_error (NGX_LOG_STDERR, log, 0, args) #define ndk_log_emerg(log,args...) ngx_log_error (NGX_LOG_EMERG, log, 0, args) #define ndk_log_alert(log,args...) ngx_log_error (NGX_LOG_ALERT, log, 0, args) #define ndk_log_crit(log,args...) ngx_log_error (NGX_LOG_CRIT, log, 0, args) #define ndk_log_err(log,args...) ngx_log_error (NGX_LOG_ERR, log, 0, args) #define ndk_log_warning(log,args...) ngx_log_error (NGX_LOG_WARN, log, 0, args) #define ndk_log_notice(log,args...) ngx_log_error (NGX_LOG_NOTICE, log, 0, args) #define ndk_log_info(log,args...) ngx_log_error (NGX_LOG_INFO, log, 0, args) #define ndk_log_debug_core(log,args...) ngx_log_debug (NGX_LOG_DEBUG_CORE, log, 0, args) #define ndk_log_debug_alloc(log,args...) ngx_log_debug (NGX_LOG_DEBUG_ALLOC, log, 0, args) #define ndk_log_debug_mutex(log,args...) ngx_log_debug (NGX_LOG_DEBUG_MUTEX, log, 0, args) #define ndk_log_debug_event(log,args...) ngx_log_debug (NGX_LOG_DEBUG_EVENT, log, 0, args) #define ndk_log_debug_http(log,args...) ngx_log_debug (NGX_LOG_DEBUG_HTTP, log, 0, args) #define ndk_log_debug_mail(log,args...) ngx_log_debug (NGX_LOG_DEBUG_MAIL, log, 0, args) #define ndk_log_debug_mysql(log,args...) ngx_log_debug (NGX_LOG_DEBUG_MYSQL, log, 0, args) #define ndk_log_debug_script(log,args...) ngx_log_debug (NGX_LOG_DEBUG_SCRIPT, log, 0, args) #define ndk_conf_log_stderr(cf,args...) ngx_conf_log_error (NGX_LOG_STDERR, cf, 0, args) #define ndk_conf_log_emerg(cf,args...) ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, args) #define ndk_conf_log_alert(cf,args...) ngx_conf_log_error (NGX_LOG_ALERT, cf, 0, args) #define ndk_conf_log_crit(cf,args...) ngx_conf_log_error (NGX_LOG_CRIT, cf, 0, args) #define ndk_conf_log_err(cf,args...) ngx_conf_log_error (NGX_LOG_ERR, cf, 0, args) #define ndk_conf_log_warning(cf,args...) ngx_conf_log_error (NGX_LOG_WARN, cf, 0, args) #define ndk_conf_log_notice(cf,args...) ngx_conf_log_error (NGX_LOG_NOTICE, cf, 0, args) #define ndk_conf_log_info(cf,args...) ngx_conf_log_error (NGX_LOG_INFO, cf, 0, args) #define ndk_conf_log_debug_core(r,args...) ndk_log_debug_core (ndk_conf_to_log(r), args) #define ndk_conf_log_debug_alloc(r,args...) ndk_log_debug_alloc (ndk_conf_to_log(r), args) #define ndk_conf_log_debug_mutex(r,args...) ndk_log_debug_mutex (ndk_conf_to_log(r), args) #define ndk_conf_log_debug_event(r,args...) ndk_log_debug_event (ndk_conf_to_log(r), args) #define ndk_conf_log_debug_http(r,args...) ndk_log_debug_http (ndk_conf_to_log(r), args) #define ndk_conf_log_debug_mail(r,args...) ndk_log_debug_mail (ndk_conf_to_log(r), args) #define ndk_conf_log_debug_mysql(r,args...) ndk_log_debug_mysql (ndk_conf_to_log(r), args) #define ndk_conf_log_debug_script(r,args...) ndk_log_debug_script (ndk_conf_to_log(r), args) #define ndk_request_log_stderr(r,args...) ndk_log_stderr (ndk_request_to_log(r), args) #define ndk_request_log_emerg(r,args...) ndk_log_emerg (ndk_request_to_log(r), args) #define ndk_request_log_alert(r,args...) ndk_log_alert (ndk_request_to_log(r), args) #define ndk_request_log_crit(r,args...) ndk_log_crit (ndk_request_to_log(r), args) #define ndk_request_log_err(r,args...) ndk_log_err (ndk_request_to_log(r), args) #define ndk_request_log_warning(r,args...) ndk_log_warning (ndk_request_to_log(r), args) #define ndk_request_log_notice(r,args...) ndk_log_notice (ndk_request_to_log(r), args) #define ndk_request_log_info(r,args...) ndk_log_info (ndk_request_to_log(r), args) #define ndk_request_log_debug_core(r,args...) ndk_log_debug_core (ndk_request_to_log(r), args) #define ndk_request_log_debug_alloc(r,args...) ndk_log_debug_alloc (ndk_request_to_log(r), args) #define ndk_request_log_debug_mutex(r,args...) ndk_log_debug_mutex (ndk_request_to_log(r), args) #define ndk_request_log_debug_event(r,args...) ndk_log_debug_event (ndk_request_to_log(r), args) #define ndk_request_log_debug_http(r,args...) ndk_log_debug_http (ndk_request_to_log(r), args) #define ndk_request_log_debug_mail(r,args...) ndk_log_debug_mail (ndk_request_to_log(r), args) #define ndk_request_log_debug_mysql(r,args...) ndk_log_debug_mysql (ndk_request_to_log(r), args) #define ndk_request_log_debug_script(r,args...) ndk_log_debug_script (ndk_request_to_log(r), args) /*********************************/ #else /* NO VARIADIC MACROS */ /* #warning does not work on Windows */ #pragma message("Nginx Devel Kit logging without variadic macros not yet implemented") #endif /* VARIADIC MACROS */ debian/modules/nginx-development-kit/src/ndk_conf_file.h0000664000000000000000000000414012705233614020612 0ustar /* conf set functions */ char * ndk_conf_set_true_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_false_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_full_path_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_ptr_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_null_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_str_array_multi_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_keyval1_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_num_flag (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_num64_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ndk_conf_set_sec_flag_slot (ngx_conf_t *cf, ngx_command_t *cmd, void *conf); ngx_http_conf_ctx_t * ndk_conf_create_http_location (ngx_conf_t *cf); ngx_http_conf_ctx_t * ngx_conf_create_http_named_location (ngx_conf_t *cf, ngx_str_t *name); ngx_int_t ndk_replace_command (ngx_command_t *new_cmd, ngx_uint_t module_type); /* values for conf_set_xxx_flag */ #define NDK_CONF_SET_TRUE -2 #define NDK_CONF_SET_FALSE -3 /* wrappers for utility macros */ #define ndk_conf_set_bitmask_slot ngx_conf_set_bitmask_slot #define ndk_conf_set_bufs_slot ngx_conf_set_bufs_slot #define ndk_conf_set_enum_slot ngx_conf_set_enum_slot #define ndk_conf_set_flag_slot ngx_conf_set_flag_slot #define ndk_conf_set_keyval_slot ngx_conf_set_keyval_slot #define ndk_conf_set_msec_slot ngx_conf_set_msec_slot #define ndk_conf_set_num_slot ngx_conf_set_num_slot #define ndk_conf_set_off_slot ngx_conf_set_off_slot #define ndk_conf_set_sec_slot ngx_conf_set_sec_slot #define ndk_conf_set_size_slot ngx_conf_set_size_slot #define ndk_conf_set_str_slot ngx_conf_set_str_slot debian/modules/nginx-development-kit/src/ndk.h0000664000000000000000000000200012705233614016577 0ustar /* * 2010 (C) Marcus Clyne */ #ifndef NDK_H #define NDK_H #include #include #include #define ndk_version 2015 #define NDK_VERSION "0.2.15" #if (NGX_DEBUG) #ifndef NDK_DEBUG #define NDK_DEBUG 1 #endif #else #ifndef NDK_DEBUG #define NDK_DEBUG 0 #endif #endif #if !(NDK) #error At least one module requires the Nginx Development Kit to be compiled with \ the source (add --with-module=/path/to/devel/kit/src to configure command) #endif #include #if (NDK_HTTP_CREATE_MAIN_CONF) #define ndk_http_conf_get_main_conf(cf) ngx_http_conf_get_module_main_conf (cf, ndk_http_module) #define ndk_http_get_main_conf(r) ngx_http_get_module_main_conf (r, ndk_http_module) typedef struct { #if (NDK_UPSTREAM_LIST) ngx_array_t *upstreams; #endif } ndk_http_main_conf_t; #endif /* NDK_HTTP_CREATE_MAIN_CONF */ #include extern ngx_module_t ndk_http_module; #endif debian/modules/nginx-development-kit/src/ndk_debug.h0000664000000000000000000001155512705233614017764 0ustar #ifndef NDK_DEBUG_H #define NDK_DEBUG_H /* TODO : use the Nginx printf function */ #include #include /* TODO - andk_debug variety of debugging formats - global include file for all debugging - can pass declaration to cflags for the option */ #if (NDK_DEBUG) #if (NGX_HAVE_VARIADIC_MACROS) #define ndk_debug(...) ndk_debug_helper (__func__,__VA_ARGS__) #define ndk_debug_helper(func,...) \ fprintf(stderr, "%-60s", func); \ fprintf(stderr, (const char *)__VA_ARGS__); \ fprintf(stderr,"\n"); /*fprintf(stderr, " at %s line %d.\n", __FILE__, __LINE__)*/ #else /* NOTE : these includes might not be necessary since they're probably included with the core */ #include #include #include static void ndk_debug (const char * fmt, ...) { } #endif #if NDK_DEBUG > 1 #define ndk_debug_request() ndk_debug_request_helper(r, __func__) static ngx_inline void ndk_debug_request_helper (ngx_http_request_t *r, const char *func) { ngx_http_posted_request_t *pr; /* TODO : improve the format */ fprintf (stderr, "%s %.*s %.*s?%.*s c:%d m:%p r:%p ar:%p pr:%p", func, (int) r->method_name.len, r->method_name.data, (int) r->uri.len, r->uri.data, (int) r->args.len, r->args.data, 0/*(int) r->main->count*/, r->main, r, r->connection->data, r->parent); if (r->posted_requests) { fprintf(stderr, " posted:"); for (pr = r->posted_requests; pr; pr = pr->next) { fprintf (stderr, "%p,", pr); } } fprintf (stderr, "\n"); } #else #define ndk_debug_request() #endif static ngx_inline void ndk_debug_print_posted_requests (ngx_http_request_t *r) { ngx_http_posted_request_t *pr; ndk_request_log_debug_http (r, "ndk debug - http posted requests"); for (pr = r->main->posted_requests; pr; pr = pr->next) { if (!pr->request) continue; ndk_request_log_debug_http (r, "ndk debug - http posted request:%V", &pr->request->uri); } } #define ndk_debug_http_conf_location(cf) ndk_debug_http_conf_location_helper (cf, __func__) static ngx_inline void ndk_debug_http_conf_location_helper (ngx_conf_t *cf, const char *func) { ngx_http_core_loc_conf_t *lcf; lcf = ngx_http_conf_get_module_loc_conf (cf, ngx_http_core_module); ndk_debug_helper (func, "[%s]", lcf->name.data); } /* static void ndk_debug_log_chain (ngx_log_t *log, ngx_chain_t *cl) { } */ #else #if (NGX_HAVE_VARIADIC_MACROS) #define ndk_debug(...) #define ndk_debug_request() #else #include static void ndk_debug (const char * fmt, ...) { } static void ndk_debug_request() { } #endif #define ndk_debug_http_conf_location(cf) #endif #if (NDK_DEBUG) #define ndk_debug_check_read_event_handler(r) \ \ ndk_debug("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 ndk_debug_check_write_event_handler(r) \ \ ndk_debug ("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 ndk_debug_check_read_event_handler(r) #define ndk_debug_check_write_event_handler(r) #endif #endif /* NDK_DEBUG_H */ debian/modules/nginx-development-kit/src/ndk_string.h0000664000000000000000000000211212705233614020171 0ustar #if 1 /* TODO : set ndk_hex_dump for older versions of Nginx */ #define ndk_hex_dump ngx_hex_dump #endif typedef struct { size_t len; u_char *data; ngx_flag_t escaped; } ndk_estr_t; int64_t ndk_atoi64 (u_char *line, size_t n); ngx_int_t ndk_strcntc (ngx_str_t *s, char c); ngx_int_t ndk_strccnt (char *s, char c); ngx_array_t * ndk_str_array_create (ngx_pool_t *pool, char **s, ngx_int_t n); u_char * ndk_catstrf (ngx_pool_t *pool, ngx_str_t *dest, const char *fmt, ...); ngx_int_t ndk_cmpstr (ngx_str_t *s1, ngx_str_t *s2); u_char * ndk_dupstr (ngx_pool_t *pool, ngx_str_t *dest, ngx_str_t *src); static ngx_inline void ndk_strtoupper (u_char *p, size_t len) { u_char *e = p + len; for ( ; ps; for (i=0; ilen; i++) { if (s->data[i] < '0' || s->data[i] > '9') break; } if (!i) { ulp->weight = 1; return NGX_OK; } if (i == s->len) { ngx_conf_log_error (NGX_LOG_EMERG, ulp->cf, 0, "upstream list just consists of number \"%V\"", s); return NGX_ERROR; } if (s->data[i] != ':') { ngx_conf_log_error (NGX_LOG_EMERG, ulp->cf, 0, "upstream list not correct format \"%V\"", s); return NGX_ERROR; } ulp->weight = ngx_atoi (s->data, i); s->data += (i + 1); s->len -= (i + 1); return NGX_OK; } static char * ndk_upstream_list (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { /* TODO : change this for getting upstream pointer if available */ ngx_uint_t buckets, count, i, j; ngx_str_t *value, **bucket, *us; ngx_array_t *ula; ndk_upstream_list_t *ul, *ule; ndk_upstream_list_parse_t ulp; ndk_http_main_conf_t *mcf; mcf = ngx_http_conf_get_module_main_conf (cf, ndk_http_module); ula = mcf->upstreams; /* create array of upstream lists it doesn't already exist */ if (ula == NULL) { ula = ngx_array_create (cf->pool, 4, sizeof (ndk_upstream_list_t)); if (ula == NULL) return NGX_CONF_ERROR; mcf->upstreams = ula; } /* check to see if the list already exists */ value = cf->args->elts; value++; ul = ula->elts; ule = ul + ula->nelts; for ( ; ulname.len == value->len && ngx_strncasecmp (ul->name.data, value->data, value->len) == 0) { ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, "duplicate upstream list name \"%V\"", value); return NGX_CONF_ERROR; } } /* create a new list */ ul = ngx_array_push (ula); if (ul == NULL) return NGX_CONF_ERROR; ul->name = *value; /* copy all the upstream names */ count = cf->args->nelts - 2; us = ngx_palloc (cf->pool, count * sizeof (ngx_str_t)); if (us == NULL) return NGX_CONF_ERROR; ngx_memcpy (us, value + 1, count * sizeof (ngx_str_t)); /* calculate the total number of buckets */ buckets = 0; ulp.cf = cf; for (i=0; ipool, buckets * sizeof (ngx_str_t **)); if (bucket == NULL) return NGX_CONF_ERROR; ul->elts = bucket; ul->nelts = buckets; /* set values for each bucket */ us -= count; for (i=0; idata = ulp.s.data; us->len = ulp.s.len; /* TODO : check format of upstream */ /* TODO : add automatic adding of http:// in upstreams? */ for (j=0; jupstreams; if (ua == NULL) { return NULL; } ul = ua->elts; ule = ul + ua->nelts; for (; ul < ule; ul++) { if (ul->name.len == len && ngx_strncasecmp(ul->name.data, data, len) == 0) { return ul; } } return NULL; } debian/modules/nginx-development-kit/src/ndk_uri.c0000664000000000000000000000146712705233614017471 0ustar /* TODO : check that this is correct */ u_char * ndk_map_uri_to_path_add_suffix (ngx_http_request_t *r, ngx_str_t *path, ngx_str_t *suffix, ngx_int_t dot) { size_t root_size; u_char *p; if (suffix->len) { if (dot) { p = ngx_http_map_uri_to_path (r, path, &root_size, suffix->len + 1); if (p == NULL) return NULL; *p = '.'; p++; } else { p = ngx_http_map_uri_to_path (r, path, &root_size, suffix->len); if (p == NULL) return NULL; } path->len--; p = ngx_cpymem (p, suffix->data, suffix->len); *p = '\0'; return p; } p = ngx_http_map_uri_to_path (r, path, &root_size, 0); path->len--; return p; } debian/modules/nginx-development-kit/src/ndk_debug.c0000664000000000000000000000255012705233614017752 0ustar #if (NGX_DEBUG) void ndk_debug_helper (const char *func, const char *fmt, ...) { size_t len, flen, tlen; char *s, *p, *e; /* check to see if the format is empty */ flen = strlen (fmt); /* build func name */ len = strlen (func); if (flen == 0) tlen = len + 1; else char func_name [len + flen + 1]; s = func_name; e = s + len; memcpy (s, func, len); /* remove initial ngx_ */ if (strncmp (s, "ngx_", 4) == 0) s += 4; /* replace '_' with ' ' */ for (p=s; pmethod_name.len, r->method_name.data, (int) r->uri.len, r->uri.data, (int) r->args.len, r->args.data, 0/*(int) r->main->count*/, r->main, r, r->connection->data, r->parent); if (r->posted_requests) { fprintf(stderr, " posted:"); for (pr = r->posted_requests; pr; pr = pr->next) { fprintf (stderr, "%p,", pr); } } fprintf (stderr, "\n"); } #endif debian/modules/nginx-development-kit/src/ndk_set_var.c0000664000000000000000000003420712705233614020333 0ustar #include typedef struct { ngx_http_script_code_pt code; void *func; } ndk_set_var_code_t; typedef struct { ngx_http_script_code_pt code; void *func; size_t size; } ndk_set_var_size_code_t; typedef struct { ngx_http_script_code_pt code; void *func; void *data; } ndk_set_var_data_code_t; typedef struct { ngx_http_script_code_pt code; void *func; size_t size; void *data; } ndk_set_var_size_data_code_t; typedef struct { ngx_int_t index; ngx_str_t *value; ngx_http_variable_t *v; ngx_conf_t *cf; ndk_http_rewrite_loc_conf_t *rlcf; } ndk_set_var_info_t; static void ndk_set_var_code (ngx_http_script_engine_t *e); static void ndk_set_var_hash_code (ngx_http_script_engine_t *e); static void ndk_set_var_value_code (ngx_http_script_engine_t *e); static ngx_inline void ndk_set_var_code_finalize(ngx_http_script_engine_t *e, ngx_int_t rc, ngx_http_variable_value_t *v, ngx_str_t *str) { switch (rc) { case NGX_OK: v->data = str->data; v->len = str->len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, "http script value (post filter): \"%v\"", v); break; case NGX_DECLINED: v->valid = 0; v->not_found = 1; v->no_cacheable = 1; break; case NGX_ERROR: e->ip = ndk_http_script_exit; e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; break; } } static void ndk_set_var_code(ngx_http_script_engine_t *e) { ngx_int_t rc; ngx_str_t str; ngx_http_variable_value_t *v; ndk_set_var_code_t *sv; ndk_set_var_pt func; sv = (ndk_set_var_code_t *) e->ip; e->ip += sizeof(ndk_set_var_code_t); v = e->sp++; func = (ndk_set_var_pt) sv->func; rc = func(e->request, &str); ndk_set_var_code_finalize(e, rc, v, &str); } static void ndk_set_var_data_code(ngx_http_script_engine_t *e) { ngx_int_t rc; ngx_str_t str; ngx_http_variable_value_t *v; ndk_set_var_data_code_t *svd; ndk_set_var_data_pt func; svd = (ndk_set_var_data_code_t *) e->ip; e->ip += sizeof(ndk_set_var_data_code_t); v = e->sp++; func = (ndk_set_var_data_pt) svd->func; rc = func(e->request, &str, svd->data); ndk_set_var_code_finalize(e, rc, v, &str); } static void ndk_set_var_value_code(ngx_http_script_engine_t *e) { ngx_int_t rc; ngx_str_t str; ngx_http_variable_value_t *v; ndk_set_var_code_t *sv; ndk_set_var_value_pt func; sv = (ndk_set_var_code_t *) e->ip; e->ip += sizeof(ndk_set_var_code_t); v = e->sp - 1; func = (ndk_set_var_value_pt) sv->func; rc = func(e->request, &str, v); ndk_set_var_code_finalize(e, rc, v, &str); } static void ndk_set_var_value_data_code(ngx_http_script_engine_t *e) { ngx_int_t rc; ngx_str_t str; ngx_http_variable_value_t *v; ndk_set_var_data_code_t *svd; ndk_set_var_value_data_pt func; svd = (ndk_set_var_data_code_t *) e->ip; e->ip += sizeof(ndk_set_var_data_code_t); v = e->sp - 1; func = (ndk_set_var_value_data_pt) svd->func; rc = func(e->request, &str, v, svd->data); ndk_set_var_code_finalize(e, rc, v, &str); } static void ndk_set_var_multi_value_code(ngx_http_script_engine_t *e) { ngx_int_t rc; ngx_str_t str; ngx_http_variable_value_t *v; ndk_set_var_size_code_t *svs; ndk_set_var_value_pt func; svs = (ndk_set_var_size_code_t *) e->ip; e->ip += sizeof(ndk_set_var_size_code_t); v = e->sp - svs->size; e->sp = v + 1; func = (ndk_set_var_value_pt) svs->func; rc = func(e->request, &str, v); ndk_set_var_code_finalize(e, rc, v, &str); } static void ndk_set_var_multi_value_data_code(ngx_http_script_engine_t *e) { ngx_int_t rc; ngx_str_t str; ngx_http_variable_value_t *v; ndk_set_var_size_data_code_t *svsd; ndk_set_var_value_data_pt func; svsd = (ndk_set_var_size_data_code_t *) e->ip; e->ip += sizeof(ndk_set_var_size_data_code_t); v = e->sp - svsd->size; e->sp = v + 1; func = (ndk_set_var_value_data_pt) svsd->func; rc = func(e->request, &str, v, svsd->data); ndk_set_var_code_finalize(e, rc, v, &str); } static void ndk_set_var_hash_code(ngx_http_script_engine_t *e) { u_char *p; ngx_http_variable_value_t *v; ndk_set_var_size_code_t *svs; ndk_set_var_hash_pt func; svs = (ndk_set_var_size_code_t *) e->ip; e->ip += sizeof(ndk_set_var_size_code_t); p = ngx_palloc(e->request->pool, svs->size); if (p == NULL) { e->ip = ndk_http_script_exit; e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; return; } v = e->sp - 1; func = (ndk_set_var_hash_pt) svs->func; func(p, (char *) v->data, v->len); v->data = (u_char *) p; v->len = svs->size; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, "http script hashed value: \"%v\"", v); } static char * ndk_set_var_name(ndk_set_var_info_t *info, ngx_str_t *varname) { ngx_int_t index; ngx_http_variable_t *v; ngx_conf_t *cf; ndk_http_rewrite_loc_conf_t *rlcf; ngx_str_t name; name = *varname; cf = info->cf; rlcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_rewrite_module); if (name.data[0] != '$') { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid variable name \"%V\"", &name); return NGX_CONF_ERROR; } name.len--; name.data++; v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); if (v == NULL) { return NGX_CONF_ERROR; } index = ngx_http_get_variable_index(cf, &name); if (index == NGX_ERROR) { return NGX_CONF_ERROR; } if (v->get_handler == NULL && ngx_strncasecmp(name.data, (u_char *) "arg_", 4) != 0 && ngx_strncasecmp(name.data, (u_char *) "cookie_", 7) != 0 && ngx_strncasecmp(name.data, (u_char *) "http_", 5) != 0 && ngx_strncasecmp(name.data, (u_char *) "sent_http_", 10) != 0 && ngx_strncasecmp(name.data, (u_char *) "upstream_http_", 14) != 0) { v->get_handler = ndk_http_rewrite_var; v->data = index; } info->v = v; info->index = index; info->rlcf = rlcf; return NGX_CONF_OK; } static void ndk_set_variable_value_space(ndk_http_rewrite_loc_conf_t *rlcf, ngx_uint_t count) { /* if the number of variable values that will be used is greater than 10, * make sure there is enough space allocated on the rewrite value stack */ if (count <= 10) return; if (rlcf->stack_size == NGX_CONF_UNSET_UINT) { rlcf->stack_size = count; return; } if (rlcf->stack_size < count) rlcf->stack_size = count; } static char * ndk_set_var_filter(ngx_conf_t *cf, ndk_http_rewrite_loc_conf_t *rlcf, ndk_set_var_t *filter) { ndk_set_var_code_t *sv; ndk_set_var_size_code_t *svs; ndk_set_var_data_code_t *svd; ndk_set_var_size_data_code_t *svsd; if (filter == NULL) { return "no filter set"; } switch (filter->type) { case NDK_SET_VAR_BASIC: sv = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ndk_set_var_code_t)); if (sv == NULL) { return NGX_CONF_ERROR; } sv->code = ndk_set_var_code; sv->func = filter->func; break; case NDK_SET_VAR_DATA: svd = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ndk_set_var_data_code_t)); if (svd == NULL) { return NGX_CONF_ERROR; } svd->code = ndk_set_var_data_code; svd->func = filter->func; svd->data = filter->data; break; case NDK_SET_VAR_VALUE: sv = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ndk_set_var_code_t)); if (sv == NULL) { return NGX_CONF_ERROR; } sv->code = ndk_set_var_value_code; sv->func = filter->func; break; case NDK_SET_VAR_VALUE_DATA: svd = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ndk_set_var_data_code_t)); if (svd == NULL) { return NGX_CONF_ERROR; } svd->code = ndk_set_var_value_data_code; svd->func = filter->func; svd->data = filter->data; break; case NDK_SET_VAR_MULTI_VALUE: svs = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ndk_set_var_size_code_t)); if (svs == NULL) { return NGX_CONF_ERROR; } svs->code = ndk_set_var_multi_value_code; svs->func = filter->func; svs->size = filter->size; ndk_set_variable_value_space(rlcf, svs->size); break; case NDK_SET_VAR_MULTI_VALUE_DATA: svsd = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ndk_set_var_size_data_code_t)); if (svsd == NULL) { return NGX_CONF_ERROR; } svsd->code = ndk_set_var_multi_value_data_code; svsd->func = filter->func; svsd->size = filter->size; svsd->data = filter->data; ndk_set_variable_value_space(rlcf, svsd->size); break; case NDK_SET_VAR_HASH: svs = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ndk_set_var_size_code_t)); if (svs == NULL) { return NGX_CONF_ERROR; } svs->code = ndk_set_var_hash_code; svs->func = filter->func; svs->size = filter->size; break; default: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid filter type \"%ul\"", filter->type); return NGX_CONF_ERROR; } return NGX_CONF_OK; } static char * ndk_set_var_filter_value(ndk_set_var_info_t *info, ndk_set_var_t *filter) { ngx_conf_t *cf; ngx_http_variable_t *v; ndk_http_rewrite_loc_conf_t *rlcf; ngx_http_script_var_code_t *vcode; ngx_http_script_var_handler_code_t *vhcode; v = info->v; cf = info->cf; rlcf = info->rlcf; if (ndk_set_var_filter(cf, rlcf, filter) != NGX_CONF_OK) { return NGX_CONF_ERROR; } if (v->set_handler) { vhcode = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ngx_http_script_var_handler_code_t)); if (vhcode == NULL) { return NGX_CONF_ERROR; } vhcode->code = ngx_http_script_var_set_handler_code; vhcode->handler = v->set_handler; vhcode->data = v->data; return NGX_CONF_OK; } vcode = ngx_http_script_start_code(cf->pool, &rlcf->codes, sizeof(ngx_http_script_var_code_t)); if (vcode == NULL) { return NGX_CONF_ERROR; } vcode->code = ngx_http_script_set_var_code; vcode->index = (uintptr_t) info->index; return NGX_CONF_OK; } char * ndk_set_var_core(ngx_conf_t *cf, ngx_str_t *name, ndk_set_var_t *filter) { char *p; ndk_set_var_info_t info; info.cf = cf; p = ndk_set_var_name(&info, name); if (p != NGX_CONF_OK) { return p; } return ndk_set_var_filter_value(&info, filter); } char * ndk_set_var_value_core(ngx_conf_t *cf, ngx_str_t *name, ngx_str_t *value, ndk_set_var_t *filter) { char *p; ndk_set_var_info_t info; info.cf = cf; p = ndk_set_var_name(&info, name); if (p != NGX_CONF_OK) { return p; } p = ndk_http_rewrite_value(cf, info.rlcf, value); if (p != NGX_CONF_OK) { return p; } return ndk_set_var_filter_value(&info, filter); } char * ndk_set_var_multi_value_core(ngx_conf_t *cf, ngx_str_t *name, ngx_str_t *value, ndk_set_var_t *filter) { char *p; ndk_set_var_info_t info; ngx_int_t i; info.cf = cf; p = ndk_set_var_name(&info, name); if (p != NGX_CONF_OK) { return p; } for (i = filter->size; i; i--, value++) { p = ndk_http_rewrite_value(cf, info.rlcf, value); if (p != NGX_CONF_OK) { return p; } } return ndk_set_var_filter_value(&info, filter); } char * ndk_set_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value; ndk_set_var_t *filter; value = cf->args->elts; value++; filter = (ndk_set_var_t *) cmd->post; return ndk_set_var_core(cf, value, filter); } char * ndk_set_var_value(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value; ndk_set_var_t *filter; value = cf->args->elts; value++; filter = (ndk_set_var_t *) cmd->post; return ndk_set_var_value_core(cf, value, cf->args->nelts == 1 + 1 ? value : value + 1, filter); } char * ndk_set_var_multi_value(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value; ndk_set_var_t *filter; value = cf->args->elts; value++; filter = (ndk_set_var_t *) cmd->post; return ndk_set_var_multi_value_core(cf, value, value + 1, filter); } debian/modules/nginx-development-kit/src/ndk_string_util.h0000664000000000000000000000112412705233614021230 0ustar #define ndk_str_init(ns,s) {(ns).data = (u_char*) s; (ns).len = sizeof (s) - 1;} #define ndk_strp_init(ns,s) {(ns)->data = (u_char*) s; (ns)->len = sizeof (s) - 1;} #define ndk_zero(p,sz) memset (p,'\0',sz) #define ndk_zerop(p) ndk_zero (p,sizeof(*p)) #define ndk_zeropn(p,n) ndk_zero (p,sizeof(*p)*(n)) #define ndk_zerov(v) ndk_zero (&v,sizeof(v)) #define ngx_null_enum { ngx_null_string, 0 } #define ndk_memcpyp(d,s) ngx_memcpy(d,s,sizeof(s)) debian/modules/nginx-development-kit/src/ndk_parse.h0000664000000000000000000000606212705233614020005 0ustar #if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) #define ndk_str3_cmp(m, c0, c1, c2, c3) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) #define ndk_str3Ocmp(m, c0, c1, c2, c3) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) #define ndk_str4cmp(m, c0, c1, c2, c3) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) #define ndk_str5cmp(m, c0, c1, c2, c3, c4) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && m[4] == c4 #define ndk_str6cmp(m, c0, c1, c2, c3, c4, c5) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && (((uint32_t *) m)[1] & 0xffff) == ((c5 << 8) | c4) #define ndk_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4) #define ndk_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4) #define ndk_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \ *(uint32_t *) m == ((c3 << 24) | (c2 << 16) | (c1 << 8) | c0) \ && ((uint32_t *) m)[1] == ((c7 << 24) | (c6 << 16) | (c5 << 8) | c4) \ && m[8] == c8 #else /* !(NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED) */ #define ndk_str3_cmp(m, c0, c1, c2, c3) \ m[0] == c0 && m[1] == c1 && m[2] == c2 #define ndk_str3Ocmp(m, c0, c1, c2, c3) \ m[0] == c0 && m[2] == c2 && m[3] == c3 #define ndk_str4cmp(m, c0, c1, c2, c3) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 #define ndk_str5cmp(m, c0, c1, c2, c3, c4) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 && m[4] == c4 #define ndk_str6cmp(m, c0, c1, c2, c3, c4, c5) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \ && m[4] == c4 && m[5] == c5 #define ndk_str7_cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \ && m[4] == c4 && m[5] == c5 && m[6] == c6 #define ndk_str8cmp(m, c0, c1, c2, c3, c4, c5, c6, c7) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \ && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7 #define ndk_str9cmp(m, c0, c1, c2, c3, c4, c5, c6, c7, c8) \ m[0] == c0 && m[1] == c1 && m[2] == c2 && m[3] == c3 \ && m[4] == c4 && m[5] == c5 && m[6] == c6 && m[7] == c7 && m[8] == c8 #endif debian/modules/nginx-development-kit/src/ndk_hash.h0000664000000000000000000000161212705233614017612 0ustar #ifndef NDK_HASH_H #define NDK_HASH_H #ifdef NDK_HASH_ALL #ifndef NDK_MD5 #define NDK_MD5 #endif #ifndef NDK_MURMUR2 #define NDK_MURMUR2 #endif #ifndef NDK_SHA1 #define NDK_SHA1 #endif #endif #include #include typedef void (*ndk_hash_pt) (u_char *p, char *data, size_t len); #ifdef NDK_MD5 #include void ndk_md5_hash (u_char *p, char *data, size_t len); void ndk_md5_hash_upper (u_char *p, char *data, size_t len); #endif #ifdef NDK_MURMUR2 #define MURMURHASH2_DIGEST_LENGTH 4 void ndk_murmur2_hash (u_char *p, char *data, size_t len); void ndk_murmur2_hash_upper (u_char *p, char *data, size_t len); #endif #ifdef NDK_SHA1 #include void ndk_sha1_hash (u_char *p, char *data, size_t len); void ndk_sha1_hash_upper (u_char *p, char *data, size_t len); #endif #endif /* NDK_HASH_H */ debian/modules/nginx-development-kit/ngx_auto_lib_core0000664000000000000000000004554312705233614020513 0ustar ## Directories to search for usable builds: ## ## - [$PFX]_INC and [$PFX]_LIB ## - the dir specified by --with-[$pfx]=* ## - each dir named [$pfx]-* under [$PFX]_BASE (descending order) ## - each dir named [$pfx]-* under $ngx_src_dir/.. (descending order) ## - system_paths (see below) ## ## Note : specifying [$PFX]_INC or [$PFX]_LIB prevents other dirs being tried ## specifying --with-[$pfx]= prevents autodiscovery of dirs ## ## Note : if this file is not in the same directory as the config file, the value ## for ngx_auto_lib_file should be changed to a relative path from that file ## e.g. : $ngx_addon_dir/libs/ngx_auto_lib ## ## TODO : explain hooks ############# ## VERSION ## ############# ngx_auto_lib_version=1001 if [ ! $ngx_auto_lib_file_version ] || [ $ngx_auto_lib_file_version -lt $ngx_auto_lib_version ]; then if [ ! $ngx_addon_dir ]; then ngx_addon_dir=`cd $(dirname $0); pwd` fi ngx_auto_lib_file="$ngx_addon_dir/ngx_auto_lib_core" ngx_auto_lib_file_version="$ngx_auto_lib_version" fi ############### ## VARIABLES ## ############### v= v="$v inc_path" v="$v incs" v="$v libs" v="$v name" v="$v path" v="$v run" v="$v test" ev= ev="$ev add_libs" ev="$ev add_path" ev="$ev build_dirs" ev="$ev build_inc_dirs" ev="$ev build_lib_dirs" ev="$ev check_macros_defined" ev="$ev check_macros_non_zero" ev="$ev defines" ev="$ev deps" ev="$ev exit_if_not_found" ev="$ev haves" ev="$ev inc_names" ev="$ev lib_files" ev="$ev lib_names" ev="$ev libs_to_add" ev="$ev modules" ev="$ev srcs" ev="$ev shared" ev="$ev test_libs" ev="$ev variables" ngx_feature_vars="$v" ngx_feature_extra_vars="$ev" ngx_feature_all_vars="$v $ev" NGX_AUTO_LIB_DEFAULT_SYSTEM_DIRS='/usr/local /usr /opt/local /opt /usr/pkg' #################### ## UTIL FUNCTIONS ## #################### to_upper() { echo "$@" | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' } to_lower() { echo "$@" | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' } #################### ## INIT FUNCTIONS ## #################### ngx_auto_lib_init() { . $ngx_auto_lib_file ngx_auto_lib_init_latest $@ } ngx_auto_lib_init_latest() { # set name and prefixes if [ ! $1 ]; then echo "ngx_auto_lib_init() requires that a name be passed" exit 1 fi ngx_auto_lib_name=$1 ngx_auto_lib_module_name=$2 if [ $2 ]; then NGX_AUTO_LIB_PFX=`to_upper $2` else NGX_AUTO_LIB_PFX=`to_upper $1` fi ngx_auto_lib_pfx=`to_lower $NGX_AUTO_LIB_PFX` ngx_auto_lib_clean_feature_vars } ngx_auto_lib_clean_feature_vars() { for var in $ngx_feature_all_vars; do eval ngx_feature_$var= done } ngx_auto_lib_get_variables() { local pfx=$ngx_auto_lib_pfx local PFX=$NGX_AUTO_LIB_PFX eval NGX_AUTO_LIB_INC=\"\$${PFX}_INC\" eval NGX_AUTO_LIB_LIB=\"\$${PFX}_LIB\" eval NGX_AUTO_LIB_DIR=\"\$${PFX}\" eval NGX_AUTO_LIB_BASE=\"\$${PFX}_BASE\" eval NGX_AUTO_LIB_SEARCH_LIB_INC=\"\$${PFX}_SEARCH_LIB_INC\" eval NGX_AUTO_LIB_SEARCH_DIR=\"\$${PFX}_SEARCH_DIR\" eval NGX_AUTO_LIB_SEARCH_BASE=\"\$${PFX}_SEARCH_BASE\" eval NGX_AUTO_LIB_SEARCH_BASE_PREFIX=\"\$${PFX}_SEARCH_BASE_PREFIX\" eval NGX_AUTO_LIB_SEARCH_PARENT=\"\$${PFX}_SEARCH_PARENT\" eval NGX_AUTO_LIB_SEARCH_SYSTEM=\"\$${PFX}_SEARCH_SYSTEM\" eval NGX_AUTO_LIB_SHARED=\"\$${PFX}_SHARED\" eval NGX_AUTO_LIB_SYSTEM_DIRS=\"\$${PFX}_SYSTEM_DIR\" eval USE_NGX_AUTO_LIB=\"\$USE_${LIB}\" if [ ! "$NGX_AUTO_LIB_DIR" ]; then NGX_AUTO_LIB_DIR=NONE fi if [ ! "$USE_NGX_AUTO_LIB" ]; then if [ $ngx_feature_check_macros_defined -o $ngx_feature_check_macros_non_zero ]; then USE_NGX_AUTO_LIB=MAYBE elif [ "$ngx_feature_required" = no ]; then USE_NGX_AUTO_LIB=MAYBE else USE_NGX_AUTO_LIB=YES fi fi if [ ! "$NGX_AUTO_LIB_SYSTEM_DIRS" ]; then NGX_AUTO_LIB_SYSTEM_DIRS=$NGX_AUTO_LIB_DEFAULT_SYSTEM_DIRS fi # TODO : add _STATIC, and do searches for both static and shared libs if [ ! "$NGX_AUTO_LIB_SHARED" ]; then if [ "$ngx_feature_shared" = no ]; then NGX_AUTO_LIB_SHARED=NO else NGX_AUTO_LIB_SHARED=YES fi fi NGX_AUTO_LIB_SEARCH_DEP=NO # set default search methods # Note : these can be over-ridden by setting NGX_AUTO_LIB_SEARCH_[type]=YES|NO local auto=y if [ "$NGX_AUTO_LIB_INC" ] || [ "$NGX_AUTO_LIB_LIB" ]; then ngx_auto_lib_search LIB_INC YES auto=n fi if [ "$NGX_AUTO_LIB_DIR" != NONE ]; then ngx_auto_lib_search DIR YES auto=n fi if [ "$NGX_AUTO_LIB_BASE" ]; then ngx_auto_lib_search BASE YES auto=n fi if [ $auto = y ]; then ngx_auto_lib_search PARENT YES ngx_auto_lib_search SYSTEM YES fi ngx_auto_lib_search LIB_INC NO ngx_auto_lib_search DIR NO ngx_auto_lib_search BASE NO ngx_auto_lib_search PARENT NO ngx_auto_lib_search SYSTEM NO if [ ! "$ngx_feature_lib_names" ]; then ngx_feature_lib_names=$pfx fi if [ ! "$ngx_feature_inc_names" ]; then ngx_feature_inc_names=$ngx_feature_lib_names fi if [ ! "$ngx_feature_exit_if_not_found" ]; then ngx_feature_exit_if_not_found=yes fi } ####################### ## DEFAULT FUNCTIONS ## ####################### ngx_auto_lib_set_default() { local suffix= if [ $1 ]; then suffix="_$1" fi local def=$2 local var="NGX_AUTO_LIB$suffix" val= if [ ! `eval echo '$'$var` ]; then eval $var=\"$def\" fi #eval echo "$var = \$$var" } ngx_auto_lib_search() { ngx_auto_lib_set_default "SEARCH_$1" $2 } #################### ## SAVE FUNCTIONS ## #################### ngx_auto_lib_save_vars() { OLD_CORE_DEPS=$CORE_DEPS OLD_CORE_INCS=$CORE_INCS OLD_CORE_LIBS=$CORE_LIBS OLD_CORE_SRCS=$CORE_SRCS OLD_LINK_DEPS=$LINK_DEPS CORE_DEPS= CORE_INCS= CORE_LIBS= CORE_SRCS= LINK_DEPS= } ngx_auto_lib_reset_vars() { CORE_DEPS=$OLD_CORE_DEPS CORE_INCS=$OLD_CORE_INCS CORE_LIBS=$OLD_CORE_LIBS CORE_SRCS=$OLD_CORE_SRCS LINK_DEPS=$OLD_LINK_DEPS } ngx_auto_lib_save_feature_vars() { for var in $ngx_feature_all_vars; do eval main_ngx_feature_$var=\"\$ngx_feature_$var\" done } ngx_auto_lib_reset_feature_vars() { for var in $ngx_feature_all_vars; do eval ngx_feature_$var=\"\$main_ngx_feature_$var\" done } ######################## ## CHECKING FUNCTIONS ## ######################## ngx_auto_lib_check_auto_config() { ngx_auto_lib_save_feature_vars ngx_auto_lib_clean_feature_vars ngx_feature=$1 ngx_feature_inc_path="`echo $CFLAGS | tr ' ' '\n' | grep -- -D | tr '\n' ' '`" ngx_feature_incs="#include <$NGX_AUTO_CONFIG_H>" ngx_feature_libs= ngx_feature_path=`pwd` ngx_feature_run=no ngx_feature_test=$2 #ngx_auto_lib_print_feature_vars . auto/feature if [ $ngx_found = yes ]; then rv=0 else rv=1 fi ngx_auto_lib_reset_feature_vars return $rv } ngx_auto_lib_check_macro_defined() { for m in $@; do ngx_auto_lib_check_auto_config "$m" " #ifndef $m rubbish #endif" && return 0 done return 1 } ngx_auto_lib_check_macro_non_zero() { for m in $@; do ngx_auto_lib_check_auto_config "$m" " #if !($m) rubbish #endif" && return 0 done return 1 } ngx_auto_lib_check_require() { if [ $USE_NGX_AUTO_LIB = YES ]; then return 0 elif [ $USE_NGX_AUTO_LIB = NO ]; then return 1 fi # check if the libraries are required elsewhere for l in $ngx_feature_lib_names; do [ ! "`echo $CORE_LIBS $ADDON_LIBS | grep -w -- -l$l`" ] && return 0 done # check that any required macros are set local d=$ngx_feature_check_macros_defined local nz=$ngx_feature_check_macros_non_zero if [ "$d" ] || [ "$nz" ]; then ngx_auto_lib_check_macro_defined $d && return 0 ngx_auto_lib_check_macro_non_zero $nz && return 0 fi ngx_auto_lib_check } ngx_auto_lib_check() { return 1 } ################################## ## TEST PHASE HANDLER FUNCTIONS ## ################################## ngx_auto_lib_test() { ngx_auto_lib_test_pre_setup "$@" ngx_auto_lib_test_setup "$@" ngx_auto_lib_test_post_setup "$@" ngx_auto_lib_test_feature } ngx_auto_lib_test_pre_setup() { return 0 } ngx_auto_lib_test_setup() { local INC=$1 local LIB=$2 ngx_auto_lib_inc_dir=$INC ngx_auto_lib_lib_dir=$LIB ngx_auto_lib_reset_feature_vars if [ ! "$ngx_feature_path" ]; then ngx_feature_path="$INC" fi ngx_feature_path="$ngx_feature_path $ngx_feature_add_path" for sfx in $ngx_feature_path_suffixes; do ngx_feature_path="$ngx_feature_path $INC/$sfx" done local inc= local lib= local incs="$ngx_feature_inc_names" local libs="$ngx_feature_lib_names" local lib_files="$ngx_feature_lib_files" for inc in $incs; do ngx_feature_incs="$ngx_feature_incs #include <$inc.h>" done if [ ! "$ngx_feature_libs" ]; then if [ $NGX_AUTO_LIB_SHARED = YES ]; then if [ $NGX_RPATH = YES ]; then ngx_feature_libs="-R$LIB" fi ngx_feature_libs="$ngx_feature_libs -L$LIB" for lib in $libs; do ngx_feature_libs="$ngx_feature_libs -l$lib" done # TODO : only add --rpath when the path is not a standard system path - warn if /usr ngx_feature_libs="$ngx_feature_libs -Wl,--rpath -Wl,$LIB" else for lib in $lib_files; do ngx_feature_libs="$ngx_feature_libs $LIB/$lib" done for lib in $libs; do ngx_feature_libs="$ngx_feature_libs $LIB/lib$lib.a" done fi fi if [ ! $ngx_feature_run ]; then ngx_feature_run=no fi if [ $NGX_AUTO_LIB_SHARED = YES ]; then # Add a test to be called in auto/feature after compilation that will check # whether any libraries that are linked are in fact using the path provided to # link libraries rather than a standard path. Note : this test will work on # all linked shared objects, even if supplied directly by setting # $ngx_feature_libs instead of usign $ngx_feature_lib_names # TODO : allow for some libraries to not be checked here if desired - if part of system paths libs="`echo $ngx_feature_libs | tr ' ' '\n' | grep -- -l | sed 's|-l||g'`" local test=" for l in $libs; do o="'\`ldd '$NGX_AUTOTEST' | grep '$LIB'/lib\$l\\.so\`; if [ ! \"\$o\" ]; then chmod -x $NGX_AUTOTEST; echo Linker does not link to correct version else chmod +x $NGX_AUTOTEST; fi done' test="`echo "$test" | tr '\n' ' '`" ngx_feature_test_libs="$ngx_feature_test_libs; $test" fi ngx_feature_libs="$ngx_feature_libs $ngx_feature_add_libs" ngx_feature_libs_to_add="$ngx_feature_libs" ngx_feature_libs="$ngx_feature_libs $ngx_feature_test_libs" ngx_feature="$ngx_auto_lib_name library $ngx_feature" } ngx_auto_lib_test_post_setup() { return 0 } ngx_auto_lib_test_feature() { #ngx_auto_lib_print_feature_vars . auto/feature [ $ngx_found = yes ] && return 0 return 1 } ######################## ## TEST DIR FUNCTIONS ## ######################## ngx_auto_lib_test_dir_pair() { ngx_auto_lib_test_inc_dir=$1 ngx_auto_lib_test_lib_dir=$2 if [ $1 = $2 ]; then ngx_feature="in $1$3" else ngx_feature="in $1 and $2$3" fi ngx_auto_lib_test "$1" "$2" "$3" } ngx_auto_lib_test_dir_pairs() { ngx_auto_lib_test_dir_pair "$1/include" "$2/lib" "$3" && return 0 ngx_auto_lib_test_dir_pair "$1" "$2" "$3" && return 0 return 1 } ngx_auto_lib_test_dirs() { local msg="$1" local bdir idir ldir local bdirs=$ngx_feature_build_dirs local idirs=$ngx_feature_build_inc_dirs local ldirs=$ngx_feature_build_lib_dirs shift for dir in "$@"; do ngx_auto_lib_test_dir=$dir for ldir in $ldirs; do for idir in $idirs; do ngx_auto_lib_test_dir_pair "$dir/$idir" "$dir/$ldir" "$msg" && return 0 done done for ldir in $ldirs; do ngx_auto_lib_test_dir_pair "$dir" "$dir/$ldir" "$msg" && return 0 done for idir in $idirs; do ngx_auto_lib_test_dir_pair "$dir/$idir" "$dir" "$msg" && return 0 done for bdir in $bdirs; do ngx_auto_lib_test_dir_pairs "$dir/$bdir" "$dir/$bdir" "$msg" && return 0 done ngx_auto_lib_test_dir_pairs "$dir" "$dir" "$msg" && return 0 ngx_auto_lib_test_dir= done return 1 } ngx_auto_lib_test_install_dirs() { local msg="$1" local dir= shift for dir in "$@"; do ngx_auto_lib_test_dir=$dir ngx_auto_lib_test_dir_pair "$dir/include" "$dir/lib" "$msg" && return 0 ngx_auto_lib_test_dir= done return 1 } ngx_auto_lib_run_tests() { local name="$ngx_auto_lib_name" local pfx="$ngx_auto_lib_pfx" local PFX="$NGX_AUTO_LIB_PFX" local INC="$NGX_AUTO_LIB_INC" local LIB="$NGX_AUTO_LIB_LIB" local DIR="$NGX_AUTO_LIB_DIR" local BASE="$NGX_AUTO_LIB_BASE" local MSG="$NGX_AUTO_LIB_MSG" ngx_found=no # dependency if [ $NGX_AUTO_LIB_SEARCH_DEP = YES ]; then ngx_auto_lib_test_dir_pair "$INC" "$LIB" "$MSG" return $? fi # lib and include dirs set explicitly (e.g. $OPENSSL_INC, $OPENSSL_LIB) if [ $NGX_AUTO_LIB_SEARCH_LIB_INC = YES ]; then ngx_auto_lib_test_dir_pair "$INC" "$LIB" " (specified by \$${PFX}_INC and \$${PFX}_LIB)" && return 0 fi # path specified by ${PFX} (e.g. $OPENSSL, $PCRE) # Note : these will be set automatically by configure for OpenSSL, PCRE, Zlib etc # TODO : change to searching more than one path if [ $NGX_AUTO_LIB_SEARCH_DIR = YES ] && [ $DIR != NONE ]; then ngx_auto_lib_test_dirs " (specified by \$${PFX})" $DIR && return 0 fi # directories beginning with '$pfx-' that are in $NGX_AUTO_LIB_BASE (e.g. $OPENSSL_BASE) if [ $NGX_AUTO_LIB_SEARCH_BASE = YES ] && [ $BASE ]; then p=$NGX_AUTO_LIB_SEARCH_BASE_PREFIX if [ "$p" = YES ]; then p="!ame $pfx-*" elif [ "$p" ]; then p="!ame $p*" fi ngx_auto_lib_test_dirs " (found under \$${PFX}_BASE)" \ `find $BASE/* -maxdepth 0 -type d $p 2> /dev/null | sort -r` && return 0 fi # directories beginning with '$pfx-' that are in the same directory as the Nginx source if [ $NGX_AUTO_LIB_SEARCH_PARENT = YES ]; then local src_dir=`cd ..; pwd` ngx_auto_lib_test_dirs " (found under Nginx source parent dir)" \ `find $src_dir/* -maxdepth 0 -type d !ame $pfx-* 2> /dev/null | sort -r` && return 0 fi # system folders if [ $NGX_AUTO_LIB_SEARCH_SYSTEM = YES ]; then ngx_auto_lib_test_install_dirs "" $NGX_AUTO_LIB_SYSTEM_DIRS && return 0 fi return 1 } ####################### ## HANDLER FUNCTIONS ## ####################### ngx_auto_lib_run() { ngx_auto_lib_get_variables eval AUTO_$NGX_AUTO_LIB_PFX=NO ngx_auto_lib_check_require || return ngx_auto_lib_setup || return ngx_auto_lib_save_feature_vars ngx_auto_lib_run_tests ngx_auto_lib_post_tests || return ngx_auto_lib_finalize } ngx_auto_lib_print_feature_vars() { echo ---------------------------- for var in $ngx_feature_vars; do eval "echo ngx_feature_$var = \$ngx_feature_$var" done echo ---------------------------- } ngx_auto_lib_setup() { return 0 } ngx_auto_lib_post_tests() { return 0 } ############################# ## SET VARIABLES FUNCTIONS ## ############################# # TODO : add HTTP/ADDON settings too ngx_auto_lib_set_core_variables() { # TODO : don't add includes / libs more than once eval CORE_DEPS=\"$CORE_DEPS $ngx_feature_deps\" eval CORE_INCS=\"$CORE_INCS $ngx_feature_path\" eval CORE_LIBS=\"$CORE_LIBS $ngx_feature_libs_to_add\" eval CORE_SRCS=\"$CORE_SRCS $ngx_feature_srcs\" } ngx_auto_lib_set_generic_variables() { local INC=$ngx_auto_lib_test_inc_dir local LIB=$ngx_auto_lib_test_lib_dir modules="$modules $ngx_feature_modules" for have in $ngx_feature_haves; do . auto/have done set - $ngx_feature_defines while [ $1 ]; do have=$1 value=$2 . auto/define done local PFX=$NGX_AUTO_LIB_PFX eval USE_$PFX=NO if [ $ngx_auto_lib_test_dir ]; then eval $PFX=$ngx_auto_lib_test_dir else eval $PFX=$ngx_auto_lib_lib_dir fi if [ $NGX_AUTO_LIB_SHARED != YES ]; then for l in $ngx_feature_lib_names; do CORE_LIBS=`echo $CORE_LIBS | sed 's|-\||g'` ADDON_LIBS=`echo $ADDON_LIBS | sed 's|-\||g'` done fi eval ${PFX}_INC=$INC eval ${PFX}_LIB=$LIB eval ${PFX}_SHARED=$NGX_AUTO_LIB_SHARED eval AUTO_$PFX=YES } ngx_auto_lib_set_custom_variables() { return 0 } ######################## ## FINALIZE FUNCTIONS ## ######################## ngx_auto_lib_finalize() { ngx_auto_lib_finalize_core } ngx_auto_lib_finalize_core() { if [ $ngx_found = yes ]; then ngx_auto_lib_set_core_variables ngx_auto_lib_set_generic_variables if [ "$ngx_feature_variables" ]; then eval $ngx_feature_variables fi ngx_auto_lib_set_custom_variables elif [ $ngx_feature_exit_if_not_found = yes ]; then if [ $ngx_auto_lib_module_name ]; then module_txt=" by the $ngx_auto_lib_module_name module" else module_text= fi lib=$ngx_auto_lib_name pfx=$ngx_auto_lib_pfx PFX=$NGX_AUTO_LIB_PFX cat << END $0: error: the $lib library is required$module_txt, but cannot be found using the current configuration. In order for the compilation to succeed, you will need to install the library using your system's package installer or point the configure script to the library using one of the following variables : to define a dir to find $pfx library (source or install dir) $PFX to define $pfx lib and include dirs separately ${PFX}_LIB & ${PFX}_INC to define a base dir to search for dirs beginning with $pfx- ${PFX}_BASE e.g. $ export ${PFX}_LIB=/path/to/library/lib $ export ${PFX}_LIB=/path/to/library/include $ $0 ... END exit 1 fi } debian/modules/nginx-echo/0000775000000000000000000000000012705233614012702 5ustar debian/modules/nginx-echo/util/0000775000000000000000000000000012705233614013657 5ustar debian/modules/nginx-echo/util/wiki2pod.pl0000664000000000000000000000606412705233614015752 0ustar #!/usr/bin/env perl use strict; use warnings; use bytes; my @nl_counts; my $last_nl_count_level; my @bl_counts; my $last_bl_count_level; sub fmt_pos ($) { (my $s = $_[0]) =~ s{\#(.*)}{/"$1"}; $s; } sub fmt_mark ($$) { my ($tag, $s) = @_; my $max_level = 0; while ($s =~ /([<>])\1*/g) { my $level = length $&; if ($level > $max_level) { $max_level = $level; } } my $times = $max_level + 1; if ($times > 1) { $s = " $s "; } return $tag . ('<' x $times) . $s . ('>' x $times); } print "=encoding utf-8\n\n"; while (<>) { if ($. == 1) { # strip the leading U+FEFF byte in MS-DOS text files my $first = ord(substr($_, 0, 1)); #printf STDERR "0x%x", $first; #my $second = ord(substr($_, 2, 1)); #printf STDERR "0x%x", $second; if ($first == 0xEF) { substr($_, 0, 1, ''); #warn "Hit!"; } } s{\[(http[^ \]]+) ([^\]]*)\]}{$2 (L<$1>)}gi; s{ \[\[ ( [^\]\|]+ ) \| ([^\]]*) \]\] }{"L<$2|" . fmt_pos($1) . ">"}gixe; s{(.*?)}{fmt_mark('C', $1)}gie; s{'''(.*?)'''}{fmt_mark('B', $1)}ge; s{''(.*?)''}{fmt_mark('I', $1)}ge; if (s{^\s*<[^>]+>\s*$}{}) { next; } if (/^\s*$/) { print "\n"; next; } =begin cmt if ($. == 1) { warn $_; for my $i (0..length($_) - 1) { my $chr = substr($_, $i, 1); warn "chr ord($i): ".ord($chr)." \"$chr\"\n"; } } =end cmt =cut if (/(=+) (.*) \1$/) { #warn "HERE! $_" if $. == 1; my ($level, $title) = (length $1, $2); collapse_lists(); print "\n=head$level $title\n\n"; } elsif (/^(\#+) (.*)/) { my ($level, $txt) = (length($1) - 1, $2); if (defined $last_nl_count_level && $level != $last_nl_count_level) { print "\n=back\n\n"; } $last_nl_count_level = $level; $nl_counts[$level] ||= 0; if ($nl_counts[$level] == 0) { print "\n=over\n\n"; } $nl_counts[$level]++; print "\n=item $nl_counts[$level].\n\n"; print "$txt\n"; } elsif (/^(\*+) (.*)/) { my ($level, $txt) = (length($1) - 1, $2); if (defined $last_bl_count_level && $level != $last_bl_count_level) { print "\n=back\n\n"; } $last_bl_count_level = $level; $bl_counts[$level] ||= 0; if ($bl_counts[$level] == 0) { print "\n=over\n\n"; } $bl_counts[$level]++; print "\n=item *\n\n"; print "$txt\n"; } else { collapse_lists(); print; } } collapse_lists(); sub collapse_lists { while (defined $last_nl_count_level && $last_nl_count_level >= 0) { print "\n=back\n\n"; $last_nl_count_level--; } undef $last_nl_count_level; undef @nl_counts; while (defined $last_bl_count_level && $last_bl_count_level >= 0) { print "\n=back\n\n"; $last_bl_count_level--; } undef $last_bl_count_level; undef @bl_counts; } debian/modules/nginx-echo/util/build.sh0000775000000000000000000000326212705233614015320 0ustar #!/usr/bin/env bash # this file is mostly meant to be used by the author himself. root=`pwd` version=$1 force=$2 home=~ #--without-http_ssi_module \ #--with-cc=gcc46 \ ngx-build $force $version \ --with-ld-opt="-L$PCRE_LIB -Wl,-rpath,$PCRE_LIB:$LIBDRIZZLE_LIB:/usr/local/lib" \ --with-cc-opt="-DDEBUG_MALLOC" \ --with-http_stub_status_module \ --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_addition_module \ --add-module=$root/../ndk-nginx-module \ --add-module=$root/../set-misc-nginx-module \ --add-module=$root/../eval-nginx-module \ --add-module=$root/../xss-nginx-module \ --add-module=$root/../rds-json-nginx-module \ --add-module=$root/../headers-more-nginx-module \ --add-module=$root/../lua-nginx-module \ --add-module=$root $opts \ --with-select_module \ --with-poll_module \ --with-rtsig_module \ --with-debug || exit 1 #--add-module=$root/../lz-session-nginx-module \ #--add-module=$home/work/ndk \ #--add-module=$home/work/ndk/examples/http/set_var \ #--add-module=$root/../eval-nginx-module \ #--add-module=/home/agentz/work/nginx_eval_module-1.0.1 \ debian/modules/nginx-echo/t/0000775000000000000000000000000012705233614013145 5ustar debian/modules/nginx-echo/t/echo-after-body.t0000664000000000000000000001002412705233614016277 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (2 * blocks() + 1); no_long_string(); log_level('warn'); #master_on(); #workers(1); run_tests(); __DATA__ === TEST 1: sanity --- http_config postpone_output 1; --- config location /echo { echo_after_body hello; echo world; } --- request GET /echo --- response_body world hello === TEST 2: echo after proxy --- config location /echo { echo_after_body hello; proxy_pass http://127.0.0.1:$server_port$request_uri/more; } location /echo/more { echo world; } --- request GET /echo --- response_body world hello === TEST 3: with variables --- config location /echo { echo_after_body $request_method; echo world; } --- request GET /echo --- response_body world GET === TEST 4: w/o args --- config location /echo { echo_after_body; echo world; } --- request GET /echo --- response_body eval "world\n\n" === TEST 5: order is not important --- config location /reversed { echo world; echo_after_body hello; } --- request GET /reversed --- response_body world hello === TEST 6: multiple echo_after_body instances --- config location /echo { echo_after_body hello; echo_after_body world; echo !; } --- request GET /echo --- response_body ! hello world === TEST 7: multiple echo_after_body instances with multiple echo cmds --- config location /echo { echo_after_body hello; echo_after_body world; echo i; echo say; } --- request GET /echo --- response_body i say hello world === TEST 8: echo-after-body & echo-before-body --- config location /mixed { echo_before_body hello; echo_after_body world; echo_before_body hiya; echo_after_body igor; echo ////////; } --- request GET /mixed --- response_body hello hiya //////// world igor === TEST 9: echo around proxy --- config location /echo { echo_before_body hello; echo_before_body world; #echo $scheme://$host:$server_port$request_uri/more; proxy_pass $scheme://127.0.0.1:$server_port$request_uri/more; echo_after_body hiya; echo_after_body igor; } location /echo/more { echo blah; } --- request GET /echo --- response_body hello world blah hiya igor === TEST 10: with $echo_response_status --- config location /status { echo_after_body "status: $echo_response_status"; return 404; } --- request GET /status --- response_body_like .*404 Not Found.* status: 404$ --- error_code: 404 === TEST 11: in subrequests --- config location /main { echo_location_async /hello; } location /hello { echo_after_body 'world!'; echo 'hello'; } --- request GET /main --- response_body hello world! === TEST 12: echo_after_body + gzip --- config gzip on; gzip_min_length 1; location /main { echo_after_body 'world!'; echo_duplicate 1024 'hello'; } --- request GET /main --- response_body_like hello --- SKIP === TEST 13: echo_after_body + proxy output --- config #gzip on; #gzip_min_length 1; location /main { echo_after_body 'world'; proxy_pass http://127.0.0.1:$server_port/foo; } location /foo { echo_duplicate 10 hello; } --- request GET /main --- response_body_like ^(?:hello){10}world$ === TEST 14: in subrequests (we get last_in_chain set properly) --- config location /main { echo_location_async /hello; } location /hello { echo 'hello'; echo_after_body 'world!'; body_filter_by_lua ' local eof = ngx.arg[2] if eof then print("lua: eof found in body") end '; } --- request GET /main --- response_body hello world! --- log_level: notice --- error_log lua: eof found in body debian/modules/nginx-echo/t/filter-used.t0000664000000000000000000000153312705233614015557 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (3 * blocks()); no_long_string(); log_level('warn'); #master_on(); #workers(1); run_tests(); __DATA__ === TEST 1: filter indeed used --- http_config postpone_output 1; --- config location /echo { echo_after_body hello; echo world; } --- request GET /echo --- stap F(ngx_http_echo_header_filter) { println("echo header filter called") } --- stap_out echo header filter called --- response_body world hello === TEST 2: filter not used --- http_config postpone_output 1; --- config location /echo { #echo_after_body hello; echo world; } --- request GET /echo --- stap F(ngx_http_echo_header_filter) { println("echo header filter called") } --- stap_out --- response_body world debian/modules/nginx-echo/t/if.t0000664000000000000000000000475412705233614013742 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; plan tests => 2 * blocks(); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: sanity (hit) --- config location ^~ /if { set $res miss; if ($arg_val ~* '^a') { set $res hit; echo $res; } echo $res; } --- request GET /if?val=abc --- response_body hit === TEST 2: sanity (miss) --- config location ^~ /if { set $res miss; if ($arg_val ~* '^a') { set $res hit; echo $res; } echo $res; } --- request GET /if?val=bcd --- response_body miss === TEST 3: proxy in if (hit) --- config location ^~ /if { set $res miss; if ($arg_val ~* '^a') { set $res hit; proxy_pass $scheme://127.0.0.1:$server_port/foo?res=$res; } proxy_pass $scheme://127.0.0.1:$server_port/foo?res=$res; } location /foo { echo "res = $arg_res"; } --- request GET /if?val=abc --- response_body res = hit === TEST 4: proxy in if (miss) --- config location ^~ /if { set $res miss; if ($arg_val ~* '^a') { set $res hit; proxy_pass $scheme://127.0.0.1:$server_port/foo?res=$res; } proxy_pass $scheme://127.0.0.1:$server_port/foo?res=$res; } location /foo { echo "res = $arg_res"; } --- request GET /if?val=bcd --- response_body res = miss === TEST 5: if too long url (hit) --- config location /foo { if ($request_uri ~ '.{20,}') { echo too long; } echo ok; } --- request GET /foo?a=12345678901234567890 --- response_body too long === TEST 6: if too long url (miss) --- config location /foo { if ($request_uri ~ '.{20,}') { echo too long; } echo ok; } --- request GET /foo?a=1234567890 --- response_body ok === TEST 7: echo should be inherited by if blocks --- config location /foo { if ($uri ~ 'foo') { } echo ok; } --- request GET /foo --- response_body ok === TEST 8: echo_after_body and echo_before_body should be inherited by if blocks --- config location /foo { if ($uri ~ 'foo') { } echo_before_body -n 'hello'; echo_location /comma; echo_after_body 'world'; } location = /comma { internal; echo -n ', '; } --- request GET /foo --- response_body hello, world debian/modules/nginx-echo/t/incr.t0000664000000000000000000000075512705233614014274 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; plan tests => 2 * blocks(); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: sanity --- config location /main { echo "main pre: $echo_incr"; echo_location_async /sub; echo_location_async /sub; echo "main post: $echo_incr"; } location /sub { echo "sub: $echo_incr"; } --- request GET /main --- response_body main pre: 1 sub: 3 sub: 4 main post: 2 debian/modules/nginx-echo/t/echo-before-body.t0000664000000000000000000001025012705233614016441 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; plan tests => 2 * blocks(); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: sanity --- config location /echo { echo_before_body hello; echo world; } --- request GET /echo --- response_body hello world === TEST 2: echo before proxy --- config location /echo { echo_before_body hello; proxy_pass $scheme://127.0.0.1:$server_port$request_uri/more; } location /echo/more { echo world; } --- request GET /echo --- response_body hello world === TEST 3: with variables --- config location /echo { echo_before_body $request_method; echo world; } --- request GET /echo --- response_body GET world === TEST 4: w/o args --- config location /echo { echo_before_body; echo world; } --- request GET /echo --- response_body eval "\nworld\n" === TEST 5: order is not important --- config location /reversed { echo world; echo_before_body hello; } --- request GET /reversed --- response_body hello world === TEST 6: multiple echo_before_body instances --- config location /echo { echo_before_body hello; echo_before_body world; echo !; } --- request GET /echo --- response_body hello world ! === TEST 7: multiple echo_before_body instances with multiple echo cmds --- config location /echo { echo_before_body hello; echo_before_body world; echo i; echo say; } --- request GET /echo --- response_body hello world i say === TEST 8: with $echo_response_status --- config location /status { echo_before_body "status: $echo_response_status"; return 404; } --- request GET /status --- response_body_like status: 404 .*404 Not Found.*$ --- error_code: 404 === TEST 9: $echo_response_status in echo_before_body in subrequests --- config location /main { echo_location '/status?val=403'; echo_location '/status?val=500'; } location /status { if ($arg_val = 500) { echo_before_body "status: $echo_response_status"; return 500; break; } if ($arg_val = 403) { echo_before_body "status: $echo_response_status"; return 403; break; } return 200; } --- request GET /main --- response_body_like ^status: 403.*?status: 500.*$ === TEST 10: echo -n --- config location /echo { echo_before_body -n hello; echo_before_body -n world; echo ==; } --- request GET /echo --- response_body helloworld== === TEST 11: echo a -n --- config location /echo { echo_before_body a -n hello; echo_before_body b -n world; echo ==; } --- request GET /echo --- response_body a -n hello b -n world == === TEST 12: -n in a var --- config location /echo { set $opt -n; echo_before_body $opt hello; echo_before_body $opt world; echo ==; } --- request GET /echo --- response_body -n hello -n world == === TEST 13: -n only --- config location /echo { echo_before_body -n; echo_before_body -n; echo ==; } --- request GET /echo --- response_body == === TEST 14: -n with an empty string --- config location /echo { echo_before_body -n ""; set $empty ""; echo_before_body -n $empty; echo ==; } --- request GET /echo --- response_body == === TEST 15: -- -n --- config location /echo { echo_before_body -- -n hello; echo_before_body -- -n world; echo ==; } --- request GET /echo --- response_body -n hello -n world == === TEST 16: -n -n --- config location /echo { echo_before_body -n -n hello; echo_before_body -n -n world; echo ==; } --- request GET /echo --- response_body helloworld== === TEST 17: -n -- -n --- config location /echo { echo_before_body -n -- -n hello; echo_before_body -n -- -n world; echo ==; } --- request GET /echo --- response_body -n hello-n world== debian/modules/nginx-echo/t/request-body.t0000664000000000000000000000200312705233614015750 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * 2 * blocks(); run_tests(); __DATA__ === TEST 1: big client body buffered into temp files --- config location /echo { client_body_buffer_size 1k; echo_read_request_body; echo_request_body; } --- request eval "POST /echo " . 'a' x 4096 . 'end'; --- response_body eval 'a' x 4096 . 'end' === TEST 2: in memory request body (trailing echo) --- config location /echo { client_body_buffer_size 1k; echo_read_request_body; echo_request_body; echo done; } --- request POST /echo hello world --- response_body hello worlddone === TEST 3: big client body buffered into temp files (trailing echo) --- config location /echo { client_body_buffer_size 1k; echo_read_request_body; echo_request_body; echo done; } --- request eval "POST /echo " . 'a' x 4096 . "end\n"; --- response_body eval 'a' x 4096 . "enddone\n" debian/modules/nginx-echo/t/blocking-sleep.t0000664000000000000000000000434612705233614016237 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; plan tests => 2 * blocks(); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: sanity --- config location /echo { echo_blocking_sleep 1; } --- request GET /echo --- response_body === TEST 2: fractional delay --- config location /echo { echo_blocking_sleep 0.01; } --- request GET /echo --- response_body === TEST 3: leading echo --- config location /echo { echo before...; echo_blocking_sleep 0.01; } --- request GET /echo --- response_body before... === TEST 4: trailing echo --- config location /echo { echo_blocking_sleep 0.01; echo after...; } --- request GET /echo --- response_body after... === TEST 5: two echos around sleep --- config location /echo { echo before...; echo_blocking_sleep 0.01; echo after...; } --- request GET /echo --- response_body before... after... === TEST 6: interleaving sleep and echo --- config location /echo { echo 1; echo_blocking_sleep 0.01; echo 2; echo_blocking_sleep 0.01; } --- request GET /echo --- response_body 1 2 === TEST 7: interleaving sleep and echo with echo at the end... --- config location /echo { echo 1; echo_blocking_sleep 0.01; echo 2; echo_blocking_sleep 0.01; echo 3; } --- request GET /echo --- response_body 1 2 3 === TEST 8: flush before sleep we didn't really test the actual effect of "echo_flush" here... merely checks if it croaks if appears. --- config location /flush { echo hi; echo_flush; echo_blocking_sleep 0.01; echo trees; } --- request GET /flush --- response_body hi trees === TEST 9: flush does not increment opcode pointer itself --- config location /flush { echo hi; echo_flush; echo trees; } --- request GET /flush --- response_body hi trees === TEST 10: blocking sleep by variable --- config location ~ ^/sleep/(.+) { echo before...; echo_blocking_sleep $1; echo after...; } --- request GET /sleep/0.01 --- response_body before... after... debian/modules/nginx-echo/t/subrequest-async.t0000664000000000000000000002603612705233614016656 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (blocks() * 2 + 1); #$Test::Nginx::LWP::LogLevel = 'debug'; $ENV{TEST_NGINX_HTML_DIR} = html_dir; run_tests(); __DATA__ === TEST 1: sanity - GET --- config location /main { echo_subrequest_async GET /sub; } location /sub { echo "sub method: $echo_request_method"; echo "main method: $echo_client_request_method"; } --- request GET /main --- response_body sub method: GET main method: GET === TEST 2: sanity - DELETE --- config location /main { echo_subrequest_async DELETE /sub; } location /sub { echo "sub method: $echo_request_method"; echo "main method: $echo_client_request_method"; } --- request GET /main --- response_body sub method: DELETE main method: GET === TEST 3: trailing echo --- config location /main { echo_subrequest_async GET /sub; echo after subrequest; } location /sub { echo hello; } --- request GET /main --- response_body hello after subrequest === TEST 4: leading echo --- config location /main { echo before subrequest; echo_subrequest_async GET /sub; } location /sub { echo hello; } --- request GET /main --- response_body before subrequest hello === TEST 5: leading & trailing echo --- config location /main { echo before subrequest; echo_subrequest_async GET /sub; echo after subrequest; } location /sub { echo hello; } --- request GET /main --- response_body before subrequest hello after subrequest === TEST 6: multiple subrequests --- config location /main { echo before sr 1; echo_subrequest_async GET /sub; echo after sr 1; echo before sr 2; echo_subrequest_async GET /sub; echo after sr 2; } location /sub { echo hello; } --- request GET /main --- response_body before sr 1 hello after sr 1 before sr 2 hello after sr 2 === TEST 7: timed multiple subrequests (blocking sleep) --- config location /main { echo_reset_timer; echo_subrequest_async GET /sub1; echo_subrequest_async GET /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_blocking_sleep 0.02; echo hello; } location /sub2 { echo_blocking_sleep 0.01; echo world; } --- request GET /main --- response_body_like ^hello world took 0\.00[0-5] sec for total\.$ === TEST 8: timed multiple subrequests (non-blocking sleep) --- config location /main { echo_reset_timer; echo_subrequest_async GET /sub1; echo_subrequest_async GET /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 0.02; echo hello; } location /sub2 { echo_sleep 0.01; echo world; } --- request GET /main --- response_body_like ^hello world took 0\.00[0-5] sec for total\.$ === TEST 9: location with args --- config location /main { echo_subrequest_async GET /sub -q 'foo=Foo&bar=Bar'; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body Foo Bar === TEST 10: encoded chars in query strings --- config location /main { echo_subrequest_async GET /sub -q 'foo=a%20b&bar=Bar'; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body a%20b Bar === TEST 11: UTF-8 chars in query strings --- config location /main { echo_subrequest_async GET /sub -q 'foo=你好'; } location /sub { echo $arg_foo; } --- request GET /main --- response_body 你好 === TEST 12: encoded chars in location url --- config location /main { echo_subrequest_async GET /sub%31 -q 'foo=Foo&bar=Bar'; } location /sub%31 { echo 'sub%31'; } location /sub1 { echo 'sub1'; } --- request GET /main --- response_body sub1 === TEST 13: querystring in url --- config location /main { echo_subrequest_async GET /sub?foo=Foo&bar=Bar; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body Foo Bar === TEST 14: querystring in url *AND* an explicit querystring --- config location /main { echo_subrequest_async GET /sub?foo=Foo&bar=Bar -q blah=Blah; } location /sub { echo $arg_foo $arg_bar $arg_blah; } --- request GET /main --- response_body Blah === TEST 15: explicit flush in main request flush won't really flush the buffer... --- config location /main_flush { echo 'pre main'; echo_subrequest_async GET /sub; echo 'post main'; echo_flush; } location /sub { echo_sleep 0.02; echo 'sub'; } --- request GET /main_flush --- response_body pre main sub post main === TEST 16: POST subrequest with body (with proxy in the middle) and without read body explicitly --- config location /main { echo_subrequest_async POST /proxy -b 'hello, world'; } location /proxy { proxy_pass $scheme://127.0.0.1:$server_port/sub; } location /sub { echo "sub method: $echo_request_method."; # we need to read body explicitly here...or $echo_request_body # will evaluate to empty ("") echo "sub body: $echo_request_body."; } --- request GET /main --- response_body sub method: POST. sub body: . === TEST 17: POST subrequest with body (with proxy in the middle) and read body explicitly --- config location /main { echo_subrequest_async POST /proxy -b 'hello, world'; } location /proxy { proxy_pass $scheme://127.0.0.1:$server_port/sub; } location /sub { echo "sub method: $echo_request_method."; # we need to read body explicitly here...or $echo_request_body # will evaluate to empty ("") echo_read_request_body; echo "sub body: $echo_request_body."; } --- request GET /main --- response_body sub method: POST. sub body: hello, world. === TEST 18: multiple subrequests --- config location /multi { echo_subrequest_async POST '/sub' -q 'foo=Foo' -b 'hi'; echo_subrequest_async PUT '/sub' -q 'bar=Bar' -b 'hello'; } location /sub { echo "querystring: $query_string"; echo "method: $echo_request_method"; echo "body: $echo_request_body"; echo "content length: $http_content_length"; echo '///'; } --- request GET /multi --- response_body querystring: foo=Foo method: POST body: hi content length: 2 /// querystring: bar=Bar method: PUT body: hello content length: 5 /// === TEST 19: no varaiable inheritance --- config location /main { echo $echo_cacheable_request_uri; echo_subrequest_async GET /sub; echo_subrequest_async GET /sub2; } location /sub { echo $echo_cacheable_request_uri; } location /sub2 { echo $echo_cacheable_request_uri; } --- request GET /main --- response_body /main /sub /sub2 === TEST 20: unsafe uri --- config location /unsafe { echo_subrequest_async GET '/../foo'; } --- request GET /unsafe --- ignore_response --- error_log echo_subrequest_async sees unsafe uri: "/../foo" --- no_error_log [error] [alert] === TEST 21: let subrequest to read the main request's request body --- SKIP --- config location /main { echo_subrequest_async POST /sub; } location /sub { echo_read_request_body; echo_request_body; } --- request POST /main hello, body! --- response_body chomp hello, body! === TEST 22: POST subrequest with file body (relative paths) --- config location /main { echo_subrequest_async POST /sub -f html/blah.txt; } location /sub { echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo_request_body; } --- user_files >>> blah.txt Hello, world --- request GET /main --- response_body sub method: POST Hello, world === TEST 23: POST subrequest with file body (absolute paths) --- config location /main { echo_subrequest_async POST /sub -f $TEST_NGINX_HTML_DIR/blah.txt; } location /sub { echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo_request_body; } --- user_files >>> blah.txt Hello, world! Haha --- request GET /main --- response_body sub method: POST Hello, world! Haha === TEST 24: POST subrequest with file body (file not found) --- config location /main { echo_subrequest_async POST /sub -f html/blah/blah.txt; } location /sub { echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo_request_body; } --- user_files >>> blah.txt Hello, world --- request GET /main --- ignore_response --- error_log eval qr/open\(\) ".*?" failed/ --- no_error_log [alert] === TEST 25: POST subrequest with file body (absolute paths in vars) --- config location /main { set $path $TEST_NGINX_HTML_DIR/blah.txt; echo_subrequest_async POST /sub -f $path; } location /sub { echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo_request_body; } --- user_files >>> blah.txt Hello, world! Haha --- request GET /main --- response_body sub method: POST Hello, world! Haha === TEST 26: leading subrequest & echo_before_body --- config location /main { echo_before_body hello; echo_subrequest_async GET /foo; } location /foo { echo world; } --- request GET /main --- response_body hello world === TEST 27: leading subrequest & xss --- config location /main { default_type 'application/json'; xss_get on; xss_callback_arg c; echo_subrequest_async GET /foo; } location /foo { echo -n world; } --- request GET /main?c=hi --- response_body chop hi(world); === TEST 28: multiple leading subrequest & xss --- config location /main { default_type 'application/json'; xss_get on; xss_callback_arg c; echo_subrequest_async GET /foo; echo_subrequest_async GET /bar; } location /foo { echo -n world; } location /bar { echo -n ' people'; } --- request GET /main?c=hi --- response_body chop hi(world people); === TEST 29: sanity (HEAD) --- config location /main { echo_subrequest_async GET /sub; echo_subrequest_async GET /sub; } location /sub { echo hello; } --- request HEAD /main --- response_body === TEST 30: HEAD subrequest --- config location /main { echo_subrequest_async HEAD /sub; echo_subrequest_async HEAD /sub; } location /sub { echo hello; } --- request GET /main --- response_body debian/modules/nginx-echo/t/echo-timer.t0000664000000000000000000000401012705233614015361 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; plan tests => 2 * blocks(); run_tests(); __DATA__ === TEST 1: timer without explicit reset --- config location /timer { echo_sleep 0.03; echo "elapsed $echo_timer_elapsed sec."; } --- request GET /timer --- response_body_like ^elapsed 0\.0(2[6-9]|3[0-6]) sec\.$ === TEST 2: timer without explicit reset and sleep --- config location /timer { echo "elapsed $echo_timer_elapsed sec."; } --- request GET /timer --- response_body_like ^elapsed 0\.00[0-5] sec\.$ === TEST 3: timing accumulated sleeps --- config location /timer { echo_sleep 0.03; echo_sleep 0.02; echo "elapsed $echo_timer_elapsed sec."; } --- request GET /timer --- response_body_like ^elapsed 0\.0(4[6-9]|5[0-6]) sec\.$ === TEST 4: timer with explicit reset but without sleep --- config location /timer { echo_reset_timer; echo "elapsed $echo_timer_elapsed sec."; } --- request GET /timer --- response_body_like ^elapsed 0\.00[0-5] sec\.$ === TEST 5: reset timer between sleeps --- config location /timer { echo_sleep 0.02; echo "elapsed $echo_timer_elapsed sec."; echo_reset_timer; echo_sleep 0.03; echo "elapsed $echo_timer_elapsed sec."; } --- request GET /timer --- response_body_like ^elapsed 0\.0(1[6-9]|2[0-6]) sec\. elapsed 0\.0(2[6-9]|3[0-6]) sec\.$ === TEST 6: reset timer between blocking sleeps --- config location /timer { echo_blocking_sleep 0.02; echo "elapsed $echo_timer_elapsed sec."; echo_reset_timer; echo_blocking_sleep 0.03; echo "elapsed $echo_timer_elapsed sec."; } --- request GET /timer --- response_body_like ^elapsed 0\.0(1[6-9]|2[0-9]) sec\. elapsed 0\.0(2[6-9]|3[0-6]) sec\.$ === TEST 7: timer without explicit reset --- config location = /timer { return 200 "$echo_timer_elapsed"; } --- request GET /timer --- response_body_like chop ^0(\.0\d*)$ debian/modules/nginx-echo/t/mixed.t0000664000000000000000000000246412705233614014446 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; plan tests => 2 * blocks(); run_tests(); __DATA__ === TEST 1: echo before echo_client_request_headers --- config location /echo { echo "headers:"; echo -n $echo_client_request_headers; } --- request GET /echo --- response_body eval "headers: GET /echo HTTP/1.1\r Host: localhost\r Connection: close\r \r " === TEST 2: echo_client_request_headers before echo --- config location /echo { echo -n $echo_client_request_headers; echo "...these are the headers"; } --- request GET /echo --- response_body eval "GET /echo HTTP/1.1\r Host: localhost\r Connection: close\r \r ...these are the headers " === TEST 3: echo & headers & echo --- config location /echo { echo "headers are"; echo -n $echo_client_request_headers; echo "...these are the headers"; } --- request GET /echo --- response_body eval "headers are GET /echo HTTP/1.1\r Host: localhost\r Connection: close\r \r ...these are the headers " === TEST 4: mixed with echo_duplicate --- config location /mixed { echo hello; echo_duplicate 2 ---; echo_duplicate 1 ' END '; echo_duplicate 2 ---; echo; } --- request GET /mixed --- response_body hello ------ END ------ debian/modules/nginx-echo/t/request-info.t0000664000000000000000000003505112705233614015757 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (3 * blocks() + 15); run_tests(); __DATA__ === TEST 1: standalone directive --- config location /echo { echo -n $echo_client_request_headers; } --- request GET /echo --- response_body eval "GET /echo HTTP/1.1\r Host: localhost\r Connection: close\r \r " --- no_error_log [error] === TEST 2: multiple instances --- config location /echo { echo -n $echo_client_request_headers; echo -n $echo_client_request_headers; } --- request GET /echo --- response_body eval "GET /echo HTTP/1.1\r Host: localhost\r Connection: close\r \r GET /echo HTTP/1.1\r Host: localhost\r Connection: close\r \r " --- no_error_log [error] === TEST 3: does not explicitly request_body --- config location /echo { echo [$echo_request_body]; } --- request POST /echo body here heh --- response_body [] --- no_error_log [error] === TEST 4: let proxy read request_body --- config location /echo { echo_before_body [$echo_request_body]; proxy_pass $scheme://127.0.0.1:$server_port/blah; } location /blah { echo_duplicate 0 ''; } --- request POST /echo body here heh --- response_body [body here heh] --- no_error_log [error] === TEST 5: use echo_read_request_body to read it! --- config location /echo { echo_read_request_body; echo [$echo_request_body]; } --- request POST /echo body here heh --- response_body [body here heh] --- no_error_log [error] === TEST 6: how about sleep after that? --- config location /echo { echo_read_request_body; echo_sleep 0.002; echo [$echo_request_body]; } --- request POST /echo body here heh --- response_body [body here heh] --- no_error_log [error] === TEST 7: echo back the whole client request --- config # echo back the client request location /echoback { echo -n $echo_client_request_headers; echo_read_request_body; echo $echo_request_body; } --- request POST /echoback body here haha --- response_body eval "POST /echoback HTTP/1.1\r Host: localhost\r Connection: close\r Content-Length: 14\r \r body here haha " --- no_error_log [error] === TEST 8: echo_request_body --- config location /body { client_body_buffer_size 5; echo_read_request_body; echo "[$echo_request_body]"; echo_request_body; } --- request eval "POST /body " . ('a' x 2048) . "b" --- response_body eval "[]\n" . ('a' x 2048) . "b" --- no_error_log [error] === TEST 9: $echo_response_status in content handler --- config location /status { echo "status: $echo_response_status"; } --- request GET /status --- response_body status: --- no_error_log [error] === TEST 10: echo_request_body (empty body) --- config location /body { echo_read_request_body; echo_request_body; } location /main { proxy_pass http://127.0.0.1:$server_port/body; } --- request eval "POST /main" --- response_body eval "" --- no_error_log [error] === TEST 11: small header --- config location /t { echo -n $echo_client_request_headers; } --- request GET /t --- response_body eval qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r \r } --- no_error_log [error] --- no_error_log [error] === TEST 12: large header --- config client_header_buffer_size 10; large_client_header_buffers 30 561; location /t { echo -n $echo_client_request_headers; } --- request GET /t --- more_headers eval CORE::join "\n", map { "Header$_: value-$_" } 1..512 --- response_body eval qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r } .(CORE::join "\r\n", map { "Header$_: value-$_" } 1..512) . "\r\n\r\n" --- no_error_log [error] === TEST 13: small header, with leading CRLF --- config location /t { echo -n $echo_client_request_headers; } --- raw_request eval "\r\nGET /t HTTP/1.1\r Host: localhost\r Connection: close\r \r " --- response_body eval qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r \r } --- no_error_log [error] === TEST 14: large header, with leading CRLF --- config client_header_buffer_size 10; large_client_header_buffers 30 561; location /t { echo -n $echo_client_request_headers; } --- raw_request eval "\r\nGET /t HTTP/1.1\r Host: localhost\r Connection: close\r ". (CORE::join "\r\n", map { "Header$_: value-$_" } 1..512) . "\r\n\r\n" --- response_body eval qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r } .(CORE::join "\r\n", map { "Header$_: value-$_" } 1..512) . "\r\n\r\n" --- no_error_log [error] === TEST 15: small header, pipelined --- config location /t { echo -n $echo_client_request_headers; } --- pipelined_requests eval ["GET /t", "GET /th"] --- more_headers Foo: bar --- response_body eval [qq{GET /t HTTP/1.1\r Host: localhost\r Connection: keep-alive\r Foo: bar\r \r }, qq{GET /th HTTP/1.1\r Host: localhost\r Connection: close\r Foo: bar\r \r }] --- no_error_log [error] === TEST 16: large header, pipelined --- config client_header_buffer_size 10; large_client_header_buffers 30 561; location /t { echo -n $echo_client_request_headers; } --- pipelined_requests eval ["GET /t", "GET /t"] --- more_headers eval CORE::join "\n", map { "Header$_: value-$_" } 1..512 --- response_body eval my $headers = (CORE::join "\r\n", map { "Header$_: value-$_" } 1..512) . "\r\n\r\n"; [qq{GET /t HTTP/1.1\r Host: localhost\r Connection: keep-alive\r $headers}, qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r $headers}] --- no_error_log [error] === TEST 17: small header, multi-line header --- config location /t { echo -n $echo_client_request_headers; } --- raw_request eval "GET /t HTTP/1.1\r Host: localhost\r Connection: close\r Foo: bar baz\r blah\r \r " --- response_body eval qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r Foo: bar baz\r blah\r \r } --- no_error_log [error] === TEST 18: large header, multi-line header --- config client_header_buffer_size 10; large_client_header_buffers 50 567; location /t { echo -n $echo_client_request_headers; } --- raw_request eval my $headers = (CORE::join "\r\n", map { "Header$_: value-$_\r\n hello $_ world blah blah" } 1..512) . "\r\n\r\n"; qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r $headers} --- response_body eval qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r } .(CORE::join "\r\n", map { "Header$_: value-$_\r\n hello $_ world blah blah" } 1..512) . "\r\n\r\n" --- no_error_log [error] === TEST 19: small header (POST body) --- config location /t { echo_read_request_body; echo -n $echo_client_request_headers; } --- request POST /t hello --- response_body eval qq{POST /t HTTP/1.1\r Host: localhost\r Connection: close\r Content-Length: 5\r \r } --- no_error_log [error] === TEST 20: small header (POST body) - in subrequests (location) --- config location /t { echo -n $echo_client_request_headers; } location /main { echo_location /t; } --- request POST /main hello --- response_body eval qq{POST /main HTTP/1.1\r Host: localhost\r Connection: close\r Content-Length: 5\r \r } --- no_error_log [error] === TEST 21: large header (POST body) --- config client_header_buffer_size 10; large_client_header_buffers 30 561; location /t { echo_read_request_body; echo -n $echo_client_request_headers; } --- request POST /t hello --- more_headers eval CORE::join"\n", map { "Header$_: value-$_" } 1..512 --- response_body eval qq{POST /t HTTP/1.1\r Host: localhost\r Connection: close\r } .(CORE::join "\r\n", map { "Header$_: value-$_" } 1..512) . "\r\nContent-Length: 5\r\n\r\n" --- no_error_log [error] --- timeout: 5 === TEST 22: large header (POST body) - in subrequests --- config client_header_buffer_size 10; large_client_header_buffers 30 561; location /t { echo_read_request_body; echo -n $echo_client_request_headers; } location /main { echo_location /t; } --- request POST /main hello --- more_headers eval CORE::join"\n", map { "Header$_: value-$_" } 1..512 --- response_body eval qq{POST /main HTTP/1.1\r Host: localhost\r Connection: close\r } .(CORE::join "\r\n", map { "Header$_: value-$_" } 1..512) . "\r\nContent-Length: 5\r\n\r\n" --- no_error_log [error] --- timeout: 5 === TEST 23: raw headers - the default header buffer can hold the request line, but not the header entries --- config location /t { echo_read_request_body; echo -n $echo_client_request_headers; } --- request GET /t --- more_headers eval my $s = "User-Agent: curl\nBah: bah\n"; $s .= "Accept: */*\n"; $s .= "Cookie: " . "C" x 1200 . "\n"; $s --- response_body eval "GET /t HTTP/1.1\r Host: localhost\r Connection: close\r User-Agent: curl\r Bah: bah\r Accept: */*\r Cookie: " . ("C" x 1200) . "\r\n\r\n" --- no_error_log [error] === TEST 24: small header (POST body) - in subrequests (location_async) --- config location /t { echo -n $echo_client_request_headers; } location /main { echo_location_async /t; } --- request POST /main hello --- response_body eval qq{POST /main HTTP/1.1\r Host: localhost\r Connection: close\r Content-Length: 5\r \r } --- no_error_log [error] === TEST 25: small header (POST body) - in subrequests (subrequest) --- config location /t { echo -n $echo_client_request_headers; } location /main { echo_subrequest GET /t; } --- request POST /main hello --- response_body eval qq{POST /main HTTP/1.1\r Host: localhost\r Connection: close\r Content-Length: 5\r \r } --- no_error_log [error] === TEST 26: small header (POST body) - in subrequests (subrequest_async) --- config location /t { echo -n $echo_client_request_headers; } location /main { echo_subrequest_async GET /t; } --- request POST /main hello --- response_body eval qq{POST /main HTTP/1.1\r Host: localhost\r Connection: close\r Content-Length: 5\r \r } --- no_error_log [error] === TEST 27: ngx_proxy/ngx_fastcgi/etc change r->header_end to point to their own buffers --- config location = /t { proxy_buffering off; proxy_pass http://127.0.0.1:$server_port/bad; proxy_intercept_errors on; error_page 500 = /500; } location = /bad { return 500; } location = /500 { echo -n $echo_client_request_headers; } --- request GET /t --- response_body eval "GET /t HTTP/1.1\r Host: localhost\r Connection: close\r \r " --- no_error_log [error] === TEST 28: ngx_proxy/ngx_fastcgi/etc change r->header_end to point to their own buffers (exclusive LF in the request data) --- config location = /t { proxy_buffering off; proxy_pass http://127.0.0.1:$server_port/bad; proxy_intercept_errors on; error_page 500 = /500; } location = /bad { return 500; } location = /500 { internal; echo -n $echo_client_request_headers; } --- raw_request eval "GET /t HTTP/1.1 Host: localhost Connection: close Content-Length: 5 hello" --- response_body eval "GET /t HTTP/1.1 Host: localhost Connection: close Content-Length: 5 " --- no_error_log [error] === TEST 29: ngx_proxy/ngx_fastcgi/etc change r->header_end to point to their own buffers (mixed LF and CRLF in the request data) --- config location = /t { proxy_buffering off; proxy_pass http://127.0.0.1:$server_port/bad; proxy_intercept_errors on; error_page 500 = /500; } location = /bad { return 500; } location = /500 { internal; echo -n $echo_client_request_headers; } --- raw_request eval "GET /t HTTP/1.1\r Host: localhost Connection: close\r Content-Length: 5\r hello" --- response_body eval "GET /t HTTP/1.1\r Host: localhost Connection: close\r Content-Length: 5\r " --- no_error_log [error] === TEST 30: ngx_proxy/ngx_fastcgi/etc change r->header_end to point to their own buffers (another way of mixing LF and CRLF in the request data) --- config location = /t { proxy_buffering off; proxy_pass http://127.0.0.1:$server_port/bad; proxy_intercept_errors on; error_page 500 = /500; } location = /bad { return 500; } location = /500 { internal; echo -n $echo_client_request_headers; } --- raw_request eval "GET /t HTTP/1.1\r Host: localhost Connection: close\r Content-Length: 5 \r hello" --- response_body eval "GET /t HTTP/1.1\r Host: localhost Connection: close\r Content-Length: 5 \r " --- no_error_log [error] === TEST 31: two pipelined requests with large headers --- config client_header_buffer_size 10; large_client_header_buffers 3 5610; location /t { echo -n $echo_client_request_headers; } --- pipelined_requests eval ["GET /t", "GET /t"] --- more_headers eval CORE::join "\n", map { "Header$_: value-$_" } 1..585 --- response_body eval [qq{GET /t HTTP/1.1\r Host: localhost\r Connection: keep-alive\r } .(CORE::join "\r\n", map { "Header$_: value-$_" } 1..585) . "\r\n\r\n", qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r } .(CORE::join "\r\n", map { "Header$_: value-$_" } 1..585) . "\r\n\r\n", , ] --- no_error_log [error] --- timeout: 5 === TEST 32: a request with large header and a smaller pipelined request following --- config client_header_buffer_size 10; large_client_header_buffers 2 1921; location /t { echo -n $echo_client_request_headers; } --- pipelined_requests eval ["GET /t", "GET /t"] --- more_headers eval [CORE::join("\n", map { "Header$_: value-$_" } 1..170), "Foo: bar\n"] --- response_body eval [qq{GET /t HTTP/1.1\r Host: localhost\r Connection: keep-alive\r } .(CORE::join "\r\n", map { "Header$_: value-$_" } 1..170) . "\r\n\r\n", qq{GET /t HTTP/1.1\r Host: localhost\r Connection: close\r Foo: bar\r \r }, ] --- no_error_log [error] --- timeout: 5 === TEST 33: a request with large header and a smaller pipelined request following --- config client_header_buffer_size 10; large_client_header_buffers 2 1921; location /t { echo -n $echo_client_request_headers; } --- pipelined_requests eval ["GET /t", "GET /t" . ("a" x 512)] --- more_headers eval [CORE::join("\n", map { "Header$_: value-$_" } 1..170), "Foo: bar\n"] --- response_body eval [qq{GET /t HTTP/1.1\r Host: localhost\r Connection: keep-alive\r } .(CORE::join "\r\n", map { "Header$_: value-$_" } 1..170) . "\r\n\r\n", qq{GET /t} . ("a" x 512) . qq{ HTTP/1.1\r Host: localhost\r Connection: close\r Foo: bar\r \r }, ] --- no_error_log [error] --- timeout: 5 debian/modules/nginx-echo/t/location.t0000664000000000000000000002155412705233614015151 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (2 * blocks() + 2); #$Test::Nginx::LWP::LogLevel = 'debug'; #no_diff(); run_tests(); __DATA__ === TEST 1: sanity --- config location /main { echo_location /sub; } location /sub { echo hello; } --- request GET /main --- response_body hello === TEST 2: sanity with proxy in the middle --- config location /main { echo_location /proxy; } location /proxy { proxy_pass $scheme://127.0.0.1:$server_port/sub; } location /sub { echo hello; } --- request GET /main --- response_body hello === TEST 3: trailing echo --- config location /main { echo_location /sub; echo after subrequest; } location /sub { echo hello; } --- request GET /main --- response_body hello after subrequest === TEST 4: leading echo --- config location /main { echo before subrequest; echo_location /sub; } location /sub { echo hello; } --- request GET /main --- response_body before subrequest hello === TEST 5: leading & trailing echo --- config location /main { echo before subrequest; echo_location /sub; echo after subrequest; } location /sub { echo hello; } --- request GET /main --- response_body before subrequest hello after subrequest === TEST 6: multiple subrequests --- config location /main { echo before sr 1; echo_location /sub; echo after sr 1; echo before sr 2; echo_location /sub; echo after sr 2; } location /sub { echo hello; } --- request GET /main --- response_body before sr 1 hello after sr 1 before sr 2 hello after sr 2 === TEST 7: timed multiple subrequests (blocking sleep) --- config location /main { echo_reset_timer; echo_location /sub1; echo_location /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_blocking_sleep 0.02; echo hello; } location /sub2 { echo_blocking_sleep 0.01; echo world; } --- request GET /main --- response_body_like ^hello world took 0\.0(?:2[5-9]|3[0-5]) sec for total\.$ === TEST 8: timed multiple subrequests (non-blocking sleep) --- config location /main { echo_reset_timer; echo_location /sub1; echo_location /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 0.02; echo hello; } location /sub2 { echo_sleep 0.01; echo world; } --- request GET /main --- response_body_like ^hello world took 0\.0(?:2[5-9]|3[0-6]) sec for total\.$ === TEST 9: location with args --- config location /main { echo_location /sub 'foo=Foo&bar=Bar'; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body Foo Bar === TEST 10: chained subrequests --- config location /main { echo 'pre main'; echo_location /sub; echo 'post main'; } location /sub { echo 'pre sub'; echo_location /subsub; echo 'post sub'; } location /subsub { echo 'subsub'; } --- request GET /main --- response_body pre main pre sub subsub post sub post main === TEST 11: chained subrequests using named locations as of 0.8.20, ngx_http_subrequest still does not support named location. sigh. this case is a TODO. --- config location /main { echo 'pre main'; echo_location @sub; echo 'post main'; } location @sub { echo 'pre sub'; echo_location @subsub; echo 'post sub'; } location @subsub { echo 'subsub'; } --- request GET /main --- response_body pre main pre sub subsub post sub post main --- SKIP === TEST 12: explicit flush in main request --- config location /main { echo 'pre main'; echo_location /sub; echo 'post main'; echo_flush; } location /sub { echo_sleep 0.02; echo 'sub'; } --- request GET /main --- response_body pre main sub post main === TEST 13: no varaiable inheritance --- config location /main { echo $echo_cacheable_request_uri; echo_location /sub; echo_location /sub2; } location /sub { echo $echo_cacheable_request_uri; } location /sub2 { echo $echo_cacheable_request_uri; } --- request GET /main --- response_body /main /sub /sub2 === TEST 14: unsafe uri --- config location /unsafe { echo_location '/../foo'; } --- request GET /unsafe --- ignore_response --- error_log echo_location sees unsafe uri: "/../foo" --- no_error_log [error] [alert] === TEST 15: querystring in url --- config location /main { echo_location /sub?foo=Foo&bar=Bar; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body Foo Bar === TEST 16: querystring in url *AND* an explicit querystring --- config location /main { echo_location /sub?foo=Foo&bar=Bar blah=Blah; } location /sub { echo $arg_foo $arg_bar $arg_blah; } --- request GET /main --- response_body Blah === TEST 17: let subrequest to read the main request's request body --- SKIP --- config location /main { echo_location /sub; } location /sub { echo_read_request_body; echo_request_body; } --- request POST /main hello, body! --- response_body chomp hello, body! === TEST 18: sleep after location --- config location /main { echo_location /sub; echo_sleep 0.001; echo_location /sub; } location /sub { echo_sleep 0.001; echo sub; } --- request GET /main --- response_body sub sub --- skip_nginx: 2: < 0.8.11 === TEST 19: deep nested echo_location/echo_location_async --- config location /main { echo_location /bar; echo_location_async /bar; echo_location_async /bar; echo_location /group; echo_location_async /group; } location /group { echo_location /bar; echo_location_async /bar; } location /bar { #echo_sleep 0.001; echo $echo_incr; } --- request GET /main --- response_body 1 2 3 4 5 6 7 --- timeout: 2 === TEST 20: deep nested echo_location/echo_location_async (with sleep) --- config location /main { echo_location /bar; echo_location_async /bar; echo_location_async /bar; echo_location /group; echo_location_async /group; } location /group { echo_location /baz; echo_location_async /bah; } location ~ '^/ba[rzh]' { echo_sleep 0.001; echo $echo_incr; } --- request GET /main --- response_body 1 2 3 4 5 6 7 --- timeout: 2 === TEST 21: deep nested echo_location (with sleep) --- config location /main { echo_location /bar; echo_location /bar; echo_location /bar; echo_location /group; echo_location /group; } location /group { echo_location /bar; echo_location /bar; } location /incr { echo_sleep 0.001; echo $echo_incr; } location /bar { proxy_pass $scheme://127.0.0.1:$server_port/incr; } --- request GET /main --- response_body 1 1 1 1 1 1 1 --- timeout: 5 --- no_error_log [error] === TEST 22: leading subrequest & echo_before_body --- config location /main { echo_before_body hello; echo_location /foo; } location /foo { echo world; } --- request GET /main --- response_body hello world === TEST 23: leading subrequest & xss --- config location /main { default_type 'application/json'; xss_get on; xss_callback_arg c; echo_location /foo; } location /foo { echo -n world; } --- request GET /main?c=hi --- response_body chop hi(world); === TEST 24: multiple leading subrequest & xss --- config location /main { default_type 'application/json'; xss_get on; xss_callback_arg c; echo_location /foo; echo_location /bar; } location /main2 { content_by_lua ' local res = ngx.location.capture("/foo") local res2 = ngx.location.capture("/bar") ngx.say(res.body) ngx.say(res2.body) '; } location /foo { echo -n world; } location /bar { echo -n ' people'; } --- request GET /main?c=hi --- response_body chop hi(world people); === TEST 25: sanity (HEAD) --- config location /main { echo_location /sub; echo_location /sub; } location /sub { echo hello; } --- request HEAD /main --- response_body debian/modules/nginx-echo/t/echo.t0000664000000000000000000001321612705233614014253 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (2 * blocks() + 5); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: sanity --- config location /echo { echo hello; } --- request GET /echo --- response_body hello === TEST 2: multiple args --- config location /echo { echo say hello world; } --- request GET /echo --- response_body say hello world === TEST 3: multiple directive instances --- config location /echo { echo say that; echo hello; echo world !; } --- request GET /echo --- response_body say that hello world ! === TEST 4: echo without arguments --- config location /echo { echo; echo; } --- request GET /echo --- response_body eval "\n\n" === TEST 5: escaped newline --- config location /echo { echo "hello\nworld"; } --- request GET /echo --- response_body hello world === TEST 6: escaped tabs and \r and " wihtin "..." --- config location /echo { echo "i say \"hello\tworld\"\r"; } --- request GET /echo --- response_body eval: "i say \"hello\tworld\"\r\n" === TEST 7: escaped tabs and \r and " in single quotes --- config location /echo { echo 'i say \"hello\tworld\"\r'; } --- request GET /echo --- response_body eval: "i say \"hello\tworld\"\r\n" === TEST 8: escaped tabs and \r and " w/o any quotes --- config location /echo { echo i say \"hello\tworld\"\r; } --- request GET /echo --- response_body eval: "i say \"hello\tworld\"\r\n" === TEST 9: escaping $ As of Nginx 0.8.20, there's still no way to escape the '$' character. --- config location /echo { echo \$; } --- request GET /echo --- response_body $ --- SKIP === TEST 10: XSS --- config location /blah { echo_duplicate 1 "$arg_callback("; echo_location_async "/data?$uri"; echo_duplicate 1 ")"; } location /data { echo_duplicate 1 '{"dog":"$query_string"}'; } --- request GET /blah/9999999.json?callback=ding1111111 --- response_body chomp ding1111111({"dog":"/blah/9999999.json"}) === TEST 11: XSS - filter version --- config location /blah { echo_before_body "$arg_callback("; echo_duplicate 1 '{"dog":"$uri"}'; echo_after_body ")"; } --- request GET /blah/9999999.json?callback=ding1111111 --- response_body ding1111111( {"dog":"/blah/9999999.json"}) === TEST 12: if --- config location /first { echo "before"; echo_location_async /second $request_uri; echo "after"; } location = /second { if ($query_string ~ '([^?]+)') { set $memcached_key $1; # needing this to be keyed on the request_path, not the entire uri echo $memcached_key; } } --- request GET /first/9999999.json?callback=ding1111111 --- response_body before /first/9999999.json after === TEST 13: echo -n --- config location /echo { echo -n hello; echo -n world; } --- request GET /echo --- response_body chop helloworld === TEST 14: echo a -n --- config location /echo { echo a -n hello; echo b -n world; } --- request GET /echo --- response_body a -n hello b -n world === TEST 15: -n in a var --- config location /echo { set $opt -n; echo $opt hello; echo $opt world; } --- request GET /echo --- response_body -n hello -n world === TEST 16: -n only --- config location /echo { echo -n; echo -n; } --- request GET /echo --- response_body chop === TEST 17: -n with an empty string --- config location /echo { echo -n ""; set $empty ""; echo -n $empty; } --- request GET /echo --- response_body chop === TEST 18: -- -n --- config location /echo { echo -- -n hello; echo -- -n world; } --- request GET /echo --- response_body -n hello -n world === TEST 19: -n -n --- config location /echo { echo -n -n hello; echo -n -n world; } --- request GET /echo --- response_body chop helloworld === TEST 20: -n -- -n --- config location /echo { echo -n -- -n hello; echo -n -- -n world; } --- request GET /echo --- response_body chop -n hello-n world === TEST 21: proxy --- config location /main { proxy_pass http://127.0.0.1:$server_port/echo; } location /echo { echo hello; echo world; } --- request GET /main --- response_headers !Content-Length --- response_body hello world === TEST 22: if is evil --- config location /test { set $a 3; set_by_lua $a ' if ngx.var.a == "3" then return 4 end '; echo $a; } --- request GET /test --- response_body 4 --- SKIP === TEST 23: HEAD --- config location /echo { echo hello; echo world; } --- request HEAD /echo --- response_body === TEST 24: POST --- config location /echo { echo hello; echo world; } --- pipelined_requests eval ["POST /echo blah blah", "POST /echo foo bar baz"] --- response_body eval ["hello\nworld\n","hello\nworld\n"] === TEST 25: POST --- config location /echo { echo_sleep 0.001; echo hello; echo world; } --- pipelined_requests eval ["POST /echo blah blah", "POST /echo foo bar baz"] --- response_body eval ["hello\nworld\n","hello\nworld\n"] === TEST 26: empty arg after -n (github issue #33) --- config location = /t { set $empty ""; echo -n $empty hello world; } --- request GET /t --- response_body chop hello world debian/modules/nginx-echo/t/foreach-split.t0000664000000000000000000001162012705233614016072 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * 2 * blocks(); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: sanity --- config location /main { echo_foreach_split '&' $query_string; echo_location_async $echo_it; echo '/* end */'; echo_end; } location /sub/1.css { echo "body { font-size: 12pt; }"; } location /sub/2.css { echo "table { color: 'red'; }"; } --- request GET /main?/sub/1.css&/sub/2.css --- response_body body { font-size: 12pt; } /* end */ table { color: 'red'; } /* end */ === TEST 2: split in a url argument (echo_location_async) --- config location /main_async { echo_foreach_split ',' $arg_cssfiles; echo_location_async $echo_it; echo_end; } location /foo.css { echo foo; } location /bar.css { echo bar; } location /baz.css { echo baz; } --- request GET /main_async?cssfiles=/foo.css,/bar.css,/baz.css --- response_body foo bar baz === TEST 3: split in a url argument (echo_location) --- config location /main_sync { echo_foreach_split ',' $arg_cssfiles; echo_location $echo_it; echo_end; } location /foo.css { echo foo; } location /bar.css { echo bar; } location /baz.css { echo baz; } --- request GET /main_sync?cssfiles=/foo.css,/bar.css,/baz.css --- response_body foo bar baz --- SKIP === TEST 4: empty loop --- config location /main { echo "start"; echo_foreach_split ',' $arg_cssfiles; echo_end; echo "end"; } --- request GET /main?cssfiles=/foo.css,/bar.css,/baz.css --- response_body start end === TEST 5: trailing delimiter --- config location /main_t { echo_foreach_split ',' $arg_cssfiles; echo_location_async $echo_it; echo_end; } location /foo.css { echo foo; } --- request GET /main_t?cssfiles=/foo.css, --- response_body foo === TEST 6: multi-char delimiter --- config location /main_sleep { echo_foreach_split '-a-' $arg_list; echo $echo_it; echo_end; } --- request GET /main_sleep?list=foo-a-bar-a-baz --- error_code: 500 --- response_body_like: 500 Internal Server Error === TEST 7: multi-char delimiter (the right way) --- config location /main_sleep { echo_foreach_split -- '-a-' $arg_list; echo $echo_it; echo_end; } --- request GET /main_sleep?list=foo-a-bar-a-baz --- response_body foo bar baz === TEST 8: loop with sleep --- config location /main_sleep { echo_foreach_split '-' $arg_list; echo_sleep 0.001; echo $echo_it; echo_end; } --- request GET /main_sleep?list=foo-a-bar-A-baz --- response_body foo a bar A baz === TEST 9: empty --- config location /merge { default_type 'text/javascript'; echo_foreach_split '&' $query_string; echo "/* JS File $echo_it */"; echo_location_async $echo_it; echo; echo_end; } --- request GET /merge --- response_body === TEST 10: single & --- config location /merge { default_type 'text/javascript'; echo_foreach_split '&' $query_string; echo "/* JS File $echo_it */"; echo_location_async $echo_it; echo; echo_end; } --- request GET /merge?& --- response_body === TEST 11: pure &'s --- config location /merge { default_type 'text/javascript'; echo_foreach_split '&' $query_string; echo "/* JS File $echo_it */"; echo_location_async $echo_it; echo; echo_end; } --- request GET /merge?&&& --- response_body === TEST 12: pure & and spaces TODO: needs to uri_decode $echo_it... --- config location /merge { default_type 'text/javascript'; echo_foreach_split '&' $query_string; echo "/* JS File $echo_it */"; echo_location_async $echo_it; echo; echo_end; } --- request GET /merge?&%20&%20& --- response_body --- SKIP === TEST 13: multiple foreach_split --- config location /multi { echo_foreach_split '&' $query_string; echo [$echo_it]; echo_end; echo '...'; echo_foreach_split '-' $query_string; echo [$echo_it]; echo_end; } --- request GET /multi?a-b&c-d --- response_body [a-b] [c-d] ... [a] [b&c] [d] === TEST 14: github issue #2: setting a variable from $echo_it results to crashing --- config location = /getFile { set $filelist "a,b,c"; echo_foreach_split ',' $filelist; set $file $echo_it; echo_subrequest GET '/getFile2' -q 'sha256=$file'; echo_end; } location = /getFile2 { echo "sha256: $arg_sha256"; } --- request GET /getFile --- response_body sha256: sha256: sha256: debian/modules/nginx-echo/t/status.t0000664000000000000000000000361612705233614014663 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(1); plan tests => repeat_each() * (2 * blocks()); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: 200 --- config location /echo { echo_status 200; echo hello; } --- request GET /echo --- response_body hello --- error_code: 200 === TEST 2: if location (200) --- config location /echo { set $true 1; if ($true) { } echo_status 200; echo hello; } --- request GET /echo --- response_body hello --- error_code: 200 === TEST 3: 404 --- config location /echo { echo_status 404; echo hello; } --- request GET /echo --- response_body hello --- error_code: 404 === TEST 4: if location (404) --- config location /echo { set $true 1; if ($true) { } echo_status 404; echo hello; } --- request GET /echo --- response_body hello --- error_code: 404 === TEST 5: 500 --- config location /echo { echo_status 500; echo hello; } --- request GET /echo --- response_body hello --- error_code: 500 === TEST 6: if location (500) --- config location /echo { set $true 1; if ($true) { } echo_status 500; echo hello; } --- request GET /echo --- response_body hello --- error_code: 500 === TEST 7: if location (500) no inherit --- config location /echo { set $true 1; if ($true) { echo_status 503; } echo_status 500; echo hello; } --- request GET /echo --- response_body hello --- error_code: 503 === TEST 8: subrequest --- config location /echo { echo_location /sub; echo_status 503; } location /sub { echo blah blah; } --- request GET /echo --- response_body blah blah --- error_code: 503 debian/modules/nginx-echo/t/echo-duplicate.t0000664000000000000000000000225512705233614016224 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; plan tests => 2 * blocks(); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: sanity --- config location /dup { echo_duplicate 3 a; } --- request GET /dup --- response_body: aaa === TEST 2: abc abc --- config location /dup { echo_duplicate 2 abc; } --- request GET /dup --- response_body: abcabc === TEST 3: big size with underscores --- config location /dup { echo_duplicate 10_000 A; } --- request GET /dup --- response_body eval 'A' x 10_000 === TEST 4: 0 duplicate 0 empty strings --- config location /dup { echo_duplicate 0 ""; } --- request GET /dup --- response_body === TEST 5: 0 duplicate non-empty strings --- config location /dup { echo_duplicate 0 "abc"; } --- request GET /dup --- response_body === TEST 6: duplication of empty strings --- config location /dup { echo_duplicate 2 ""; } --- request GET /dup --- response_body === TEST 7: sanity (HEAD) --- config location /dup { echo_duplicate 3 a; } --- request HEAD /dup --- response_body debian/modules/nginx-echo/t/gzip.t0000664000000000000000000000075312705233614014310 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(1); plan tests => repeat_each() * 2 * blocks(); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: sanity --- config location /gzip { gzip on; gzip_min_length 10; gzip_types text/plain; echo_duplicate 1000 hello; } --- request GET /gzip --- more_headers Accept-Encoding: gzip --- response_headers Content-Encoding: gzip --- timeout: 20 debian/modules/nginx-echo/t/exec.t0000664000000000000000000000645112705233614014264 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (2 * blocks() + 1); #$Test::Nginx::LWP::LogLevel = 'debug'; run_tests(); __DATA__ === TEST 1: exec normal location --- config location /main { echo_exec /bar; echo end; } location = /bar { echo "$echo_request_uri:"; echo bar; } --- request GET /main --- response_body /bar: bar === TEST 2: location with args (inlined in uri) --- config location /main { echo_exec /bar?a=32; echo end; } location /bar { echo "a: [$arg_a]"; } --- request GET /main --- response_body a: [32] === TEST 3: location with args (in separate arg) --- config location /main { echo_exec /bar a=56; echo end; } location /bar { echo "a: [$arg_a]"; } --- request GET /main --- response_body a: [56] === TEST 4: exec named location --- config location /main { echo_exec @bar; echo end; } location @bar { echo bar; } --- request GET /main --- response_body bar === TEST 5: query string ignored for named locations --- config location /main { echo_exec @bar?a=32; echo end; } location @bar { echo "a: [$arg_a]"; } --- request GET /main --- response_body a: [] --- error_log querystring a=32 ignored when exec'ing named location @bar === TEST 6: query string ignored for named locations --- config location /foo { echo_exec @bar; } location @bar { echo "uri: [$echo_request_uri]"; } --- request GET /foo --- response_body uri: [/foo] === TEST 7: exec(named location) in subrequests --- config location /entry { echo_location /foo; echo_sleep 0.001; echo_location /foo2; } location /foo { echo_exec @bar; } location /foo2 { echo_exec @bar; } location @bar { proxy_pass http://127.0.0.1:$server_port/bar; } location /bar { echo_sleep 0.01; echo hello; } --- request GET /entry --- response_body hello hello === TEST 8: exec(normal loctions) in subrequests --- config location /entry { echo_location /foo; echo_sleep 0.001; echo_location /foo2; } location /foo { echo_exec /baz; } location /foo2 { echo_exec /baz; } location /baz { proxy_pass http://127.0.0.1:$server_port/bar; } location /bar { echo_sleep 0.01; echo hello; } --- request GET /entry --- response_body hello hello === TEST 9: exec should clear ctx --- config location @bar { echo hello; echo world; echo heh; } location /foo { #echo_sleep 0.001; echo_reset_timer; echo_exec @bar; } --- request GET /foo --- response_body hello world heh === TEST 10: reset ctx --- config location @proxy { rewrite_by_lua return; echo hello; } location /main { rewrite_by_lua return; echo_exec @proxy; } --- request GET /main --- response_body hello === TEST 11: yield before exec --- config location @bar { echo hello; echo world; echo heh; } location /foo { echo_sleep 0.001; echo_exec @bar; } --- request GET /foo --- response_body hello world heh debian/modules/nginx-echo/t/unused.t0000664000000000000000000000331412705233614014636 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (5 * blocks()); no_long_string(); log_level('warn'); #master_on(); #workers(1); run_tests(); __DATA__ === TEST 1: filters used --- http_config postpone_output 1; --- config location /echo { echo world; echo_after_body hello; } --- request GET /echo?blah --- response_body world hello --- error_log echo header filter, uri "/echo?blah" echo body filter, uri "/echo?blah" --- no_error_log [error] --- log_level: debug === TEST 2: filters not used --- http_config postpone_output 1; --- config location /echo { echo world; #echo_after_body hello; } --- request GET /echo?blah --- response_body world --- no_error_log echo header filter, uri "/echo?blah" echo body filter, uri "/echo?blah" [error] --- log_level: debug === TEST 3: (after) filters used (multiple http {} blocks) --- http_config postpone_output 1; --- config location /echo { echo world; echo_after_body hello; } --- post_main_config http { } --- request GET /echo?blah --- response_body world hello --- error_log echo header filter, uri "/echo?blah" echo body filter, uri "/echo?blah" --- no_error_log [error] --- log_level: debug === TEST 4: (before) filters used (multiple http {} blocks) --- http_config postpone_output 1; --- config location /echo { echo world; echo_before_body hello; } --- post_main_config http { } --- request GET /echo?blah --- response_body hello world --- error_log echo header filter, uri "/echo?blah" echo body filter, uri "/echo?blah" --- no_error_log [error] --- log_level: debug debian/modules/nginx-echo/t/subrequest.t0000664000000000000000000003257012705233614015543 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (2 * blocks() + 1); $ENV{TEST_NGINX_HTML_DIR} = html_dir; $ENV{TEST_NGINX_CLIENT_PORT} ||= server_port(); run_tests(); __DATA__ === TEST 1: sanity --- config location /main { echo_subrequest GET /sub; } location /sub { echo hello; } --- request GET /main --- response_body hello === TEST 2: trailing echo --- config location /main { echo_subrequest GET /sub; echo after subrequest; } location /sub { echo hello; } --- request GET /main --- response_body hello after subrequest === TEST 3: leading echo --- config location /main { echo before subrequest; echo_subrequest GET /sub; } location /sub { echo hello; } --- request GET /main --- response_body before subrequest hello === TEST 4: leading & trailing echo --- config location /main { echo before subrequest; echo_subrequest GET /sub; echo after subrequest; } location /sub { echo hello; } --- request GET /main --- response_body before subrequest hello after subrequest === TEST 5: multiple subrequests --- config location /main { echo before sr 1; echo_subrequest GET /sub; echo after sr 1; echo before sr 2; echo_subrequest GET /sub; echo after sr 2; } location /sub { echo hello; } --- request GET /main --- response_body before sr 1 hello after sr 1 before sr 2 hello after sr 2 === TEST 6: timed multiple subrequests (blocking sleep) --- config location /main { echo_reset_timer; echo_subrequest GET /sub1; echo_subrequest GET /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_blocking_sleep 0.02; echo hello; } location /sub2 { echo_blocking_sleep 0.01; echo world; } --- request GET /main --- response_body_like ^hello world took 0\.0(?:2[5-9]|3[0-5]) sec for total\.$ === TEST 7: timed multiple subrequests (non-blocking sleep) --- config location /main { echo_reset_timer; echo_subrequest GET /sub1; echo_subrequest GET /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 0.02; echo hello; } location /sub2 { echo_sleep 0.01; echo world; } --- request GET /main --- response_body_like ^hello world took 0\.0(?:2[5-9]|3[0-6]) sec for total\.$ === TEST 8: location with args --- config location /main { echo_subrequest GET /sub -q 'foo=Foo&bar=Bar'; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body Foo Bar === TEST 9: chained subrequests --- config location /main { echo 'pre main'; echo_subrequest GET /sub; echo 'post main'; } location /sub { echo 'pre sub'; echo_subrequest GET /subsub; echo 'post sub'; } location /subsub { echo 'subsub'; } --- request GET /main --- response_body pre main pre sub subsub post sub post main === TEST 10: chained subrequests using named locations as of 0.8.20, ngx_http_subrequest still does not support named location. sigh. this case is a TODO. --- config location /main { echo 'pre main'; echo_subrequest GET @sub; echo 'post main'; } location @sub { echo 'pre sub'; echo_subrequest GET @subsub; echo 'post sub'; } location @subsub { echo 'subsub'; } --- request GET /main --- response_body pre main pre sub subsub post sub post main --- SKIP === TEST 11: explicit flush in main request --- config location /main { echo 'pre main'; echo_subrequest GET /sub; echo 'post main'; echo_flush; } location /sub { echo_sleep 0.02; echo 'sub'; } --- request GET /main --- response_body pre main sub post main === TEST 12: DELETE subrequest --- config location /main { echo_subrequest DELETE /sub; } location /sub { echo "sub method: $echo_request_method"; echo "main method: $echo_client_request_method"; } --- request GET /main --- response_body sub method: DELETE main method: GET === TEST 13: DELETE subrequest --- config location /main { echo "main method: $echo_client_request_method"; echo_subrequest GET /proxy; echo_subrequest DELETE /proxy; } location /proxy { proxy_pass $scheme://127.0.0.1:$server_port/sub; } location /sub { echo "sub method: $echo_request_method"; } --- request GET /main --- response_body main method: GET sub method: GET sub method: DELETE === TEST 14: POST subrequest with body --- config location /main { echo_subrequest POST /sub -b 'hello, world'; } location /sub { echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo "sub body: $echo_request_body"; } --- request GET /main --- response_body sub method: POST sub body: hello, world === TEST 15: POST subrequest with body (explicitly read the body) --- config location /main { echo_subrequest POST /sub -b 'hello, world'; } location /sub { echo "sub method: $echo_request_method"; # we call echo_read_client_body explicitly here even # though it's not necessary. echo_read_request_body; echo "sub body: $echo_request_body"; } --- request GET /main --- response_body sub method: POST sub body: hello, world === TEST 16: POST subrequest with body (with proxy in the middle) and without read body explicitly --- config location /main { echo_subrequest POST /proxy -b 'hello, world'; } location /proxy { proxy_pass $scheme://127.0.0.1:$server_port/sub; } location /sub { echo "sub method: $echo_request_method."; # we need to read body explicitly here...or $echo_request_body # will evaluate to empty ("") echo "sub body: $echo_request_body."; } --- request GET /main --- response_body sub method: POST. sub body: . === TEST 17: POST subrequest with body (with proxy in the middle) and read body explicitly --- config location /main { echo_subrequest POST /proxy -b 'hello, world'; } location /proxy { proxy_pass $scheme://127.0.0.1:$server_port/sub; } location /sub { echo "sub method: $echo_request_method."; # we need to read body explicitly here...or $echo_request_body # will evaluate to empty ("") echo_read_request_body; echo "sub body: $echo_request_body."; } --- request GET /main --- response_body sub method: POST. sub body: hello, world. === TEST 18: multiple subrequests --- config location /multi { echo_subrequest POST '/sub' -q 'foo=Foo' -b 'hi'; echo_subrequest PUT '/sub' -q 'bar=Bar' -b 'hello'; } location /sub { echo "querystring: $query_string"; echo "method: $echo_request_method"; echo "body: $echo_request_body"; echo "content length: $http_content_length"; echo '///'; } --- request GET /multi --- response_body querystring: foo=Foo method: POST body: hi content length: 2 /// querystring: bar=Bar method: PUT body: hello content length: 5 /// === TEST 19: unsafe uri --- config location /unsafe { echo_subrequest GET '/../foo'; } --- request GET /unsafe --- ignore_response --- error_log echo_subrequest sees unsafe uri: "/../foo" --- no_error_log [error] === TEST 20: querystring in url --- config location /main { echo_subrequest GET /sub?foo=Foo&bar=Bar; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body Foo Bar === TEST 21: querystring in url *AND* an explicit querystring --- config location /main { echo_subrequest GET /sub?foo=Foo&bar=Bar -q blah=Blah; } location /sub { echo $arg_foo $arg_bar $arg_blah; } --- request GET /main --- response_body Blah === TEST 22: let subrequest to read the main request's request body --- SKIP --- config location /main { echo_subrequest POST /sub; } location /sub { echo_read_request_body; echo_request_body; } --- request POST /main hello, body! --- response_body chomp hello, body! === TEST 23: deep nested echo_subrequest/echo_subrequest_async --- config location /main { echo_subrequest GET /bar; echo_subrequest_async GET /bar; echo_subrequest_async GET /bar; echo_subrequest GET /group; echo_subrequest_async GET /group; } location /group { echo_subrequest GET /bar; echo_subrequest_async GET /bar; } location /bar { echo $echo_incr; } --- request GET /main --- response_body 1 2 3 4 5 6 7 === TEST 24: deep nested echo_subrequest/echo_subrequest_async --- config location /main { echo_subrequest GET /bar?a; echo_subrequest_async GET /bar?b; echo_subrequest_async GET /bar?c; echo_subrequest GET /group?a=d&b=e; echo_subrequest_async GET /group?a=f&b=g; } location /group { echo_subrequest GET /bar?$arg_a; echo_subrequest_async GET /bar?$arg_b; } location /bar { echo -n $query_string; } --- request GET /main --- response_body: abcdefg --- timeout: 2 === TEST 25: POST subrequest with file body (relative paths) --- config location /main { echo_subrequest POST /sub -f html/blah.txt; } location /sub { echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo_request_body; } --- user_files >>> blah.txt Hello, world --- request GET /main --- response_body sub method: POST Hello, world === TEST 26: POST subrequest with file body (absolute paths) --- config location /main { echo_subrequest POST /sub -f $TEST_NGINX_HTML_DIR/blah.txt; } location /sub { echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo_request_body; } --- user_files >>> blah.txt Hello, world! Haha --- request GET /main --- response_body sub method: POST Hello, world! Haha === TEST 27: POST subrequest with file body (file not found) --- config location /main { echo_subrequest POST /sub -f html/blah/blah.txt; } location /sub { echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo_request_body; } --- user_files >>> blah.txt Hello, world --- request GET /main --- ignore_response --- error_log eval qr/open\(\) ".*?" failed/ --- no_error_log [alert] === TEST 28: leading subrequest & echo_before_body --- config location /main { echo_before_body hello; echo_subrequest GET /foo; } location /foo { echo world; } --- request GET /main --- response_body hello world === TEST 29: leading subrequest & xss --- config location /main { default_type 'application/json'; xss_get on; xss_callback_arg c; echo_subrequest GET /foo; } location /foo { echo -n world; } --- request GET /main?c=hi --- response_body chop hi(world); === TEST 30: multiple leading subrequest & xss --- config location /main { default_type 'application/json'; xss_get on; xss_callback_arg c; echo_subrequest GET /foo; echo_subrequest GET /bar; } location /foo { echo -n world; } location /bar { echo -n ' people'; } --- request GET /main?c=hi --- response_body chop hi(world people); === TEST 31: sanity (HEAD) --- config location /main { echo_subrequest GET /sub; echo_subrequest GET /sub; } location /sub { echo hello; } --- request HEAD /main --- response_body === TEST 32: POST subrequest to ngx_proxy --- config location /hello { default_type text/plain; echo_subrequest POST '/proxy' -q 'foo=Foo&bar=baz' -b 'request_body=test&test=3'; } location /proxy { proxy_pass http://127.0.0.1:$TEST_NGINX_CLIENT_PORT/sub; #proxy_pass http://127.0.0.1:1113/sub; } location /sub { echo_read_request_body; echo "sub method: $echo_request_method"; # we don't need to call echo_read_client_body explicitly here echo "sub body: $echo_request_body"; } --- request GET /hello --- response_body sub method: POST sub body: request_body=test&test=3 === TEST 33: HEAD subrequest --- config location /main { echo_subrequest HEAD /sub; echo_subrequest HEAD /sub; } location /sub { echo hello; } --- request GET /main --- response_body === TEST 34: method name as an nginx variable (github issue #34) --- config location ~ ^/delay/(?[0-9.]+)/(?.*)$ { # echo_blocking_sleep $delay; echo_subrequest '$echo_request_method' '/$originalURL' -q '$args'; } location /api { echo "args: $args"; } --- request GET /delay/0.343/api/?a=b --- response_body args: a=b --- no_error_log [error] debian/modules/nginx-echo/t/location-async.t0000664000000000000000000001613612705233614016264 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (2 * blocks() + 1); run_tests(); __DATA__ === TEST 1: sanity --- config location /main { echo_location_async /sub; } location /sub { echo hello; } --- request GET /main --- response_body hello === TEST 2: trailing echo --- config location /main { echo_location_async /sub; echo after subrequest; } location /sub { echo hello; } --- request GET /main --- response_body hello after subrequest === TEST 3: leading echo --- config location /main { echo before subrequest; echo_location_async /sub; } location /sub { echo hello; } --- request GET /main --- response_body before subrequest hello === TEST 4: leading & trailing echo --- config location /main { echo before subrequest; echo_location_async /sub; echo after subrequest; } location /sub { echo hello; } --- request GET /main --- response_body before subrequest hello after subrequest === TEST 5: multiple subrequests --- config location /main { echo before sr 1; echo_location_async /sub; echo after sr 1; echo before sr 2; echo_location_async /sub; echo after sr 2; } location /sub { echo hello; } --- request GET /main --- response_body before sr 1 hello after sr 1 before sr 2 hello after sr 2 === TEST 6: timed multiple subrequests (blocking sleep) --- config location /main { echo_reset_timer; echo_location_async /sub1; echo_location_async /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_blocking_sleep 0.02; echo hello; } location /sub2 { echo_blocking_sleep 0.01; echo world; } --- request GET /main --- response_body_like ^hello world took 0\.00[0-5] sec for total\.$ === TEST 7: timed multiple subrequests (non-blocking sleep) --- config location /main { echo_reset_timer; echo_location_async /sub1; echo_location_async /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 0.02; echo hello; } location /sub2 { echo_sleep 0.01; echo world; } --- request GET /main --- response_body_like ^hello world took 0\.00[0-5] sec for total\.$ === TEST 8: location with args --- config location /main { echo_location_async /sub 'foo=Foo&bar=Bar'; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body Foo Bar === TEST 9: encoded chars in query strings --- config location /main { echo_location_async /sub 'foo=a%20b&bar=Bar'; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body a%20b Bar === TEST 10: UTF-8 chars in query strings --- config location /main { echo_location_async /sub 'foo=你好'; } location /sub { echo $arg_foo; } --- request GET /main --- response_body 你好 === TEST 11: encoded chars in location url --- config location /main { echo_location_async /sub%31 'foo=Foo&bar=Bar'; } location /sub%31 { echo 'sub%31'; } location /sub1 { echo 'sub1'; } --- request GET /main --- response_body sub1 === TEST 12: querystring in url --- config location /main { echo_location_async /sub?foo=Foo&bar=Bar; } location /sub { echo $arg_foo $arg_bar; } --- request GET /main --- response_body Foo Bar === TEST 13: querystring in url *AND* an explicit querystring --- config location /main { echo_location_async /sub?foo=Foo&bar=Bar blah=Blah; } location /sub { echo $arg_foo $arg_bar $arg_blah; } --- request GET /main --- response_body Blah === TEST 14: explicit flush in main request flush won't really flush the buffer... --- config location /main_flush { echo 'pre main'; echo_location_async /sub; echo 'post main'; echo_flush; } location /sub { echo_sleep 0.02; echo 'sub'; } --- request GET /main_flush --- response_body pre main sub post main === TEST 15: no varaiable inheritance --- config location /main { echo $echo_cacheable_request_uri; echo_location_async /sub; echo_location_async /sub2; } location /sub { echo $echo_cacheable_request_uri; } location /sub2 { echo $echo_cacheable_request_uri; } --- request GET /main --- response_body /main /sub /sub2 === TEST 16: unsafe uri --- config location /unsafe { echo_location_async '/../foo'; } --- request GET /unsafe --- stap2 F(ngx_http_send_header) { printf("send header on req %p (header sent: %d)\n", $r, $r->header_sent) print_ubacktrace() } --- ignore_response --- error_log echo_location_async sees unsafe uri: "/../foo" --- no_error_log [error] [alert] === TEST 17: access/deny (access phase handlers skipped in subrequests) --- config location /main { echo_location_async /denied; } location /denied { deny all; echo No no no; } --- request GET /main --- error_code: 200 --- response_body No no no === TEST 18: rewrite is honored. --- config location /main { echo_location_async /rewrite; } location /rewrite { rewrite ^ /foo break; echo $uri; } --- request GET /main --- response_body /foo === TEST 19: let subrequest to read the main request's request body --- SKIP --- config location /main { echo_location_async /sub; } location /sub { echo_read_request_body; echo_request_body; } --- request POST /main hello, body! --- response_body chomp hello, body! === TEST 20: leading subrequest & echo_before_body --- config location /main { echo_before_body hello; echo_location_async /foo; } location /foo { echo world; } --- request GET /main --- response_body hello world === TEST 21: leading subrequest & xss --- config location /main { default_type 'application/json'; xss_get on; xss_callback_arg c; echo_location_async /foo; } location /foo { echo -n world; } --- request GET /main?c=hi --- response_body chop hi(world); === TEST 22: multiple leading subrequest & xss --- config location /main { default_type 'application/json'; xss_get on; xss_callback_arg c; echo_location_async /foo; echo_location_async /bar; } location /foo { echo -n world; } location /bar { echo -n ' people'; } --- request GET /main?c=hi --- response_body chop hi(world people); === TEST 23: sanity (HEAD) --- config location /main { echo_location_async /sub; echo_location_async /sub; } location /sub { echo hello; } --- request HEAD /main --- response_body debian/modules/nginx-echo/t/sleep.t0000664000000000000000000000546012705233614014447 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::Socket; plan tests => 2 * blocks(); run_tests(); __DATA__ === TEST 1: sanity --- config location /echo { echo_sleep 1; } --- request GET /echo --- response_body === TEST 2: fractional delay --- config location /echo { echo_sleep 0.01; } --- request GET /echo --- response_body === TEST 3: leading echo --- config location /echo { echo before...; echo_sleep 0.01; } --- request GET /echo --- response_body before... === TEST 4: trailing echo --- config location /echo { echo_sleep 0.01; echo after...; } --- request GET /echo --- response_body after... === TEST 5: two echos around sleep --- config location /echo { echo before...; echo_sleep 0.01; echo after...; } --- request GET /echo --- response_body before... after... === TEST 6: interleaving sleep and echo --- config location /echo { echo 1; echo_sleep 0.01; echo 2; echo_sleep 0.01; } --- request GET /echo --- response_body 1 2 === TEST 7: interleaving sleep and echo with echo at the end... --- config location /echo { echo 1; echo_sleep 0.01; echo 2; echo_sleep 0.01; echo 3; } --- request GET /echo --- response_body 1 2 3 === TEST 8: flush before sleep we didn't really test the actual effect of "echo_flush" here... merely checks if it croaks if appears. --- config location /flush { echo hi; echo_flush; echo_sleep 0.01; echo trees; } --- request GET /flush --- response_body hi trees === TEST 9: flush does not increment opcode pointer itself --- config location /flush { echo hi; echo_flush; echo trees; } --- request GET /flush --- response_body hi trees === TEST 10: sleep through a proxy this reveals a bug in v0.19 and the bug is fixed in v0.20. --- config location /proxy { proxy_pass $scheme://127.0.0.1:$server_port/entry'; } location /entry { echo_sleep 0.001; echo done; } --- request GET /proxy --- response_body_like done === TEST 11: abnormally quit --- config location /quit { echo before; echo_flush; echo_sleep 1; echo after; } --- request GET /quit --- response_body before after === TEST 12: two echos around sleep (HEAD) --- config location /echo { echo before...; echo_sleep 0.01; echo after...; } --- request HEAD /echo --- response_body === TEST 13: sleep by variable --- config location ~ ^/sleep/(.+) { echo before...; echo_sleep $1; echo after...; } --- request GET /sleep/0.01 --- response_body before... after... debian/modules/nginx-echo/t/abort-parent.t0000664000000000000000000000211312705233614015725 0ustar # vi:filetype= use lib 'lib'; use Test::Nginx::LWP skip_all => 'not working at all'; plan tests => 2 * blocks(); run_tests(); __DATA__ === TEST 1: sanity --- config location /abort { echo hello; echo_flush; echo_location_async '/foo'; echo_location_async '/bar'; echo_location_async '/baz'; echo world; echo_flush; } location /proxy { proxy_pass "http://127.0.0.1:$server_port/sleep?$query_string"; } location /sleep { echo_sleep $arg_sleep; echo $arg_echo; echo_flush; } location /foo { echo_location '/proxy?sleep=1&echo=foo'; #echo_flush; echo_abort_parent; } location /bar { proxy_pass 'http://127.0.0.1:$server_port/sleep_bar'; } location /baz { proxy_pass 'http://127.0.0.1:$server_port/sleep_baz'; } location /sleep_bar { echo_sleep 2; echo bar; } location /sleep_baz { echo_sleep 3; echo baz; } --- request GET /abort --- response_body hello bar debian/modules/nginx-echo/README.markdown0000664000000000000000000015221212705233614015406 0ustar Name ==== **ngx_echo** - Brings "echo", "sleep", "time", "exec" and more shell-style goodies to Nginx config file. *This module is not distributed with the Nginx source.* See [the installation instructions](#installation). Table of Contents ================= * [Status](#status) * [Version](#version) * [Synopsis](#synopsis) * [Description](#description) * [Content Handler Directives](#content-handler-directives) * [echo](#echo) * [echo_duplicate](#echo_duplicate) * [echo_flush](#echo_flush) * [echo_sleep](#echo_sleep) * [echo_blocking_sleep](#echo_blocking_sleep) * [echo_reset_timer](#echo_reset_timer) * [echo_read_request_body](#echo_read_request_body) * [echo_location_async](#echo_location_async) * [echo_location](#echo_location) * [echo_subrequest_async](#echo_subrequest_async) * [echo_subrequest](#echo_subrequest) * [echo_foreach_split](#echo_foreach_split) * [echo_end](#echo_end) * [echo_request_body](#echo_request_body) * [echo_exec](#echo_exec) * [echo_status](#echo_status) * [Filter Directives](#filter-directives) * [echo_before_body](#echo_before_body) * [echo_after_body](#echo_after_body) * [Variables](#variables) * [$echo_it](#echo_it) * [$echo_timer_elapsed](#echo_timer_elapsed) * [$echo_request_body](#echo_request_body) * [$echo_request_method](#echo_request_method) * [$echo_client_request_method](#echo_client_request_method) * [$echo_client_request_headers](#echo_client_request_headers) * [$echo_cacheable_request_uri](#echo_cacheable_request_uri) * [$echo_request_uri](#echo_request_uri) * [$echo_incr](#echo_incr) * [$echo_response_status](#echo_response_status) * [Installation](#installation) * [Compatibility](#compatibility) * [Known Issues](#known-issues) * [Modules that use this module for testing](#modules-that-use-this-module-for-testing) * [Community](#community) * [English Mailing List](#english-mailing-list) * [Chinese Mailing List](#chinese-mailing-list) * [Report Bugs](#report-bugs) * [Source Repository](#source-repository) * [Changes](#changes) * [Test Suite](#test-suite) * [TODO](#todo) * [Getting involved](#getting-involved) * [Author](#author) * [Copyright & License](#copyright--license) * [See Also](#see-also) Status ====== This module is production ready. Version ======= This document describes ngx_echo [v0.57](https://github.com/agentzh/echo-nginx-module/tags) released on 21 November 2014. Synopsis ======== ```nginx location /hello { echo "hello, world!"; } ``` ```nginx location /hello { echo -n "hello, "; echo "world!"; } ``` ```nginx location /timed_hello { echo_reset_timer; echo hello world; echo "'hello world' takes about $echo_timer_elapsed sec."; echo hiya igor; echo "'hiya igor' takes about $echo_timer_elapsed sec."; } ``` ```nginx location /echo_with_sleep { echo hello; echo_flush; # ensure the client can see previous output immediately echo_sleep 2.5; # in sec echo world; } ``` ```nginx # in the following example, accessing /echo yields # hello # world # blah # hiya # igor location /echo { echo_before_body hello; echo_before_body world; proxy_pass $scheme://127.0.0.1:$server_port$request_uri/more; echo_after_body hiya; echo_after_body igor; } location /echo/more { echo blah; } ``` ```nginx # the output of /main might be # hello # world # took 0.000 sec for total. # and the whole request would take about 2 sec to complete. location /main { echo_reset_timer; # subrequests in parallel echo_location_async /sub1; echo_location_async /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 2; echo hello; } location /sub2 { echo_sleep 1; echo world; } ``` ```nginx # the output of /main might be # hello # world # took 3.003 sec for total. # and the whole request would take about 3 sec to complete. location /main { echo_reset_timer; # subrequests in series (chained by CPS) echo_location /sub1; echo_location /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 2; echo hello; } location /sub2 { echo_sleep 1; echo world; } ``` ```nginx # Accessing /dup gives # ------ END ------ location /dup { echo_duplicate 3 "--"; echo_duplicate 1 " END "; echo_duplicate 3 "--"; echo; } ``` ```nginx # /bighello will generate 1000,000,000 hello's. location /bighello { echo_duplicate 1000_000_000 'hello'; } ``` ```nginx # echo back the client request location /echoback { echo_duplicate 1 $echo_client_request_headers; echo "\r"; echo_read_request_body; echo_request_body; } ``` ```nginx # GET /multi will yields # querystring: foo=Foo # method: POST # body: hi # content length: 2 # /// # querystring: bar=Bar # method: PUT # body: hello # content length: 5 # /// location /multi { echo_subrequest_async POST '/sub' -q 'foo=Foo' -b 'hi'; echo_subrequest_async PUT '/sub' -q 'bar=Bar' -b 'hello'; } location /sub { echo "querystring: $query_string"; echo "method: $echo_request_method"; echo "body: $echo_request_body"; echo "content length: $http_content_length"; echo '///'; } ``` ```nginx # GET /merge?/foo.js&/bar/blah.js&/yui/baz.js will merge the .js resources together location /merge { default_type 'text/javascript'; echo_foreach_split '&' $query_string; echo "/* JS File $echo_it */"; echo_location_async $echo_it; echo; echo_end; } ``` ```nginx # accessing /if?val=abc yields the "hit" output # while /if?val=bcd yields "miss": location ^~ /if { set $res miss; if ($arg_val ~* '^a') { set $res hit; echo $res; } echo $res; } ``` [Back to TOC](#table-of-contents) Description =========== This module wraps lots of Nginx internal APIs for streaming input and output, parallel/sequential subrequests, timers and sleeping, as well as various meta data accessing. Basically it provides various utilities that help testing and debugging of other modules by trivially emulating different kinds of faked subrequest locations. People will also find it useful in real-world applications that need to 1. serve static contents directly from memory (loading from the Nginx config file). 1. wrap the upstream response with custom header and footer (kinda like the [addition module](http://nginx.org/en/docs/http/ngx_http_addition_module.html) but with contents read directly from the config file and Nginx variables). 1. merge contents of various "Nginx locations" (i.e., subrequests) together in a single main request (using [echo_location](#echo_location) and its friends). This is a special dual-role module that can *lazily* serve as a content handler or register itself as an output filter only upon demand. By default, this module does not do anything at all. Technially, this module has also demonstrated the following techniques that might be helpful for module writers: 1. Issue parallel subreqeusts directly from content handler. 1. Issue chained subrequests directly from content handler, by passing continuation along the subrequest chain. 1. Issue subrequests with all HTTP 1.1 methods and even an optional faked HTTP request body. 1. Interact with the Nginx event model directly from content handler using custom events and timers, and resume the content handler back if necessary. 1. Dual-role module that can (lazily) serve as a content handler or an output filter or both. 1. Nginx config file variable creation and interpolation. 1. Streaming output control using output_chain, flush and its friends. 1. Read client request body from the content handler, and returns back (asynchronously) to the content handler after completion. 1. Use Perl-based declarative [test suite](#test-suite) to drive the development of Nginx C modules. [Back to TOC](#table-of-contents) Content Handler Directives ========================== Use of the following directives register this module to the current Nginx location as a content handler. If you want to use another module, like the [standard proxy module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html), as the content handler, use the [filter directives](#filter-directives) provided by this module. All the content handler directives can be mixed together in a single Nginx location and they're supposed to run sequentially just as in the Bash scripting language. Every content handler directive supports variable interpolation in its arguments (if any). The MIME type set by the [standard default_type directive](http://nginx.org/en/docs/http/ngx_http_core_module.html#default_type) is respected by this module, as in: ```nginx location /hello { default_type text/plain; echo hello; } ``` Then on the client side: ```bash $ curl -I 'http://localhost/echo' HTTP/1.1 200 OK Server: nginx/0.8.20 Date: Sat, 17 Oct 2009 03:40:19 GMT Content-Type: text/plain Connection: keep-alive ``` Since the [v0.22](#v022) release, all of the directives are allowed in the [rewrite module](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html)'s [if](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if) directive block, for instance: ```nginx location ^~ /if { set $res miss; if ($arg_val ~* '^a') { set $res hit; echo $res; } echo $res; } ``` [Back to TOC](#table-of-contents) echo ---- **syntax:** *echo [options] <string>...* **default:** *no* **context:** *location, location if* **phase:** *content* Sends arguments joined by spaces, along with a trailing newline, out to the client. Note that the data might be buffered by Nginx's underlying buffer. To force the output data flushed immediately, use the [echo_flush](#echo_flush) command just after `echo`, as in ```nginx echo hello world; echo_flush; ``` When no argument is specified, *echo* emits the trailing newline alone, just like the *echo* command in shell. Variables may appear in the arguments. An example is ```nginx echo The current request uri is $request_uri; ``` where [$request_uri](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_uri) is a variable exposed by the [ngx_http_core_module](http://nginx.org/en/docs/http/ngx_http_core_module.html). This command can be used multiple times in a single location configuration, as in ```nginx location /echo { echo hello; echo world; } ``` The output on the client side looks like this ```bash $ curl 'http://localhost/echo' hello world ``` Special characters like newlines (`\n`) and tabs (`\t`) can be escaped using C-style escaping sequences. But a notable exception is the dollar sign (`$`). As of Nginx 0.8.20, there's still no clean way to esacpe this characters. (A work-around might be to use a `$echo_dollor` variable that is always evaluated to the constant `$` character. This feature will possibly be introduced in a future version of this module.) As of the echo [v0.28](#v028) release, one can suppress the trailing newline character in the output by using the `-n` option, as in ```nginx location /echo { echo -n "hello, "; echo "world"; } ``` Accessing `/echo` gives ```bash $ curl 'http://localhost/echo' hello, world ``` Leading `-n` in variable values won't take effect and will be emitted literally, as in ```nginx location /echo { set $opt -n; echo $opt "hello,"; echo "world"; } ``` This gives the following output ```bash $ curl 'http://localhost/echo' -n hello, world ``` One can output leading `-n` literals and other options using the special `--` option like this ```nginx location /echo { echo -- -n is an option; } ``` which yields ```bash $ curl 'http://localhost/echo' -n is an option ``` [Back to TOC](#table-of-contents) echo_duplicate -------------- **syntax:** *echo_duplicate <count> <string>* **default:** *no* **context:** *location, location if* **phase:** *content* Outputs duplication of a string indicated by the second argument, using the times specified in the first argument. For instance, ```nginx location /dup { echo_duplicate 3 "abc"; } ``` will lead to an output of `"abcabcabc"`. Underscores are allowed in the count number, just like in Perl. For example, to emit 1000,000,000 instances of `"hello, world"`: ```nginx location /many_hellos { echo_duplicate 1000_000_000 "hello, world"; } ``` The `count` argument could be zero, but not negative. The second `string` argument could be an empty string ("") likewise. Unlike the [echo](#echo) directive, no trailing newline is appended to the result. So it's possible to "abuse" this directive as a no-trailing-newline version of [echo](#echo) by using "count" 1, as in ```nginx location /echo_art { echo_duplicate 2 '---'; echo_duplicate 1 ' END '; # we don't want a trailing newline here echo_duplicate 2 '---'; echo; # we want a trailing newline here... } ``` You get ```bash ------ END ------ ``` This directive was first introduced in [version 0.11](#v011). [Back to TOC](#table-of-contents) echo_flush ---------- **syntax:** *echo_flush* **default:** *no* **context:** *location, location if* **phase:** *content* Forces the data potentially buffered by underlying Nginx output filters to send immediately to the client side via socket. Note that techically the command just emits a ngx_buf_t object with `flush` slot set to 1, so certain weird third-party output filter module could still block it before it reaches Nginx's (last) write filter. This directive does not take any argument. Consider the following example: ```nginx location /flush { echo hello; echo_flush; echo_sleep 1; echo world; } ``` Then on the client side, using curl to access `/flush`, you'll see the "hello" line immediately, but only after 1 second, the last "world" line. Without calling `echo_flush` in the example above, you'll most likely see no output until 1 second is elapsed due to the internal buffering of Nginx. This directive will fail to flush the output buffer in case of subrequests get involved. Consider the following example: ```nginx location /main { echo_location_async /sub; echo hello; echo_flush; } location /sub { echo_sleep 1; } ``` Then the client won't see "hello" appear even if `echo_flush` has been executed before the subrequest to `/sub` has actually started executing. The outputs of `/main` that are sent *after* [echo_location_async](#echo_location_async) will be postponed and buffered firmly. This does *not* apply to outputs sent before the subrequest initiated. For a modified version of the example given above: ```nginx location /main { echo hello; echo_flush; echo_location_async /sub; } location /sub { echo_sleep 1; } ``` The client will immediately see "hello" before `/sub` enters sleeping. See also [echo](#echo), [echo_sleep](#echo_sleep), and [echo_location_async](#echo_location_async). [Back to TOC](#table-of-contents) echo_sleep ---------- **syntax:** *echo_sleep <seconds>* **default:** *no* **context:** *location, location if* **phase:** *content* Sleeps for the time period specified by the argument, which is in seconds. This operation is non-blocking on server side, so unlike the [echo_blocking_sleep](#echo_blocking_sleep) directive, it won't block the whole Nginx worker process. The period might takes three digits after the decimal point and must be greater than 0.001. An example is ```nginx location /echo_after_sleep { echo_sleep 1.234; echo resumed!; } ``` Behind the scene, it sets up a per-request "sleep" ngx_event_t object, and adds a timer using that custom event to the Nginx event model and just waits for a timeout on that event. Because the "sleep" event is per-request, this directive can work in parallel subrequests. [Back to TOC](#table-of-contents) echo_blocking_sleep ------------------- **syntax:** *echo_blocking_sleep <seconds>* **default:** *no* **context:** *location, location if* **phase:** *content* This is a blocking version of the [echo_sleep](#echo_sleep) directive. See the documentation of [echo_sleep](#echo_sleep) for more detail. Behind the curtain, it calls the ngx_msleep macro provided by the Nginx core which maps to usleep on POSIX-compliant systems. Note that this directive will block the current Nginx worker process completely while being executed, so never use it in production environment. [Back to TOC](#table-of-contents) echo_reset_timer ---------------- **syntax:** *echo_reset_timer* **default:** *no* **context:** *location, location if* **phase:** *content* Reset the timer begin time to *now*, i.e., the time when this command is executed during request. The timer begin time is default to the starting time of the current request and can be overridden by this directive, potentially multiple times in a single location. For example: ```nginx location /timed_sleep { echo_sleep 0.03; echo "$echo_timer_elapsed sec elapsed."; echo_reset_timer; echo_sleep 0.02; echo "$echo_timer_elapsed sec elapsed."; } ``` The output on the client side might be ```bash $ curl 'http://localhost/timed_sleep' 0.032 sec elapsed. 0.020 sec elapsed. ``` The actual figures you get on your side may vary a bit due to your system's current activities. Invocation of this directive will force the underlying Nginx timer to get updated to the current system time (regardless the timer resolution specified elsewhere in the config file). Furthermore, references of the [$echo_timer_elapsed](#echo_timer_elapsed) variable will also trigger timer update forcibly. See also [echo_sleep](#echo_sleep) and [$echo_timer_elapsed](#echo_timer_elapsed). [Back to TOC](#table-of-contents) echo_read_request_body ---------------------- **syntax:** *echo_read_request_body* **default:** *no* **context:** *location, location if* **phase:** *content* Explicitly reads request body so that the [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) variable will always have non-empty values (unless the body is so big that it has been saved by Nginx to a local temporary file). Note that this might not be the original client request body because the current request might be a subrequest with a "artificial" body specified by its parent. This directive does not generate any output itself, just like [echo_sleep](#echo_sleep). Here's an example for echo'ing back the original HTTP client request (both headers and body are included): ```nginx location /echoback { echo_duplicate 1 $echo_client_request_headers; echo "\r"; echo_read_request_body; echo $request_body; } ``` The content of `/echoback` looks like this on my side (I was using Perl's LWP utility to access this location on the server): ```bash $ (echo hello; echo world) | lwp-request -m POST 'http://localhost/echoback' POST /echoback HTTP/1.1 TE: deflate,gzip;q=0.3 Connection: TE, close Host: localhost User-Agent: lwp-request/5.818 libwww-perl/5.820 Content-Length: 12 Content-Type: application/x-www-form-urlencoded hello world ``` Because `/echoback` is the main request, [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) holds the original client request body. Before Nginx 0.7.56, it makes no sense to use this directive because [$request_body](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_body) was first introduced in Nginx 0.7.58. This directive itself was first introduced in the echo module's [v0.14 release](#v014). [Back to TOC](#table-of-contents) echo_location_async ------------------- **syntax:** *echo_location_async <location> [<url_args>]* **default:** *no* **context:** *location, location if* **phase:** *content* Issue GET subrequest to the location specified (first argument) with optional url arguments specified in the second argument. As of Nginx 0.8.20, the `location` argument does *not* support named location, due to a limitation in the `ngx_http_subrequest` function. The same is true for its brother, the [echo_location](#echo_location) directive. A very simple example is ```nginx location /main { echo_location_async /sub; echo world; } location /sub { echo hello; } ``` Accessing `/main` gets ```bash hello world ``` Calling multiple locations in parallel is also possible: ```nginx location /main { echo_reset_timer; echo_location_async /sub1; echo_location_async /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 2; # sleeps 2 sec echo hello; } location /sub2 { echo_sleep 1; # sleeps 1 sec echo world; } ``` Accessing `/main` yields ```bash $ time curl 'http://localhost/main' hello world took 0.000 sec for total. real 0m2.006s user 0m0.000s sys 0m0.004s ``` You can see that the main handler `/main` does *not* wait the subrequests `/sub1` and `/sub2` to complete and quickly goes on, hence the "0.000 sec" timing result. The whole request, however takes approximately 2 sec in total to complete because `/sub1` and `/sub2` run in parallel (or "concurrently" to be more accurate). If you use [echo_blocking_sleep](#echo_blocking_sleep) in the previous example instead, then you'll get the same output, but with 3 sec total response time, because "blocking sleep" blocks the whole Nginx worker process. Locations can also take an optional querystring argument, for instance ```nginx location /main { echo_location_async /sub 'foo=Foo&bar=Bar'; } location /sub { echo $arg_foo $arg_bar; } ``` Accessing `/main` yields ```bash $ curl 'http://localhost/main' Foo Bar ``` Querystrings is *not* allowed to be concatenated onto the `location` argument with "?" directly, for example, `/sub?foo=Foo&bar=Bar` is an invalid location, and shouldn't be fed as the first argument to this directive. Technically speaking, this directive is an example that Nginx content handler issues one or more subrequests directly. AFAIK, the [fancyindex module](https://connectical.com/projects/ngx-fancyindex/wiki) also does such kind of things ;) Nginx named locations like `@foo` is *not* supported here. This directive is logically equivalent to the GET version of [echo_subrequest_async](#echo_subrequest_async). For example, ```nginx echo_location_async /foo 'bar=Bar'; ``` is logically equivalent to ```nginx echo_subrequest_async GET /foo -q 'bar=Bar'; ``` But calling this directive is slightly faster than calling [echo_subrequest_async](#echo_subrequest_async) using `GET` because we don't have to parse the HTTP method names like `GET` and options like `-q`. There is a known issue with this directive when disabling the standard [standard SSI module](http://nginx.org/en/docs/http/ngx_http_ssi_module.html). See [Known Issues](#known-issues) for more details. This directive is first introduced in [version 0.09](#v009) of this module and requires at least Nginx 0.7.46. [Back to TOC](#table-of-contents) echo_location ------------- **syntax:** *echo_location <location> [<url_args>]* **default:** *no* **context:** *location, location if* **phase:** *content* Just like the [echo_location_async](#echo_location_async) directive, but `echo_location` issues subrequests *in series* rather than in parallel. That is, the content handler directives following this directive won't be executed until the subrequest issued by this directive completes. The final response body is almost always equivalent to the case when [echo_location_async](#echo_location_async) is used instead, only if timing variables is used in the outputs. Consider the following example: ```nginx location /main { echo_reset_timer; echo_location /sub1; echo_location /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 2; echo hello; } location /sub2 { echo_sleep 1; echo world; } ``` The location `/main` above will take for total 3 sec to complete (compared to 2 sec if [echo_location_async](#echo_location_async) is used instead here). Here's the result in action on my machine: ```bash $ curl 'http://localhost/main' hello world took 3.003 sec for total. real 0m3.027s user 0m0.020s sys 0m0.004s ``` This directive is logically equivalent to the GET version of [echo_subrequest](#echo_subrequest). For example, ```nginx echo_location /foo 'bar=Bar'; ``` is logically equivalent to ```nginx echo_subrequest GET /foo -q 'bar=Bar'; ``` But calling this directive is slightly faster than calling [echo_subrequest](#echo_subrequest) using `GET` because we don't have to parse the HTTP method names like `GET` and options like `-q`. Behind the scene, it creates an `ngx_http_post_subrequest_t` object as a *continuation* and passes it into the `ngx_http_subrequest` function call. Nginx will later reopen this "continuation" in the subrequest's `ngx_http_finalize_request` function call. We resumes the execution of the parent-request's content handler and starts to run the next directive (command) if any. Nginx named locations like `@foo` is *not* supported here. This directive was first introduced in the [release v0.12](#v012). See also [echo_location_async](#echo_location_async) for more details about the meaning of the arguments. [Back to TOC](#table-of-contents) echo_subrequest_async --------------------- **syntax:** *echo_subrequest_async <HTTP_method> <location> [-q <url_args>] [-b <request_body>] [-f <request_body_path>]* **default:** *no* **context:** *location, location if* **phase:** *content* Initiate an asynchronous subrequest using HTTP method, an optional url arguments (or querystring) and an optional request body which can be defined as a string or as a path to a file which contains the body. This directive is very much like a generalized version of the [echo_location_async](#echo_location_async) directive. Here's a small example demonstrating its usage: ```nginx location /multi { # body defined as string echo_subrequest_async POST '/sub' -q 'foo=Foo' -b 'hi'; # body defined as path to a file, relative to nginx prefix path if not absolute echo_subrequest_async PUT '/sub' -q 'bar=Bar' -f '/tmp/hello.txt'; } location /sub { echo "querystring: $query_string"; echo "method: $echo_request_method"; echo "body: $echo_request_body"; echo "content length: $http_content_length"; echo '///'; } ``` Then on the client side: ```bash $ echo -n hello > /tmp/hello.txt $ curl 'http://localhost/multi' querystring: foo=Foo method: POST body: hi content length: 2 /// querystring: bar=Bar method: PUT body: hello content length: 5 /// ``` Here's more funny example using the standard [proxy module](#httpproxymodule) to handle the subrequest: ```nginx location /main { echo_subrequest_async POST /sub -b 'hello, world'; } location /sub { proxy_pass $scheme://127.0.0.1:$server_port/proxied; } location /proxied { echo "method: $echo_request_method."; # we need to read body explicitly here...or $echo_request_body # will evaluate to empty ("") echo_read_request_body; echo "body: $echo_request_body."; } ``` Then on the client side, we can see that ```bash $ curl 'http://localhost/main' method: POST. body: hello, world. ``` Nginx named locations like `@foo` is *not* supported here. This directive takes several options: -q Specify the URL arguments (or URL querystring) for the subrequest. -f Specify the path for the file whose content will be serve as the subrequest's request body. -b Specify the request body data This directive was first introduced in the [release v0.15](#v015). The `-f` option to define a file path for the body was introduced in the [release v0.35](#v035). See also the [echo_subrequest](#echo_subrequest) and [echo_location_async](#echo_location_async) directives. There is a known issue with this directive when disabling the standard [standard SSI module](http://nginx.org/en/docs/http/ngx_http_ssi_module.html). See [Known Issues](#known-issues) for more details. [Back to TOC](#table-of-contents) echo_subrequest --------------- **syntax:** *echo_subrequest <HTTP_method> <location> [-q <url_args>] [-b <request_body>] [-f <request_body_path>]* **default:** *no* **context:** *location, location if* **phase:** *content* This is the synchronous version of the [echo_subrequest_async](#echo_subrequest_async) directive. And just like [echo_location](#echo_location), it does not block the Nginx worker process (while [echo_blocking_sleep](#echo_blocking_sleep) does), rather, it uses continuation to pass control along the subrequest chain. See [echo_subrequest_async](#echo_subrequest_async) for more details. Nginx named locations like `@foo` is *not* supported here. This directive was first introduced in the [release v0.15](#v015). [Back to TOC](#table-of-contents) echo_foreach_split ------------------ **syntax:** *echo_foreach_split <delimiter> <string>* **default:** *no* **context:** *location, location if* **phase:** *content* Split the second argument `string` using the delimiter specified in the first argument, and then iterate through the resulting items. For instance: ```nginx location /loop { echo_foreach_split ',' $arg_list; echo "item: $echo_it"; echo_end; } ``` Accessing /main yields ```bash $ curl 'http://localhost/loop?list=cat,dog,mouse' item: cat item: dog item: mouse ``` As seen in the previous example, this directive should always be accompanied by an [echo_end](#echo_end) directive. Parallel `echo_foreach_split` loops are allowed, but nested ones are currently forbidden. The `delimiter` argument could contain *multiple* arbitrary characters, like ```nginx # this outputs "cat\ndog\nmouse\n" echo_foreach_split -- '-a-' 'cat-a-dog-a-mouse'; echo $echo_it; echo_end; ``` Logically speaking, this looping structure is just the `foreach` loop combined with a `split` function call in Perl (using the previous example): ```perl foreach (split ',', $arg_list) { print "item $_\n"; } ``` People will also find it useful in merging multiple `.js` or `.css` resources into a whole. Here's an example: ```nginx location /merge { default_type 'text/javascript'; echo_foreach_split '&' $query_string; echo "/* JS File $echo_it */"; echo_location_async $echo_it; echo; echo_end; } ``` Then accessing /merge to merge the `.js` resources specified in the query string: ```bash $ curl 'http://localhost/merge?/foo/bar.js&/yui/blah.js&/baz.js' ``` One can also use third-party Nginx cache module to cache the merged response generated by the `/merge` location in the previous example. This directive was first introduced in the [release v0.17](#v017). [Back to TOC](#table-of-contents) echo_end -------- **syntax:** *echo_end* **default:** *no* **context:** *location, location if* **phase:** *content* This directive is used to terminate the body of looping and conditional control structures like [echo_foreach_split](#echo_foreach_split). This directive was first introduced in the [release v0.17](#v017). [Back to TOC](#table-of-contents) echo_request_body ----------------- **syntax:** *echo_request_body* **default:** *no* **context:** *location, location if* **phase:** *content* Outputs the contents of the request body previous read. Behind the scene, it's implemented roughly like this: ```C if (r->request_body && r->request_body->bufs) { return ngx_http_output_filter(r, r->request_body->bufs); } ``` Unlike the [$echo_request_body](#echo_request_body) and $request_body variables, this directive will show the whole request body even if some parts or all parts of it are saved in temporary files on the disk. It is a "no-op" if no request body has been read yet. This directive was first introduced in the [release v0.18](#v018). See also [echo_read_request_body](#echo_read_request_body) and the [chunkin module](http://github.com/agentzh/chunkin-nginx-module). [Back to TOC](#table-of-contents) echo_exec --------- **syntax:** *echo_exec <location> [<query_string>]* **syntax:** *echo_exec <named_location>* **default:** *no* **context:** *location, location if* **phase:** *content* Does an internal redirect to the location specified. An optional query string can be specified for normal locations, as in ```nginx location /foo { echo_exec /bar weight=5; } location /bar { echo $arg_weight; } ``` Or equivalently ```nginx location /foo { echo_exec /bar?weight=5; } location /bar { echo $arg_weight; } ``` Named locations are also supported. Here's an example: ```nginx location /foo { echo_exec @bar; } location @bar { # you'll get /foo rather than @bar # due to a potential bug in nginx. echo $echo_request_uri; } ``` But query string (if any) will always be ignored for named location redirects due to a limitation in the `ngx_http_named_location` function. Never try to echo things before the `echo_exec` directive or you won't see the proper response of the location you want to redirect to. Because any echoing will cause the original location handler to send HTTP headers before the redirection happens. Technically speaking, this directive exposes the Nginx internal API functions `ngx_http_internal_redirect` and `ngx_http_named_location`. This directive was first introduced in the [v0.21 release](#v021). [Back to TOC](#table-of-contents) echo_status ----------- **syntax:** *echo_status <status-num>* **default:** *echo_status 200* **context:** *location, location if* **phase:** *content* Specify the default response status code. Default to `200`. This directive is declarative and the relative order with other echo-like directives is not important. Here is an example, ```nginx location = /bad { echo_status 404; echo "Something is missing..."; } ``` then we get a response like this: HTTP/1.1 404 Not Found Server: nginx/1.2.1 Date: Sun, 24 Jun 2012 03:58:18 GMT Content-Type: text/plain Transfer-Encoding: chunked Connection: keep-alive Something is missing... This directive was first introduced in the `v0.40` release. [Back to TOC](#table-of-contents) Filter Directives ================= Use of the following directives trigger the filter registration of this module. By default, no filter will be registered by this module. Every filter directive supports variable interpolation in its arguments (if any). [Back to TOC](#table-of-contents) echo_before_body ---------------- **syntax:** *echo_before_body [options] [argument]...* **default:** *no* **context:** *location, location if* **phase:** *output filter* It's the filter version of the [echo](#echo) directive, and prepends its output to the beginning of the original outputs generated by the underlying content handler. An example is ```nginx location /echo { echo_before_body hello; proxy_pass $scheme://127.0.0.1:$server_port$request_uri/more; } location /echo/more { echo world } ``` Accessing `/echo` from the client side yields ```bash hello world ``` In the previous sample, we borrow the [standard proxy module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) to serve as the underlying content handler that generates the "main contents". Multiple instances of this filter directive are also allowed, as in: ```nginx location /echo { echo_before_body hello; echo_before_body world; echo !; } ``` On the client side, the output is like ```bash $ curl 'http://localhost/echo' hello world ! ``` In this example, we also use the [content handler directives](#content-handler-directives) provided by this module as the underlying content handler. This directive also supports the `-n` and `--` options like the [echo](#echo) directive. This directive can be mixed with its brother directive [echo_after_body](#echo_after_body). [Back to TOC](#table-of-contents) echo_after_body --------------- **syntax:** *echo_after_body [argument]...* **default:** *no* **context:** *location, location if* **phase:** *output filter* It's very much like the [echo_before_body](#echo_before_body) directive, but *appends* its output to the end of the original outputs generated by the underlying content handler. Here's a simple example: ```nginx location /echo { echo_after_body hello; proxy_pass http://127.0.0.1:$server_port$request_uri/more; } location /echo/more { echo world } ``` Accessing `/echo` from the client side yields world hello Multiple instances are allowed, as in: ```nginx location /echo { echo_after_body hello; echo_after_body world; echo i; echo say; } ``` The output on the client side while accessing the `/echo` location looks like i say hello world This directive also supports the `-n` and `--` options like the [echo](#echo) directive. This directive can be mixed with its brother directive [echo_before_body](#echo_before_body). [Back to TOC](#table-of-contents) Variables ========= [Back to TOC](#table-of-contents) $echo_it -------- This is a "topic variable" used by [echo_foreach_split](#echo_foreach_split), just like the `$_` variable in Perl. [Back to TOC](#table-of-contents) $echo_timer_elapsed ------------------- This variable holds the seconds elapsed since the start of the current request (might be a subrequest though) or the last invocation of the [echo_reset_timer](#echo_reset_timer) command. The timing result takes three digits after the decimal point. References of this variable will force the underlying Nginx timer to update to the current system time, regardless the timer resolution settings elsewhere in the config file, just like the [echo_reset_timer](#echo_reset_timer) directive. [Back to TOC](#table-of-contents) $echo_request_body ------------------ Evaluates to the current (sub)request's request body previously read if no part of the body has been saved to a temporary file. To always show the request body even if it's very large, use the [echo_request_body](#echo_request_body) directive. [Back to TOC](#table-of-contents) $echo_request_method -------------------- Evaluates to the HTTP request method of the current request (it can be a subrequest). Behind the scene, it just takes the string data stored in `r->method_name`. Compare it to the [$echo_client_request_method](#echo_client_request_method) variable. At least for Nginx 0.8.20 and older, the [$request_method](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_method) variable provided by the [http core module](http://nginx.org/en/docs/http/ngx_http_core_module.html) is actually doing what our [$echo_client_request_method](#echo_client_request_method) is doing. This variable was first introduced in our [v0.15 release](#v015). [Back to TOC](#table-of-contents) $echo_client_request_method --------------------------- Always evaluates to the main request's HTTP method even if the current request is a subrequest. Behind the scene, it just takes the string data stored in `r->main->method_name`. Compare it to the [$echo_request_method](#echo_request_method) variable. This variable was first introduced in our [v0.15 release](#v015). [Back to TOC](#table-of-contents) $echo_client_request_headers ---------------------------- Evaluates to the original client request's headers. Just as the name suggests, it will always take the main request (or the client request) even if it's currently executed in a subrequest. A simple example is below: ```nginx location /echoback { echo "headers are:" echo $echo_client_request_headers; } ``` Accessing `/echoback` yields ```bash $ curl 'http://localhost/echoback' headers are GET /echoback HTTP/1.1 User-Agent: curl/7.18.2 (i486-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.8g Host: localhost:1984 Accept: */* ``` Behind the scene, it recovers `r->main->header_in` (or the large header buffers, if any) on the C level and does not construct the headers itself by traversing parsed results in the request object. This variable was first introduced in [version 0.15](#v015). [Back to TOC](#table-of-contents) $echo_cacheable_request_uri --------------------------- Evaluates to the parsed form of the URI (usually led by `/`) of the current (sub-)request. Unlike the [$echo_request_uri](#echo_request_uri) variable, it is cacheable. See [$echo_request_uri](#echo_request_uri) for more details. This variable was first introduced in [version 0.17](#v017). [Back to TOC](#table-of-contents) $echo_request_uri ----------------- Evaluates to the parsed form of the URI (usually led by `/`) of the current (sub-)request. Unlike the [$echo_cacheable_request_uri](#echo_cacheable_request_uri) variable, it is *not* cacheable. This is quite different from the [$request_uri](http://nginx.org/en/docs/http/ngx_http_core_module.html#var_request_uri) variable exported by the [ngx_http_core_module](http://nginx.org/en/docs/http/ngx_http_core_module.html), because `$request_uri` is the *unparsed* form of the current request's URI. This variable was first introduced in [version 0.17](#v017). [Back to TOC](#table-of-contents) $echo_incr ---------- It is a counter that always generate the current counting number, starting from 1. The counter is always associated with the main request even if it is accessed within a subrequest. Consider the following example ```Nginx location /main { echo "main pre: $echo_incr"; echo_location_async /sub; echo_location_async /sub; echo "main post: $echo_incr"; } location /sub { echo "sub: $echo_incr"; } ``` Accessing `/main` yields main pre: 1 sub: 3 sub: 4 main post: 2 This directive was first introduced in the [v0.18 release](#v018). [Back to TOC](#table-of-contents) $echo_response_status --------------------- Evaluates to the status code of the current (sub)request, null if not any. Behind the scene, it's just the textual representation of `r->headers_out->status`. This directive was first introduced in the [v0.23 release](#v023). [Back to TOC](#table-of-contents) Installation ============ You're recommended to install this module (as well as the Nginx core and many other goodies) via the [ngx_openresty bundle](http://openresty.org). See [the detailed instructions](http://openresty.org/#Installation) for downloading and installing ngx_openresty into your system. This is the easiest and most safe way to set things up. Alternatively, you can install this module manually with the Nginx source: Grab the nginx source code from [nginx.org](http://nginx.org/), for example, the version 1.7.7 (see [nginx compatibility](#compatibility)), and then build the source with this module: ```bash $ wget 'http://nginx.org/download/nginx-1.7.7.tar.gz' $ tar -xzvf nginx-1.7.7.tar.gz $ cd nginx-1.7.7/ # Here we assume you would install you nginx under /opt/nginx/. $ ./configure --prefix=/opt/nginx \ --add-module=/path/to/echo-nginx-module $ make -j2 $ make install ``` Download the latest version of the release tarball of this module from [echo-nginx-module file list](https://github.com/agentzh/echo-nginx-module/tags). Also, this module is included and enabled by default in the [ngx_openresty bundle](http://openresty.org). [Back to TOC](#table-of-contents) Compatibility ============= The following versions of Nginx should work with this module: * **1.7.x** (last tested: 1.7.7) * **1.6.x** * **1.5.x** (last tested: 1.5.12) * **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.21** (last tested: 0.7.68) In particular, * the directive [echo_location_async](#echo_location_async) and its brother [echo_subrequest_async](#echo_subrequest_async) do *not* work with **0.7.x < 0.7.46**. * the [echo_after_body](#echo_after_body) directive does *not* work at all with nginx **< 0.8.7**. * the [echo_sleep](#echo_sleep) directive cannot be used after [echo_location](#echo_location) or [echo_subrequest](#echo_subrequest) for nginx **< 0.8.11**. Earlier versions of Nginx like 0.6.x and 0.5.x will *not* work at all. If you find that any particular version of Nginx above 0.7.21 does not work with this module, please consider [reporting a bug](#report-bugs). [Back to TOC](#table-of-contents) Known Issues ============ Due to an unknown bug in Nginx (it still exists in Nginx 1.7.7), the [standard SSI module](http://nginx.org/en/docs/http/ngx_http_ssi_module.html) is required to ensure that the contents of the subrequests issued by [echo_locatoin_async](#echo_location_async) and [echo_subrequest_async](#echo_subrequest_async) are correctly merged into the output chains of the main one. Fortunately, the SSI module is enabled by default during Nginx's `configure` process. If calling this directive without SSI module enabled, you'll get truncated response without contents of any subrequests and get an alert message in your Nginx's `error.log`, like this: ```nginx [alert] 24212#0: *1 the http output chain is empty, client: 127.0.0.1, ... ``` [Back to TOC](#table-of-contents) Modules that use this module for testing ======================================== The following modules take advantage of this `echo` module in their test suite: * The [memc](http://github.com/openresty/memc-nginx-module) module that supports almost the whole memcached TCP protocol. * The [chunkin](http://github.com/agentzh/chunkin-nginx-module) module that adds HTTP 1.1 chunked input support to Nginx. * The [headers_more](http://github.com/openresty/headers-more-nginx-module) module that allows you to add, set, and clear input and output headers under the conditions that you specify. * The `echo` module itself. Please mail me other modules that use `echo` in any form and I'll add them to the list above :) [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) Report Bugs =========== Although a lot of effort has been put into testing and code tuning, there must be some serious bugs lurking somewhere in this module. So whenever you are bitten by any quirks, please don't hesitate to 1. create a ticket on the [issue tracking interface](https://github.com/agentzh/echo-nginx-module/issues) provided by GitHub, 1. or send a bug report, questions, or even patches to the [OpenResty Community](#community). [Back to TOC](#table-of-contents) Source Repository ================= Available on github at [agentzh/echo-nginx-module](https://github.com/agentzh/echo-nginx-module). [Back to TOC](#table-of-contents) Changes ======= The changes of every release of this module can be obtained from the ngx_openresty bundle's change logs: [Back to TOC](#table-of-contents) Test Suite ========== This module comes with a Perl-driven test suite. The [test cases](https://github.com/agentzh/echo-nginx-module/tree/master/t/) are [declarative](https://github.com/agentzh/echo-nginx-module/blob/master/t/echo.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-echo-module:$PATH 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 standard 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 [SSI](http://nginx.org/en/docs/http/ngx_http_ssi_module.html) to be enabled as well when building Nginx. [Back to TOC](#table-of-contents) TODO ==== * Fix the [echo_after_body](#echo_after_body) directive in subrequests. * Add directives *echo_read_client_request_body* and *echo_request_headers*. * Add new directive *echo_log* to use Nginx's logging facility directly from the config file and specific loglevel can be specified, as in ```nginx echo_log debug "I am being called."; ``` * Add support for options `-h` and `-t` to [echo_subrequest_async](#echo_subrequest_async) and [echo_subrequest](#echo_subrequest). For example ```nginx echo_subrequest POST /sub -q 'foo=Foo&bar=Bar' -b 'hello' -t 'text/plan' -h 'X-My-Header: blah blah' ``` * Add options to control whether a subrequest should inherit cached variables from its parent request (i.e. the current request that is calling the subrequest in question). Currently none of the subrequests issued by this module inherit the cached variables from the parent request. * Add new variable *$echo_active_subrequests* to show `r->main->count - 1`. * Add the *echo_file* and *echo_cached_file* directives. * Add new varaible *$echo_request_headers* to accompany the existing [$echo_client_request_headers](#echo_client_request_headers) variable. * Add new directive *echo_foreach*, as in ```nginx echo_foreach 'cat' 'dog' 'mouse'; echo_location_async "/animals/$echo_it"; echo_end; ``` * Add new directive *echo_foreach_range*, as in ```nginx echo_foreach_range '[1..100]' '[a-zA-z0-9]'; echo_location_async "/item/$echo_it"; echo_end; ``` * Add new directive *echo_repeat*, as in ```nginx echo_repeat 10 $i { echo "Page $i"; echo_location "/path/to/page/$i"; } ``` This is just another way of saying ```nginx echo_foreach_range $i [1..10]; echo "Page $i"; echo_location "/path/to/page/$i"; echo_end; ``` Thanks Marcus Clyne for providing this idea. * Add new variable $echo_random which always returns a random non-negative integer with the lower/upper limit specified by the new directives `echo_random_min` and `echo_random_max`. For example, ```nginx echo_random_min 10 echo_random_max 200 echo "random number: $echo_random"; ``` Thanks Marcus Clyne for providing this idea. [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) Author ====== Yichun "agentzh" Zhang (章亦春) *<agentzh@gmail.com>*, CloudFlare Inc. 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 =================== Copyright (c) 2009-2014, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. 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. [Back to TOC](#table-of-contents) See Also ======== * The original [blog post](http://agentzh.blogspot.com/2009/10/hacking-on-nginx-echo-module.html) about this module's initial development. * The standard [addition filter module](http://nginx.org/en/docs/http/ngx_http_addition_module.html). * The standard [proxy module](http://nginx.org/en/docs/http/ngx_http_proxy_module.html). * The [ngx_openresty](http://openresty.org) bundle. debian/modules/nginx-echo/doc/0000775000000000000000000000000012705233614013447 5ustar debian/modules/nginx-echo/doc/HttpEchoModule.wiki0000664000000000000000000014616312705233614017233 0ustar = Name = '''ngx_echo''' - Brings "echo", "sleep", "time", "exec" and more shell-style goodies to Nginx config file. ''This module is not distributed with the Nginx source.'' See [[#Installation|the installation instructions]]. = Status = This module is production ready. = Version = This document describes ngx_echo [https://github.com/agentzh/echo-nginx-module/tags v0.57] released on 21 November 2014. = Synopsis = location /hello { echo "hello, world!"; } location /hello { echo -n "hello, "; echo "world!"; } location /timed_hello { echo_reset_timer; echo hello world; echo "'hello world' takes about $echo_timer_elapsed sec."; echo hiya igor; echo "'hiya igor' takes about $echo_timer_elapsed sec."; } location /echo_with_sleep { echo hello; echo_flush; # ensure the client can see previous output immediately echo_sleep 2.5; # in sec echo world; } # in the following example, accessing /echo yields # hello # world # blah # hiya # igor location /echo { echo_before_body hello; echo_before_body world; proxy_pass $scheme://127.0.0.1:$server_port$request_uri/more; echo_after_body hiya; echo_after_body igor; } location /echo/more { echo blah; } # the output of /main might be # hello # world # took 0.000 sec for total. # and the whole request would take about 2 sec to complete. location /main { echo_reset_timer; # subrequests in parallel echo_location_async /sub1; echo_location_async /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 2; echo hello; } location /sub2 { echo_sleep 1; echo world; } # the output of /main might be # hello # world # took 3.003 sec for total. # and the whole request would take about 3 sec to complete. location /main { echo_reset_timer; # subrequests in series (chained by CPS) echo_location /sub1; echo_location /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 2; echo hello; } location /sub2 { echo_sleep 1; echo world; } # Accessing /dup gives # ------ END ------ location /dup { echo_duplicate 3 "--"; echo_duplicate 1 " END "; echo_duplicate 3 "--"; echo; } # /bighello will generate 1000,000,000 hello's. location /bighello { echo_duplicate 1000_000_000 'hello'; } # echo back the client request location /echoback { echo_duplicate 1 $echo_client_request_headers; echo "\r"; echo_read_request_body; echo_request_body; } # GET /multi will yields # querystring: foo=Foo # method: POST # body: hi # content length: 2 # /// # querystring: bar=Bar # method: PUT # body: hello # content length: 5 # /// location /multi { echo_subrequest_async POST '/sub' -q 'foo=Foo' -b 'hi'; echo_subrequest_async PUT '/sub' -q 'bar=Bar' -b 'hello'; } location /sub { echo "querystring: $query_string"; echo "method: $echo_request_method"; echo "body: $echo_request_body"; echo "content length: $http_content_length"; echo '///'; } # GET /merge?/foo.js&/bar/blah.js&/yui/baz.js will merge the .js resources together location /merge { default_type 'text/javascript'; echo_foreach_split '&' $query_string; echo "/* JS File $echo_it */"; echo_location_async $echo_it; echo; echo_end; } # accessing /if?val=abc yields the "hit" output # while /if?val=bcd yields "miss": location ^~ /if { set $res miss; if ($arg_val ~* '^a') { set $res hit; echo $res; } echo $res; } = Description = This module wraps lots of Nginx internal APIs for streaming input and output, parallel/sequential subrequests, timers and sleeping, as well as various meta data accessing. Basically it provides various utilities that help testing and debugging of other modules by trivially emulating different kinds of faked subrequest locations. People will also find it useful in real-world applications that need to # serve static contents directly from memory (loading from the Nginx config file). # wrap the upstream response with custom header and footer (kinda like the [[HttpAdditionModule|addition module]] but with contents read directly from the config file and Nginx variables). # merge contents of various "Nginx locations" (i.e., subrequests) together in a single main request (using [[#echo_location|echo_location]] and its friends). This is a special dual-role module that can ''lazily'' serve as a content handler or register itself as an output filter only upon demand. By default, this module does not do anything at all. Technially, this module has also demonstrated the following techniques that might be helpful for module writers: # Issue parallel subreqeusts directly from content handler. # Issue chained subrequests directly from content handler, by passing continuation along the subrequest chain. # Issue subrequests with all HTTP 1.1 methods and even an optional faked HTTP request body. # Interact with the Nginx event model directly from content handler using custom events and timers, and resume the content handler back if necessary. # Dual-role module that can (lazily) serve as a content handler or an output filter or both. # Nginx config file variable creation and interpolation. # Streaming output control using output_chain, flush and its friends. # Read client request body from the content handler, and returns back (asynchronously) to the content handler after completion. # Use Perl-based declarative [[#Test Suite|test suite]] to drive the development of Nginx C modules. = Content Handler Directives = Use of the following directives register this module to the current Nginx location as a content handler. If you want to use another module, like the [[HttpProxyModule|standard proxy module]], as the content handler, use the [[#Filter Directives|filter directives]] provided by this module. All the content handler directives can be mixed together in a single Nginx location and they're supposed to run sequentially just as in the Bash scripting language. Every content handler directive supports variable interpolation in its arguments (if any). The MIME type set by the [[HttpCoreModule#default_type|standard default_type directive]] is respected by this module, as in: location /hello { default_type text/plain; echo hello; } Then on the client side: $ curl -I 'http://localhost/echo' HTTP/1.1 200 OK Server: nginx/0.8.20 Date: Sat, 17 Oct 2009 03:40:19 GMT Content-Type: text/plain Connection: keep-alive Since the [[#v0.22|v0.22]] release, all of the directives are allowed in the [[HttpRewriteModule|rewrite module]]'s [[HttpRewriteModule#if|if]] directive block, for instance: location ^~ /if { set $res miss; if ($arg_val ~* '^a') { set $res hit; echo $res; } echo $res; } == echo == '''syntax:''' ''echo [options] ...'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Sends arguments joined by spaces, along with a trailing newline, out to the client. Note that the data might be buffered by Nginx's underlying buffer. To force the output data flushed immediately, use the [[#echo_flush|echo_flush]] command just after echo, as in echo hello world; echo_flush; When no argument is specified, ''echo'' emits the trailing newline alone, just like the ''echo'' command in shell. Variables may appear in the arguments. An example is echo The current request uri is $request_uri; where [[HttpCoreModule#$request_uri|$request_uri]] is a variable exposed by the [[HttpCoreModule]]. This command can be used multiple times in a single location configuration, as in location /echo { echo hello; echo world; } The output on the client side looks like this $ curl 'http://localhost/echo' hello world Special characters like newlines (\n) and tabs (\t) can be escaped using C-style escaping sequences. But a notable exception is the dollar sign ($). As of Nginx 0.8.20, there's still no clean way to esacpe this characters. (A work-around might be to use a $echo_dollor variable that is always evaluated to the constant $ character. This feature will possibly be introduced in a future version of this module.) As of the echo [[#v0.28|v0.28]] release, one can suppress the trailing newline character in the output by using the -n option, as in location /echo { echo -n "hello, "; echo "world"; } Accessing /echo gives $ curl 'http://localhost/echo' hello, world Leading -n in variable values won't take effect and will be emitted literally, as in location /echo { set $opt -n; echo $opt "hello,"; echo "world"; } This gives the following output $ curl 'http://localhost/echo' -n hello, world One can output leading -n literals and other options using the special -- option like this location /echo { echo -- -n is an option; } which yields $ curl 'http://localhost/echo' -n is an option == echo_duplicate == '''syntax:''' ''echo_duplicate '' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Outputs duplication of a string indicated by the second argument, using the times specified in the first argument. For instance, location /dup { echo_duplicate 3 "abc"; } will lead to an output of "abcabcabc". Underscores are allowed in the count number, just like in Perl. For example, to emit 1000,000,000 instances of "hello, world": location /many_hellos { echo_duplicate 1000_000_000 "hello, world"; } The count argument could be zero, but not negative. The second string argument could be an empty string ("") likewise. Unlike the [[#echo|echo]] directive, no trailing newline is appended to the result. So it's possible to "abuse" this directive as a no-trailing-newline version of [[#echo|echo]] by using "count" 1, as in location /echo_art { echo_duplicate 2 '---'; echo_duplicate 1 ' END '; # we don't want a trailing newline here echo_duplicate 2 '---'; echo; # we want a trailing newline here... } You get ------ END ------ This directive was first introduced in [[#v0.11|version 0.11]]. == echo_flush == '''syntax:''' ''echo_flush'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Forces the data potentially buffered by underlying Nginx output filters to send immediately to the client side via socket. Note that techically the command just emits a ngx_buf_t object with flush slot set to 1, so certain weird third-party output filter module could still block it before it reaches Nginx's (last) write filter. This directive does not take any argument. Consider the following example: location /flush { echo hello; echo_flush; echo_sleep 1; echo world; } Then on the client side, using curl to access /flush, you'll see the "hello" line immediately, but only after 1 second, the last "world" line. Without calling echo_flush in the example above, you'll most likely see no output until 1 second is elapsed due to the internal buffering of Nginx. This directive will fail to flush the output buffer in case of subrequests get involved. Consider the following example: location /main { echo_location_async /sub; echo hello; echo_flush; } location /sub { echo_sleep 1; } Then the client won't see "hello" appear even if echo_flush has been executed before the subrequest to /sub has actually started executing. The outputs of /main that are sent ''after'' [[#echo_location_async|echo_location_async]] will be postponed and buffered firmly. This does ''not'' apply to outputs sent before the subrequest initiated. For a modified version of the example given above: location /main { echo hello; echo_flush; echo_location_async /sub; } location /sub { echo_sleep 1; } The client will immediately see "hello" before /sub enters sleeping. See also [[#echo|echo]], [[#echo_sleep|echo_sleep]], and [[#echo_location_async|echo_location_async]]. == echo_sleep == '''syntax:''' ''echo_sleep '' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Sleeps for the time period specified by the argument, which is in seconds. This operation is non-blocking on server side, so unlike the [[#echo_blocking_sleep|echo_blocking_sleep]] directive, it won't block the whole Nginx worker process. The period might takes three digits after the decimal point and must be greater than 0.001. An example is location /echo_after_sleep { echo_sleep 1.234; echo resumed!; } Behind the scene, it sets up a per-request "sleep" ngx_event_t object, and adds a timer using that custom event to the Nginx event model and just waits for a timeout on that event. Because the "sleep" event is per-request, this directive can work in parallel subrequests. == echo_blocking_sleep == '''syntax:''' ''echo_blocking_sleep '' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' This is a blocking version of the [[#echo_sleep|echo_sleep]] directive. See the documentation of [[#echo_sleep|echo_sleep]] for more detail. Behind the curtain, it calls the ngx_msleep macro provided by the Nginx core which maps to usleep on POSIX-compliant systems. Note that this directive will block the current Nginx worker process completely while being executed, so never use it in production environment. == echo_reset_timer == '''syntax:''' ''echo_reset_timer'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Reset the timer begin time to ''now'', i.e., the time when this command is executed during request. The timer begin time is default to the starting time of the current request and can be overridden by this directive, potentially multiple times in a single location. For example: location /timed_sleep { echo_sleep 0.03; echo "$echo_timer_elapsed sec elapsed."; echo_reset_timer; echo_sleep 0.02; echo "$echo_timer_elapsed sec elapsed."; } The output on the client side might be $ curl 'http://localhost/timed_sleep' 0.032 sec elapsed. 0.020 sec elapsed. The actual figures you get on your side may vary a bit due to your system's current activities. Invocation of this directive will force the underlying Nginx timer to get updated to the current system time (regardless the timer resolution specified elsewhere in the config file). Furthermore, references of the [[#$echo_timer_elapsed|$echo_timer_elapsed]] variable will also trigger timer update forcibly. See also [[#echo_sleep|echo_sleep]] and [[#$echo_timer_elapsed|$echo_timer_elapsed]]. == echo_read_request_body == '''syntax:''' ''echo_read_request_body'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Explicitly reads request body so that the [[HttpCoreModule#$request_body|$request_body]] variable will always have non-empty values (unless the body is so big that it has been saved by Nginx to a local temporary file). Note that this might not be the original client request body because the current request might be a subrequest with a "artificial" body specified by its parent. This directive does not generate any output itself, just like [[#echo_sleep|echo_sleep]]. Here's an example for echo'ing back the original HTTP client request (both headers and body are included): location /echoback { echo_duplicate 1 $echo_client_request_headers; echo "\r"; echo_read_request_body; echo $request_body; } The content of /echoback looks like this on my side (I was using Perl's LWP utility to access this location on the server): $ (echo hello; echo world) | lwp-request -m POST 'http://localhost/echoback' POST /echoback HTTP/1.1 TE: deflate,gzip;q=0.3 Connection: TE, close Host: localhost User-Agent: lwp-request/5.818 libwww-perl/5.820 Content-Length: 12 Content-Type: application/x-www-form-urlencoded hello world Because /echoback is the main request, [[HttpCoreModule#$request_body|$request_body]] holds the original client request body. Before Nginx 0.7.56, it makes no sense to use this directive because [[HttpCoreModule#$request_body|$request_body]] was first introduced in Nginx 0.7.58. This directive itself was first introduced in the echo module's [[#v0.14|v0.14 release]]. == echo_location_async == '''syntax:''' ''echo_location_async []'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Issue GET subrequest to the location specified (first argument) with optional url arguments specified in the second argument. As of Nginx 0.8.20, the location argument does ''not'' support named location, due to a limitation in the ngx_http_subrequest function. The same is true for its brother, the [[#echo_location|echo_location]] directive. A very simple example is location /main { echo_location_async /sub; echo world; } location /sub { echo hello; } Accessing /main gets hello world Calling multiple locations in parallel is also possible: location /main { echo_reset_timer; echo_location_async /sub1; echo_location_async /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 2; # sleeps 2 sec echo hello; } location /sub2 { echo_sleep 1; # sleeps 1 sec echo world; } Accessing /main yields $ time curl 'http://localhost/main' hello world took 0.000 sec for total. real 0m2.006s user 0m0.000s sys 0m0.004s You can see that the main handler /main does ''not'' wait the subrequests /sub1 and /sub2 to complete and quickly goes on, hence the "0.000 sec" timing result. The whole request, however takes approximately 2 sec in total to complete because /sub1 and /sub2 run in parallel (or "concurrently" to be more accurate). If you use [[#echo_blocking_sleep|echo_blocking_sleep]] in the previous example instead, then you'll get the same output, but with 3 sec total response time, because "blocking sleep" blocks the whole Nginx worker process. Locations can also take an optional querystring argument, for instance location /main { echo_location_async /sub 'foo=Foo&bar=Bar'; } location /sub { echo $arg_foo $arg_bar; } Accessing /main yields $ curl 'http://localhost/main' Foo Bar Querystrings is ''not'' allowed to be concatenated onto the location argument with "?" directly, for example, /sub?foo=Foo&bar=Bar is an invalid location, and shouldn't be fed as the first argument to this directive. Technically speaking, this directive is an example that Nginx content handler issues one or more subrequests directly. AFAIK, the [https://connectical.com/projects/ngx-fancyindex/wiki fancyindex module] also does such kind of things ;) Nginx named locations like @foo is ''not'' supported here. This directive is logically equivalent to the GET version of [[#echo_subrequest_async|echo_subrequest_async]]. For example, echo_location_async /foo 'bar=Bar'; is logically equivalent to echo_subrequest_async GET /foo -q 'bar=Bar'; But calling this directive is slightly faster than calling [[#echo_subrequest_async|echo_subrequest_async]] using GET because we don't have to parse the HTTP method names like GET and options like -q. There is a known issue with this directive when disabling the standard [[HttpSsiModule|standard SSI module]]. See [[#Known Issues|Known Issues]] for more details. This directive is first introduced in [[#v0.09|version 0.09]] of this module and requires at least Nginx 0.7.46. == echo_location == '''syntax:''' ''echo_location []'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Just like the [[#echo_location_async|echo_location_async]] directive, but echo_location issues subrequests ''in series'' rather than in parallel. That is, the content handler directives following this directive won't be executed until the subrequest issued by this directive completes. The final response body is almost always equivalent to the case when [[#echo_location_async|echo_location_async]] is used instead, only if timing variables is used in the outputs. Consider the following example: location /main { echo_reset_timer; echo_location /sub1; echo_location /sub2; echo "took $echo_timer_elapsed sec for total."; } location /sub1 { echo_sleep 2; echo hello; } location /sub2 { echo_sleep 1; echo world; } The location /main above will take for total 3 sec to complete (compared to 2 sec if [[#echo_location_async|echo_location_async]] is used instead here). Here's the result in action on my machine: $ curl 'http://localhost/main' hello world took 3.003 sec for total. real 0m3.027s user 0m0.020s sys 0m0.004s This directive is logically equivalent to the GET version of [[#echo_subrequest|echo_subrequest]]. For example, echo_location /foo 'bar=Bar'; is logically equivalent to echo_subrequest GET /foo -q 'bar=Bar'; But calling this directive is slightly faster than calling [[#echo_subrequest|echo_subrequest]] using GET because we don't have to parse the HTTP method names like GET and options like -q. Behind the scene, it creates an ngx_http_post_subrequest_t object as a ''continuation'' and passes it into the ngx_http_subrequest function call. Nginx will later reopen this "continuation" in the subrequest's ngx_http_finalize_request function call. We resumes the execution of the parent-request's content handler and starts to run the next directive (command) if any. Nginx named locations like @foo is ''not'' supported here. This directive was first introduced in the [[#v0.12|release v0.12]]. See also [[#echo_location_async|echo_location_async]] for more details about the meaning of the arguments. == echo_subrequest_async == '''syntax:''' ''echo_subrequest_async [-q ] [-b ] [-f ]'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Initiate an asynchronous subrequest using HTTP method, an optional url arguments (or querystring) and an optional request body which can be defined as a string or as a path to a file which contains the body. This directive is very much like a generalized version of the [[#echo_location_async|echo_location_async]] directive. Here's a small example demonstrating its usage: location /multi { # body defined as string echo_subrequest_async POST '/sub' -q 'foo=Foo' -b 'hi'; # body defined as path to a file, relative to nginx prefix path if not absolute echo_subrequest_async PUT '/sub' -q 'bar=Bar' -f '/tmp/hello.txt'; } location /sub { echo "querystring: $query_string"; echo "method: $echo_request_method"; echo "body: $echo_request_body"; echo "content length: $http_content_length"; echo '///'; } Then on the client side: $ echo -n hello > /tmp/hello.txt $ curl 'http://localhost/multi' querystring: foo=Foo method: POST body: hi content length: 2 /// querystring: bar=Bar method: PUT body: hello content length: 5 /// Here's more funny example using the standard [[#HttpProxyModule|proxy module]] to handle the subrequest: location /main { echo_subrequest_async POST /sub -b 'hello, world'; } location /sub { proxy_pass $scheme://127.0.0.1:$server_port/proxied; } location /proxied { echo "method: $echo_request_method."; # we need to read body explicitly here...or $echo_request_body # will evaluate to empty ("") echo_read_request_body; echo "body: $echo_request_body."; } Then on the client side, we can see that $ curl 'http://localhost/main' method: POST. body: hello, world. Nginx named locations like @foo is ''not'' supported here. This directive takes several options: -q Specify the URL arguments (or URL querystring) for the subrequest. -f Specify the path for the file whose content will be serve as the subrequest's request body. -b Specify the request body data This directive was first introduced in the [[#v0.15|release v0.15]]. The -f option to define a file path for the body was introduced in the [[#v0.35|release v0.35]]. See also the [[#echo_subrequest|echo_subrequest]] and [[#echo_location_async|echo_location_async]] directives. There is a known issue with this directive when disabling the standard [[HttpSsiModule|standard SSI module]]. See [[#Known Issues|Known Issues]] for more details. == echo_subrequest == '''syntax:''' ''echo_subrequest [-q ] [-b ] [-f ]'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' This is the synchronous version of the [[#echo_subrequest_async|echo_subrequest_async]] directive. And just like [[#echo_location|echo_location]], it does not block the Nginx worker process (while [[#echo_blocking_sleep|echo_blocking_sleep]] does), rather, it uses continuation to pass control along the subrequest chain. See [[#echo_subrequest_async|echo_subrequest_async]] for more details. Nginx named locations like @foo is ''not'' supported here. This directive was first introduced in the [[#v0.15|release v0.15]]. == echo_foreach_split == '''syntax:''' ''echo_foreach_split '' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Split the second argument string using the delimiter specified in the first argument, and then iterate through the resulting items. For instance: location /loop { echo_foreach_split ',' $arg_list; echo "item: $echo_it"; echo_end; } Accessing /main yields $ curl 'http://localhost/loop?list=cat,dog,mouse' item: cat item: dog item: mouse As seen in the previous example, this directive should always be accompanied by an [[#echo_end|echo_end]] directive. Parallel echo_foreach_split loops are allowed, but nested ones are currently forbidden. The delimiter argument could contain ''multiple'' arbitrary characters, like # this outputs "cat\ndog\nmouse\n" echo_foreach_split -- '-a-' 'cat-a-dog-a-mouse'; echo $echo_it; echo_end; Logically speaking, this looping structure is just the foreach loop combined with a split function call in Perl (using the previous example): foreach (split ',', $arg_list) { print "item $_\n"; } People will also find it useful in merging multiple .js or .css resources into a whole. Here's an example: location /merge { default_type 'text/javascript'; echo_foreach_split '&' $query_string; echo "/* JS File $echo_it */"; echo_location_async $echo_it; echo; echo_end; } Then accessing /merge to merge the .js resources specified in the query string: $ curl 'http://localhost/merge?/foo/bar.js&/yui/blah.js&/baz.js' One can also use third-party Nginx cache module to cache the merged response generated by the /merge location in the previous example. This directive was first introduced in the [[#v0.17|release v0.17]]. == echo_end == '''syntax:''' ''echo_end'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' This directive is used to terminate the body of looping and conditional control structures like [[#echo_foreach_split|echo_foreach_split]]. This directive was first introduced in the [[#v0.17|release v0.17]]. == echo_request_body == '''syntax:''' ''echo_request_body'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Outputs the contents of the request body previous read. Behind the scene, it's implemented roughly like this: if (r->request_body && r->request_body->bufs) { return ngx_http_output_filter(r, r->request_body->bufs); } Unlike the [[#$echo_request_body|$echo_request_body]] and $request_body variables, this directive will show the whole request body even if some parts or all parts of it are saved in temporary files on the disk. It is a "no-op" if no request body has been read yet. This directive was first introduced in the [[#v0.18|release v0.18]]. See also [[#echo_read_request_body|echo_read_request_body]] and the [[HttpChunkinModule|chunkin module]]. == echo_exec == '''syntax:''' ''echo_exec []'' '''syntax:''' ''echo_exec '' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''content'' Does an internal redirect to the location specified. An optional query string can be specified for normal locations, as in location /foo { echo_exec /bar weight=5; } location /bar { echo $arg_weight; } Or equivalently location /foo { echo_exec /bar?weight=5; } location /bar { echo $arg_weight; } Named locations are also supported. Here's an example: location /foo { echo_exec @bar; } location @bar { # you'll get /foo rather than @bar # due to a potential bug in nginx. echo $echo_request_uri; } But query string (if any) will always be ignored for named location redirects due to a limitation in the ngx_http_named_location function. Never try to echo things before the echo_exec directive or you won't see the proper response of the location you want to redirect to. Because any echoing will cause the original location handler to send HTTP headers before the redirection happens. Technically speaking, this directive exposes the Nginx internal API functions ngx_http_internal_redirect and ngx_http_named_location. This directive was first introduced in the [[#v0.21|v0.21 release]]. == echo_status == '''syntax:''' ''echo_status '' '''default:''' ''echo_status 200'' '''context:''' ''location, location if'' '''phase:''' ''content'' Specify the default response status code. Default to 200. This directive is declarative and the relative order with other echo-like directives is not important. Here is an example, location = /bad { echo_status 404; echo "Something is missing..."; } then we get a response like this: HTTP/1.1 404 Not Found Server: nginx/1.2.1 Date: Sun, 24 Jun 2012 03:58:18 GMT Content-Type: text/plain Transfer-Encoding: chunked Connection: keep-alive Something is missing... This directive was first introduced in the v0.40 release. = Filter Directives = Use of the following directives trigger the filter registration of this module. By default, no filter will be registered by this module. Every filter directive supports variable interpolation in its arguments (if any). == echo_before_body == '''syntax:''' ''echo_before_body [options] [argument]...'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''output filter'' It's the filter version of the [[#echo|echo]] directive, and prepends its output to the beginning of the original outputs generated by the underlying content handler. An example is location /echo { echo_before_body hello; proxy_pass $scheme://127.0.0.1:$server_port$request_uri/more; } location /echo/more { echo world } Accessing /echo from the client side yields hello world In the previous sample, we borrow the [[HttpProxyModule|standard proxy module]] to serve as the underlying content handler that generates the "main contents". Multiple instances of this filter directive are also allowed, as in: location /echo { echo_before_body hello; echo_before_body world; echo !; } On the client side, the output is like $ curl 'http://localhost/echo' hello world ! In this example, we also use the [[#Content Handler Directives|content handler directives]] provided by this module as the underlying content handler. This directive also supports the -n and -- options like the [[#echo|echo]] directive. This directive can be mixed with its brother directive [[#echo_after_body|echo_after_body]]. == echo_after_body == '''syntax:''' ''echo_after_body [argument]...'' '''default:''' ''no'' '''context:''' ''location, location if'' '''phase:''' ''output filter'' It's very much like the [[#echo_before_body|echo_before_body]] directive, but ''appends'' its output to the end of the original outputs generated by the underlying content handler. Here's a simple example: location /echo { echo_after_body hello; proxy_pass http://127.0.0.1:$server_port$request_uri/more; } location /echo/more { echo world } Accessing /echo from the client side yields world hello Multiple instances are allowed, as in: location /echo { echo_after_body hello; echo_after_body world; echo i; echo say; } The output on the client side while accessing the /echo location looks like i say hello world This directive also supports the -n and -- options like the [[#echo|echo]] directive. This directive can be mixed with its brother directive [[#echo_before_body|echo_before_body]]. = Variables = == $echo_it == This is a "topic variable" used by [[#echo_foreach_split|echo_foreach_split]], just like the $_ variable in Perl. == $echo_timer_elapsed == This variable holds the seconds elapsed since the start of the current request (might be a subrequest though) or the last invocation of the [[#echo_reset_timer|echo_reset_timer]] command. The timing result takes three digits after the decimal point. References of this variable will force the underlying Nginx timer to update to the current system time, regardless the timer resolution settings elsewhere in the config file, just like the [[#echo_reset_timer|echo_reset_timer]] directive. == $echo_request_body == Evaluates to the current (sub)request's request body previously read if no part of the body has been saved to a temporary file. To always show the request body even if it's very large, use the [[#echo_request_body|echo_request_body]] directive. == $echo_request_method == Evaluates to the HTTP request method of the current request (it can be a subrequest). Behind the scene, it just takes the string data stored in r->method_name. Compare it to the [[#$echo_client_request_method|$echo_client_request_method]] variable. At least for Nginx 0.8.20 and older, the [[HttpCoreModule#$request_method|$request_method]] variable provided by the [[HttpCoreModule|http core module]] is actually doing what our [[#$echo_client_request_method|$echo_client_request_method]] is doing. This variable was first introduced in our [[#v0.15|v0.15 release]]. == $echo_client_request_method == Always evaluates to the main request's HTTP method even if the current request is a subrequest. Behind the scene, it just takes the string data stored in r->main->method_name. Compare it to the [[#$echo_request_method|$echo_request_method]] variable. This variable was first introduced in our [[#v0.15|v0.15 release]]. == $echo_client_request_headers == Evaluates to the original client request's headers. Just as the name suggests, it will always take the main request (or the client request) even if it's currently executed in a subrequest. A simple example is below: location /echoback { echo "headers are:" echo $echo_client_request_headers; } Accessing /echoback yields $ curl 'http://localhost/echoback' headers are GET /echoback HTTP/1.1 User-Agent: curl/7.18.2 (i486-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.8g Host: localhost:1984 Accept: */* Behind the scene, it recovers r->main->header_in (or the large header buffers, if any) on the C level and does not construct the headers itself by traversing parsed results in the request object. This variable was first introduced in [[#v0.15|version 0.15]]. == $echo_cacheable_request_uri == Evaluates to the parsed form of the URI (usually led by /) of the current (sub-)request. Unlike the [[#$echo_request_uri|$echo_request_uri]] variable, it is cacheable. See [[#$echo_request_uri|$echo_request_uri]] for more details. This variable was first introduced in [[#v0.17|version 0.17]]. == $echo_request_uri == Evaluates to the parsed form of the URI (usually led by /) of the current (sub-)request. Unlike the [[#$echo_cacheable_request_uri|$echo_cacheable_request_uri]] variable, it is ''not'' cacheable. This is quite different from the [[HttpCoreModule#$request_uri|$request_uri]] variable exported by the [[HttpCoreModule]], because $request_uri is the ''unparsed'' form of the current request's URI. This variable was first introduced in [[#v0.17|version 0.17]]. == $echo_incr == It is a counter that always generate the current counting number, starting from 1. The counter is always associated with the main request even if it is accessed within a subrequest. Consider the following example location /main { echo "main pre: $echo_incr"; echo_location_async /sub; echo_location_async /sub; echo "main post: $echo_incr"; } location /sub { echo "sub: $echo_incr"; } Accessing /main yields main pre: 1 sub: 3 sub: 4 main post: 2 This directive was first introduced in the [[#v0.18|v0.18 release]]. == $echo_response_status == Evaluates to the status code of the current (sub)request, null if not any. Behind the scene, it's just the textual representation of r->headers_out->status. This directive was first introduced in the [[#v0.23|v0.23 release]]. = Installation = You're recommended to install this module (as well as the Nginx core and many other goodies) via the [http://openresty.org ngx_openresty bundle]. See [http://openresty.org/#Installation the detailed instructions] for downloading and installing ngx_openresty into your system. This is the easiest and most safe way to set things up. Alternatively, you can install this module manually with the Nginx source: Grab the nginx source code from [http://nginx.org/ nginx.org], for example, the version 1.7.7 (see [[#Compatibility|nginx compatibility]]), and then build the source with this module: $ wget 'http://nginx.org/download/nginx-1.7.7.tar.gz' $ tar -xzvf nginx-1.7.7.tar.gz $ cd nginx-1.7.7/ # Here we assume you would install you nginx under /opt/nginx/. $ ./configure --prefix=/opt/nginx \ --add-module=/path/to/echo-nginx-module $ make -j2 $ make install Download the latest version of the release tarball of this module from [https://github.com/agentzh/echo-nginx-module/tags echo-nginx-module file list]. Also, this module is included and enabled by default in the [http://openresty.org ngx_openresty bundle]. = Compatibility = The following versions of Nginx should work with this module: * '''1.7.x''' (last tested: 1.7.7) * '''1.6.x''' * '''1.5.x''' (last tested: 1.5.12) * '''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.21''' (last tested: 0.7.68) In particular, * the directive [[#echo_location_async|echo_location_async]] and its brother [[#echo_subrequest_async|echo_subrequest_async]] do ''not'' work with '''0.7.x < 0.7.46'''. * the [[#echo_after_body|echo_after_body]] directive does ''not'' work at all with nginx '''< 0.8.7'''. * the [[#echo_sleep|echo_sleep]] directive cannot be used after [[#echo_location|echo_location]] or [[#echo_subrequest|echo_subrequest]] for nginx '''< 0.8.11'''. Earlier versions of Nginx like 0.6.x and 0.5.x will ''not'' work at all. If you find that any particular version of Nginx above 0.7.21 does not work with this module, please consider [[#Report Bugs|reporting a bug]]. = Known Issues = Due to an unknown bug in Nginx (it still exists in Nginx 1.7.7), the [[HttpSsiModule|standard SSI module]] is required to ensure that the contents of the subrequests issued by [[#echo_location_async|echo_locatoin_async]] and [[#echo_subrequest_async|echo_subrequest_async]] are correctly merged into the output chains of the main one. Fortunately, the SSI module is enabled by default during Nginx's configure process. If calling this directive without SSI module enabled, you'll get truncated response without contents of any subrequests and get an alert message in your Nginx's error.log, like this: [alert] 24212#0: *1 the http output chain is empty, client: 127.0.0.1, ... = Modules that use this module for testing = The following modules take advantage of this echo module in their test suite: * The [[HttpMemcModule|memc]] module that supports almost the whole memcached TCP protocol. * The [[HttpChunkinModule|chunkin]] module that adds HTTP 1.1 chunked input support to Nginx. * The [[HttpHeadersMoreModule|headers_more]] module that allows you to add, set, and clear input and output headers under the conditions that you specify. * The echo module itself. Please mail me other modules that use echo in any form and I'll add them to the list above :) = Community = == English Mailing List == The [https://groups.google.com/group/openresty-en openresty-en] mailing list is for English speakers. == Chinese Mailing List == The [https://groups.google.com/group/openresty openresty] mailing list is for Chinese speakers. = Report Bugs = Although a lot of effort has been put into testing and code tuning, there must be some serious bugs lurking somewhere in this module. So whenever you are bitten by any quirks, please don't hesitate to # create a ticket on the [https://github.com/agentzh/echo-nginx-module/issues issue tracking interface] provided by GitHub, # or send a bug report, questions, or even patches to the [[#Community|OpenResty Community]]. = Source Repository = Available on github at [https://github.com/agentzh/echo-nginx-module agentzh/echo-nginx-module]. = Changes = The changes of every release of this module can be obtained from the ngx_openresty bundle's change logs: http://openresty.org/#Changes = Test Suite = This module comes with a Perl-driven test suite. The [https://github.com/agentzh/echo-nginx-module/tree/master/t/ test cases] are [https://github.com/agentzh/echo-nginx-module/blob/master/t/echo.t declarative] too. Thanks to the [http://search.cpan.org/perldoc?Test::Nginx Test::Nginx] module in the Perl world. To run it on your side: $ PATH=/path/to/your/nginx-with-echo-module:$PATH 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 standard modules [[HttpProxyModule|proxy]], [[HttpRewriteModule|rewrite]] and [[HttpSsiModule|SSI]] to be enabled as well when building Nginx. = TODO = * Fix the [[#echo_after_body|echo_after_body]] directive in subrequests. * Add directives ''echo_read_client_request_body'' and ''echo_request_headers''. * Add new directive ''echo_log'' to use Nginx's logging facility directly from the config file and specific loglevel can be specified, as in echo_log debug "I am being called."; * Add support for options -h and -t to [[#echo_subrequest_async|echo_subrequest_async]] and [[#echo_subrequest|echo_subrequest]]. For example echo_subrequest POST /sub -q 'foo=Foo&bar=Bar' -b 'hello' -t 'text/plan' -h 'X-My-Header: blah blah' * Add options to control whether a subrequest should inherit cached variables from its parent request (i.e. the current request that is calling the subrequest in question). Currently none of the subrequests issued by this module inherit the cached variables from the parent request. * Add new variable ''$echo_active_subrequests'' to show r->main->count - 1. * Add the ''echo_file'' and ''echo_cached_file'' directives. * Add new varaible ''$echo_request_headers'' to accompany the existing [[#$echo_client_request_headers|$echo_client_request_headers]] variable. * Add new directive ''echo_foreach'', as in echo_foreach 'cat' 'dog' 'mouse'; echo_location_async "/animals/$echo_it"; echo_end; * Add new directive ''echo_foreach_range'', as in echo_foreach_range '[1..100]' '[a-zA-z0-9]'; echo_location_async "/item/$echo_it"; echo_end; * Add new directive ''echo_repeat'', as in echo_repeat 10 $i { echo "Page $i"; echo_location "/path/to/page/$i"; } This is just another way of saying echo_foreach_range $i [1..10]; echo "Page $i"; echo_location "/path/to/page/$i"; echo_end; Thanks Marcus Clyne for providing this idea. * Add new variable $echo_random which always returns a random non-negative integer with the lower/upper limit specified by the new directives echo_random_min and echo_random_max. For example, echo_random_min 10 echo_random_max 200 echo "random number: $echo_random"; Thanks Marcus Clyne for providing this idea. = 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. = Author = Yichun "agentzh" Zhang (章亦春) '''', CloudFlare Inc. This wiki page is also maintained by the author himself, and everybody is encouraged to improve this page as well. = Copyright & License = Copyright (c) 2009-2014, Yichun "agentzh" Zhang (章亦春) , CloudFlare Inc. 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. = See Also = * The original [http://agentzh.blogspot.com/2009/10/hacking-on-nginx-echo-module.html blog post] about this module's initial development. * The standard [[HttpAdditionModule|addition filter module]]. * The standard [[HttpProxyModule|proxy module]]. * The [http://openresty.org ngx_openresty] bundle. debian/modules/nginx-echo/config0000664000000000000000000000223412705233614014073 0ustar ngx_addon_name=ngx_http_echo_module HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_echo_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_echo_module.c $ngx_addon_dir/src/ngx_http_echo_util.c $ngx_addon_dir/src/ngx_http_echo_timer.c $ngx_addon_dir/src/ngx_http_echo_var.c $ngx_addon_dir/src/ngx_http_echo_handler.c $ngx_addon_dir/src/ngx_http_echo_filter.c $ngx_addon_dir/src/ngx_http_echo_sleep.c $ngx_addon_dir/src/ngx_http_echo_location.c $ngx_addon_dir/src/ngx_http_echo_echo.c $ngx_addon_dir/src/ngx_http_echo_request_info.c $ngx_addon_dir/src/ngx_http_echo_subrequest.c $ngx_addon_dir/src/ngx_http_echo_foreach.c" NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ngx_http_echo_module.h $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_echo_handler.h $ngx_addon_dir/src/ngx_http_echo_util.h $ngx_addon_dir/src/ngx_http_echo_sleep.h $ngx_addon_dir/src/ngx_http_echo_filter.h $ngx_addon_dir/src/ngx_http_echo_var.h $ngx_addon_dir/src/ngx_http_echo_location.h $ngx_addon_dir/src/ngx_http_echo_echo.h $ngx_addon_dir/src/ngx_http_echo_request_info.h $ngx_addon_dir/src/ngx_http_echo_subrequest.h $ngx_addon_dir/src/ngx_http_echo_foreach.h" debian/modules/nginx-echo/LICENSE0000664000000000000000000000250112705233614013705 0ustar Copyright (C) 2009-2014, Yichun "agentzh" 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. debian/modules/nginx-echo/src/0000775000000000000000000000000012705233614013471 5ustar debian/modules/nginx-echo/src/ddebug.h0000664000000000000000000000457212705233614015104 0ustar #ifndef DDEBUG_H #define DDEBUG_H #include #include #if defined(DDEBUG) && (DDEBUG) # if (NGX_HAVE_VARIADIC_MACROS) # define dd(...) fprintf(stderr, "echo *** %s: ", __func__); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, " at %s line %d.\n", __FILE__, __LINE__) # else #include #include #include static void dd(const char * fmt, ...) { } # endif # if DDEBUG > 1 # define dd_enter() dd_enter_helper(r, __func__) static void dd_enter_helper(ngx_http_request_t *r, const char *func) { ngx_http_posted_request_t *pr; fprintf(stderr, ">enter %s %.*s %.*s?%.*s c:%d m:%p r:%p ar:%p pr:%p", func, (int) r->method_name.len, r->method_name.data, (int) r->uri.len, r->uri.data, (int) r->args.len, r->args.data, 0/*(int) r->main->count*/, r->main, r, r->connection->data, r->parent); if (r->posted_requests) { fprintf(stderr, " posted:"); for (pr = r->posted_requests; pr; pr = pr->next) { fprintf(stderr, "%p,", pr); } } fprintf(stderr, "\n"); } # else # define dd_enter() # endif #else # if (NGX_HAVE_VARIADIC_MACROS) # define dd(...) # define dd_enter() # else #include static void dd(const char * fmt, ...) { } static 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 */ debian/modules/nginx-echo/src/ngx_http_echo_request_info.c0000664000000000000000000002462112705233614021256 0ustar /* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_request_info.h" #include "ngx_http_echo_util.h" #include "ngx_http_echo_handler.h" #include static void ngx_http_echo_post_read_request_body(ngx_http_request_t *r); ngx_int_t ngx_http_echo_exec_echo_read_request_body(ngx_http_request_t* r, ngx_http_echo_ctx_t *ctx) { return ngx_http_read_client_request_body(r, ngx_http_echo_post_read_request_body); } static void ngx_http_echo_post_read_request_body(ngx_http_request_t *r) { ngx_http_echo_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); dd("wait read request body %d", (int) ctx->wait_read_request_body); if (ctx->wait_read_request_body) { ctx->waiting = 0; ctx->done = 1; r->write_event_handler = ngx_http_echo_wev_handler; ngx_http_echo_wev_handler(r); } } /* this function's implementation is borrowed from nginx 0.8.20 * and modified a bit to work with subrequests. * Copyrighted (C) by Igor Sysoev */ ngx_int_t ngx_http_echo_request_method_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { if (r->method_name.data) { v->len = r->method_name.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = r->method_name.data; } else { v->not_found = 1; } return NGX_OK; } /* this function's implementation is borrowed from nginx 0.8.20 * and modified a bit to work with subrequests. * Copyrighted (C) by Igor Sysoev */ ngx_int_t ngx_http_echo_client_request_method_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { if (r->main->method_name.data) { v->len = r->main->method_name.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = r->main->method_name.data; } else { v->not_found = 1; } return NGX_OK; } /* this function's implementation is borrowed from nginx 0.8.20 * and modified a bit to work with subrequests. * Copyrighted (C) by Igor Sysoev */ ngx_int_t ngx_http_echo_request_body_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { u_char *p; size_t len; ngx_buf_t *b; ngx_chain_t *cl; ngx_chain_t *in; if (r->request_body == NULL || r->request_body->bufs == NULL || r->request_body->temp_file) { v->not_found = 1; return NGX_OK; } in = r->request_body->bufs; len = 0; for (cl = in; cl; cl = cl->next) { b = cl->buf; if (!ngx_buf_in_memory(b)) { if (b->in_file) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "variable echo_request_body sees in-file only " "buffers and discard the whole body data"); v->not_found = 1; return NGX_OK; } } else { len += b->last - b->pos; } } p = ngx_pnalloc(r->pool, len); if (p == NULL) { return NGX_ERROR; } v->data = p; for (cl = in; cl; cl = cl->next) { b = cl->buf; if (ngx_buf_in_memory(b)) { p = ngx_copy(p, b->pos, b->last - b->pos); } } if (p - v->data != (ssize_t) len) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "variable echo_request_body: buffer error"); v->not_found = 1; return NGX_OK; } v->len = len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; } ngx_int_t ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { int line_break_len; size_t size; u_char *p, *last, *pos; ngx_int_t i, j; ngx_buf_t *b, *first = NULL; unsigned found; ngx_connection_t *c; ngx_http_request_t *mr; ngx_http_connection_t *hc; mr = r->main; hc = r->main->http_connection; c = mr->connection; size = 0; b = c->buffer; if (mr->request_line.data[mr->request_line.len] == CR) { line_break_len = 2; } else { line_break_len = 1; } if (mr->request_line.data >= b->start && mr->request_line.data + mr->request_line.len + line_break_len <= b->pos) { first = b; size += b->pos - mr->request_line.data; } if (hc->nbusy) { b = NULL; for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; if (first == NULL) { if (mr->request_line.data >= b->pos || mr->request_line.data + mr->request_line.len + line_break_len <= b->start) { continue; } dd("found first at %d", (int) i); first = b; } size += b->pos - b->start; } } size++; /* plus the null terminator, as required by the later ngx_strstr() call */ v->data = ngx_palloc(r->pool, size); if (v->data == NULL) { return NGX_ERROR; } last = v->data; b = c->buffer; found = 0; if (first == b) { found = 1; pos = b->pos; last = ngx_copy(v->data, mr->request_line.data, pos - mr->request_line.data); if (b != mr->header_in) { /* skip truncated header entries (if any) */ while (last > v->data && last[-1] != LF) { last--; } } i = 0; for (p = v->data; p != last; p++) { if (*p == '\0') { i++; if (p + 1 != last && *(p + 1) == LF) { *p = CR; } else if (i % 2 == 1) { *p = ':'; } else { *p = LF; } } } } if (hc->nbusy) { for (i = 0; i < hc->nbusy; i++) { b = hc->busy[i]; if (!found) { if (b != first) { continue; } dd("found first"); found = 1; } p = last; pos = b->pos; if (b == first) { dd("request line: %.*s", (int) mr->request_line.len, mr->request_line.data); last = ngx_copy(last, mr->request_line.data, pos - mr->request_line.data); } else { last = ngx_copy(last, b->start, pos - b->start); } #if 1 /* skip truncated header entries (if any) */ while (last > p && last[-1] != LF) { last--; } #endif j = 0; for (; p != last; p++) { if (*p == '\0') { j++; if (p + 1 == last) { /* XXX this should not happen */ dd("found string end!!"); } else if (*(p + 1) == LF) { *p = CR; } else if (j % 2 == 1) { *p = ':'; } else { *p = LF; } } } if (b == mr->header_in) { break; } } } *last++ = '\0'; if (last - v->data > (ssize_t) size) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "buffer error when evaluating " "$echo_client__request_headers: \"%V\"", (ngx_int_t) (last - v->data - size)); return NGX_ERROR; } /* strip the leading part (if any) of the request body in our header. * the first part of the request body could slip in because nginx core's * ngx_http_request_body_length_filter and etc can move r->header_in->pos * in case that some of the body data has been preread into r->header_in. */ if ((p = (u_char *) ngx_strstr(v->data, CRLF CRLF)) != NULL) { last = p + sizeof(CRLF CRLF) - 1; } else if ((p = (u_char *) ngx_strstr(v->data, CRLF "\n")) != NULL) { last = p + sizeof(CRLF "\n") - 1; } else if ((p = (u_char *) ngx_strstr(v->data, "\n" CRLF)) != NULL) { last = p + sizeof("\n" CRLF) - 1; } else { for (p = last - 1; p - v->data >= 2; p--) { if (p[0] == LF && p[-1] == CR) { p[-1] = LF; last = p + 1; break; } if (p[0] == LF && p[-1] == LF) { last = p + 1; break; } } } v->len = last - v->data; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; } ngx_int_t ngx_http_echo_cacheable_request_uri_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { if (r->uri.len) { v->len = r->uri.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = r->uri.data; } else { v->not_found = 1; } return NGX_OK; } ngx_int_t ngx_http_echo_request_uri_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { if (r->uri.len) { v->len = r->uri.len; v->valid = 1; v->no_cacheable = 1; v->not_found = 0; v->data = r->uri.data; } else { v->not_found = 1; } return NGX_OK; } ngx_int_t ngx_http_echo_response_status_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { u_char *p; if (r->headers_out.status) { dd("headers out status: %d", (int) r->headers_out.status); p = ngx_palloc(r->pool, NGX_INT_T_LEN); if (p == NULL) { return NGX_ERROR; } v->len = ngx_sprintf(p, "%ui", r->headers_out.status) - p; v->data = p; v->valid = 1; v->no_cacheable = 1; v->not_found = 0; } else { v->not_found = 1; } return NGX_OK; } /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ debian/modules/nginx-echo/src/ngx_http_echo_subrequest.c0000664000000000000000000005270512705233614020761 0ustar /* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_util.h" #include "ngx_http_echo_subrequest.h" #include "ngx_http_echo_handler.h" #include #define ngx_http_echo_method_name(m) { sizeof(m) - 1, (u_char *) m " " } ngx_str_t ngx_http_echo_content_length_header_key = ngx_string("Content-Length"); ngx_str_t ngx_http_echo_get_method = ngx_http_echo_method_name("GET"); ngx_str_t ngx_http_echo_put_method = ngx_http_echo_method_name("PUT"); ngx_str_t ngx_http_echo_post_method = ngx_http_echo_method_name("POST"); ngx_str_t ngx_http_echo_head_method = ngx_http_echo_method_name("HEAD"); ngx_str_t ngx_http_echo_copy_method = ngx_http_echo_method_name("COPY"); ngx_str_t ngx_http_echo_move_method = ngx_http_echo_method_name("MOVE"); ngx_str_t ngx_http_echo_lock_method = ngx_http_echo_method_name("LOCK"); ngx_str_t ngx_http_echo_mkcol_method = ngx_http_echo_method_name("MKCOL"); ngx_str_t ngx_http_echo_trace_method = ngx_http_echo_method_name("TRACE"); ngx_str_t ngx_http_echo_delete_method = ngx_http_echo_method_name("DELETE"); ngx_str_t ngx_http_echo_unlock_method = ngx_http_echo_method_name("UNLOCK"); ngx_str_t ngx_http_echo_options_method = ngx_http_echo_method_name("OPTIONS"); ngx_str_t ngx_http_echo_propfind_method = ngx_http_echo_method_name("PROPFIND"); ngx_str_t ngx_http_echo_proppatch_method = ngx_http_echo_method_name("PROPPATCH"); typedef struct ngx_http_echo_subrequest_s { ngx_uint_t method; ngx_str_t *method_name; ngx_str_t *location; ngx_str_t *query_string; ssize_t content_length_n; ngx_http_request_body_t *request_body; } ngx_http_echo_subrequest_t; static ngx_int_t ngx_http_echo_parse_method_name(ngx_str_t **method_name_ptr); static ngx_int_t ngx_http_echo_adjust_subrequest(ngx_http_request_t *sr, ngx_http_echo_subrequest_t *parsed_sr); static ngx_int_t ngx_http_echo_parse_subrequest_spec(ngx_http_request_t *r, ngx_array_t *computed_args, ngx_http_echo_subrequest_t **parsed_sr_ptr); static ngx_int_t ngx_http_echo_set_content_length_header(ngx_http_request_t *r, off_t len); ngx_int_t ngx_http_echo_exec_echo_subrequest_async(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_int_t rc; ngx_http_echo_subrequest_t *parsed_sr; ngx_http_request_t *sr; /* subrequest object */ ngx_str_t args; ngx_uint_t flags = 0; dd_enter(); rc = ngx_http_echo_parse_subrequest_spec(r, computed_args, &parsed_sr); if (rc != NGX_OK) { return rc; } dd("location: %.*s", (int) parsed_sr->location->len, parsed_sr->location->data); args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, parsed_sr->location, &args, &flags) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo_subrequest_async sees unsafe uri: \"%V\"", parsed_sr->location); return NGX_ERROR; } if (args.len > 0 && parsed_sr->query_string == NULL) { parsed_sr->query_string = &args; } rc = ngx_http_echo_send_header_if_needed(r, ctx); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } rc = ngx_http_subrequest(r, parsed_sr->location, parsed_sr->query_string, &sr, NULL, 0); if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_http_echo_adjust_subrequest(sr, parsed_sr); if (rc != NGX_OK) { return rc; } return NGX_OK; } ngx_int_t ngx_http_echo_exec_echo_subrequest(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_int_t rc; ngx_http_request_t *sr; /* subrequest object */ ngx_http_post_subrequest_t *psr; ngx_http_echo_subrequest_t *parsed_sr; ngx_str_t args; ngx_uint_t flags = 0; ngx_http_echo_ctx_t *sr_ctx; dd_enter(); rc = ngx_http_echo_parse_subrequest_spec(r, computed_args, &parsed_sr); if (rc != NGX_OK) { return rc; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, parsed_sr->location, &args, &flags) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo_subrequest sees unsafe uri: \"%V\"", parsed_sr->location); return NGX_ERROR; } if (args.len > 0 && parsed_sr->query_string == NULL) { parsed_sr->query_string = &args; } rc = ngx_http_echo_send_header_if_needed(r, ctx); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } sr_ctx = ngx_http_echo_create_ctx(r); /* set by ngx_http_echo_create_ctx * sr_ctx->run_post_subrequest = 0 */ dd("creating sr ctx for %.*s: %p", (int) parsed_sr->location->len, parsed_sr->location->data, sr_ctx); psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { return NGX_ERROR; } psr->handler = ngx_http_echo_post_subrequest; psr->data = sr_ctx; rc = ngx_http_subrequest(r, parsed_sr->location, parsed_sr->query_string, &sr, psr, 0); if (rc != NGX_OK) { return NGX_ERROR; } sr_ctx->sleep.data = sr; ngx_http_set_ctx(sr, sr_ctx, ngx_http_echo_module); rc = ngx_http_echo_adjust_subrequest(sr, parsed_sr); if (rc != NGX_OK) { return NGX_ERROR; } return NGX_AGAIN; } static ngx_int_t ngx_http_echo_parse_subrequest_spec(ngx_http_request_t *r, ngx_array_t *computed_args, ngx_http_echo_subrequest_t **parsed_sr_ptr) { ngx_str_t *computed_arg_elts, *arg; ngx_str_t **to_write = NULL; ngx_str_t *method_name; ngx_str_t *body_str = NULL; ngx_str_t *body_file = NULL; ngx_uint_t i; ngx_flag_t expecting_opt; ngx_http_request_body_t *rb = NULL; ngx_buf_t *b; ngx_http_echo_subrequest_t *parsed_sr; ngx_open_file_info_t of; ngx_http_core_loc_conf_t *clcf; size_t len; *parsed_sr_ptr = ngx_pcalloc(r->pool, sizeof(ngx_http_echo_subrequest_t)); if (*parsed_sr_ptr == NULL) { return NGX_ERROR; } parsed_sr = *parsed_sr_ptr; computed_arg_elts = computed_args->elts; method_name = &computed_arg_elts[0]; parsed_sr->location = &computed_arg_elts[1]; if (parsed_sr->location->len == 0) { return NGX_ERROR; } expecting_opt = 1; for (i = 2; i < computed_args->nelts; i++) { arg = &computed_arg_elts[i]; if (!expecting_opt) { if (to_write == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "echo_subrequest_async: to_write should NOT be NULL"); return NGX_ERROR; } *to_write = arg; to_write = NULL; expecting_opt = 1; continue; } if (arg->len == 2) { if (ngx_strncmp("-q", arg->data, arg->len) == 0) { to_write = &parsed_sr->query_string; expecting_opt = 0; continue; } if (ngx_strncmp("-b", arg->data, arg->len) == 0) { to_write = &body_str; expecting_opt = 0; continue; } if (ngx_strncmp("-f", arg->data, arg->len) == 0) { dd("found option -f"); to_write = &body_file; expecting_opt = 0; continue; } } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unknown option for echo_subrequest*: %V", arg); return NGX_ERROR; } if (body_str != NULL && body_str->len) { rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (rb == NULL) { return NGX_ERROR; } parsed_sr->content_length_n = body_str->len; b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->temporary = 1; /* b->memory = 1; */ b->start = b->pos = body_str->data; b->end = b->last = body_str->data + body_str->len; rb->bufs = ngx_alloc_chain_link(r->pool); if (rb->bufs == NULL) { return NGX_ERROR; } rb->bufs->buf = b; rb->bufs->next = NULL; rb->buf = b; } else if (body_file != NULL && body_file->len) { dd("body_file defined %.*s", (int) body_file->len, body_file->data); body_file->data = ngx_http_echo_rebase_path(r->pool, body_file->data, body_file->len, &len); if (body_file->data == NULL) { return NGX_ERROR; } body_file->len = len; dd("after rebase, the path becomes %.*s", (int) body_file->len, body_file->data); rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (rb == NULL) { return NGX_ERROR; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_memzero(&of, sizeof(ngx_open_file_info_t)); #if defined(nginx_version) && nginx_version >= 8018 of.read_ahead = clcf->read_ahead; #endif 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_open_cached_file(clcf->open_file_cache, body_file, &of, r->pool) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err, "%s \"%V\" failed", of.failed, body_file); return NGX_ERROR; } dd("file content size: %d", (int) of.size); parsed_sr->content_length_n = (ssize_t) of.size; b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_ERROR; } b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); if (b->file == NULL) { return NGX_ERROR; } b->file_pos = 0; b->file_last = of.size; b->in_file = b->file_last ? 1: 0; #if 0 b->last_buf = (r == r->main) ? 1: 0; b->last_in_chain = 1; #endif b->file->fd = of.fd; b->file->name = *body_file; b->file->log = r->connection->log; b->file->directio = of.is_directio; rb->bufs = ngx_alloc_chain_link(r->pool); if (rb->bufs == NULL) { return NGX_ERROR; } rb->bufs->buf = b; rb->bufs->next = NULL; rb->buf = b; } parsed_sr->request_body = rb; parsed_sr->method = ngx_http_echo_parse_method_name(&method_name); parsed_sr->method_name = method_name; return NGX_OK; } static ngx_int_t ngx_http_echo_adjust_subrequest(ngx_http_request_t *sr, ngx_http_echo_subrequest_t *parsed_sr) { ngx_http_core_main_conf_t *cmcf; ngx_http_request_t *r; ngx_http_request_body_t *body; ngx_int_t rc; sr->method = parsed_sr->method; sr->method_name = *(parsed_sr->method_name); if (sr->method == NGX_HTTP_HEAD) { sr->header_only = 1; } r = sr->parent; sr->header_in = r->header_in; /* XXX work-around a bug in ngx_http_subrequest */ if (r->headers_in.headers.last == &r->headers_in.headers.part) { sr->headers_in.headers.last = &sr->headers_in.headers.part; } /* we do not inherit the parent request's variables */ cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module); sr->variables = ngx_pcalloc(sr->pool, cmcf->variables.nelts * sizeof(ngx_http_variable_value_t)); if (sr->variables == NULL) { return NGX_ERROR; } body = parsed_sr->request_body; if (body) { sr->request_body = body; rc = ngx_http_echo_set_content_length_header(sr, body->buf ? ngx_buf_size(body->buf) : 0); if (rc != NGX_OK) { return NGX_ERROR; } } dd("subrequest body: %p", sr->request_body); return NGX_OK; } static ngx_int_t ngx_http_echo_parse_method_name(ngx_str_t **method_name_ptr) { const ngx_str_t* method_name = *method_name_ptr; switch (method_name->len) { case 3: if (ngx_http_echo_strcmp_const(method_name->data, "GET") == 0) { *method_name_ptr = &ngx_http_echo_get_method; return NGX_HTTP_GET; } if (ngx_http_echo_strcmp_const(method_name->data, "PUT") == 0) { *method_name_ptr = &ngx_http_echo_put_method; return NGX_HTTP_PUT; } return NGX_HTTP_UNKNOWN; case 4: if (ngx_http_echo_strcmp_const(method_name->data, "POST") == 0) { *method_name_ptr = &ngx_http_echo_post_method; return NGX_HTTP_POST; } if (ngx_http_echo_strcmp_const(method_name->data, "HEAD") == 0) { *method_name_ptr = &ngx_http_echo_head_method; return NGX_HTTP_HEAD; } if (ngx_http_echo_strcmp_const(method_name->data, "COPY") == 0) { *method_name_ptr = &ngx_http_echo_copy_method; return NGX_HTTP_COPY; } if (ngx_http_echo_strcmp_const(method_name->data, "MOVE") == 0) { *method_name_ptr = &ngx_http_echo_move_method; return NGX_HTTP_MOVE; } if (ngx_http_echo_strcmp_const(method_name->data, "LOCK") == 0) { *method_name_ptr = &ngx_http_echo_lock_method; return NGX_HTTP_LOCK; } return NGX_HTTP_UNKNOWN; case 5: if (ngx_http_echo_strcmp_const(method_name->data, "MKCOL") == 0) { *method_name_ptr = &ngx_http_echo_mkcol_method; return NGX_HTTP_MKCOL; } if (ngx_http_echo_strcmp_const(method_name->data, "TRACE") == 0) { *method_name_ptr = &ngx_http_echo_trace_method; return NGX_HTTP_TRACE; } return NGX_HTTP_UNKNOWN; case 6: if (ngx_http_echo_strcmp_const(method_name->data, "DELETE") == 0) { *method_name_ptr = &ngx_http_echo_delete_method; return NGX_HTTP_DELETE; } if (ngx_http_echo_strcmp_const(method_name->data, "UNLOCK") == 0) { *method_name_ptr = &ngx_http_echo_unlock_method; return NGX_HTTP_UNLOCK; } return NGX_HTTP_UNKNOWN; case 7: if (ngx_http_echo_strcmp_const(method_name->data, "OPTIONS") == 0) { *method_name_ptr = &ngx_http_echo_options_method; return NGX_HTTP_OPTIONS; } return NGX_HTTP_UNKNOWN; case 8: if (ngx_http_echo_strcmp_const(method_name->data, "PROPFIND") == 0) { *method_name_ptr = &ngx_http_echo_propfind_method; return NGX_HTTP_PROPFIND; } return NGX_HTTP_UNKNOWN; case 9: if (ngx_http_echo_strcmp_const(method_name->data, "PROPPATCH") == 0) { *method_name_ptr = &ngx_http_echo_proppatch_method; return NGX_HTTP_PROPPATCH; } return NGX_HTTP_UNKNOWN; default: return NGX_HTTP_UNKNOWN; } } /* XXX extermely evil and not working yet */ ngx_int_t ngx_http_echo_exec_abort_parent(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx) { #if 0 ngx_http_postponed_request_t *pr, *ppr; ngx_http_request_t *saved_data = NULL; ngx_chain_t *out = NULL; /* ngx_int_t rc; */ dd("aborting parent..."); if (r == r->main || r->parent == NULL) { return NGX_OK; } if (r->parent->postponed) { dd("Found parent->postponed..."); saved_data = r->connection->data; ppr = NULL; for (pr = r->parent->postponed; pr->next; pr = pr->next) { if (pr->request == NULL) { continue; } if (pr->request == r) { /* r->parent->postponed->next = pr; */ dd("found the current subrequest"); out = pr->out; continue; } /* r->connection->data = pr->request; */ dd("finalizing the subrequest..."); ngx_http_upstream_create(pr->request); pr->request->upstream = NULL; if (ppr == NULL) { r->parent->postponed = pr->next; ppr = pr->next; } else { ppr->next = pr->next; ppr = pr->next; } } } r->parent->postponed->next = NULL; /* r->connection->data = r->parent; r->connection->buffered = 0; if (out != NULL) { dd("trying to send more stuffs for the parent"); ngx_http_output_filter(r->parent, out); } */ /* ngx_http_send_special(r->parent, NGX_HTTP_LAST); */ if (saved_data) { r->connection->data = saved_data; } dd("terminating the parent request"); return ngx_http_echo_send_chain_link(r, ctx, NULL /* indicate LAST */); /* ngx_http_upstream_create(r); */ /* ngx_http_finalize_request(r->parent, NGX_ERROR); */ #endif return NGX_OK; } ngx_int_t ngx_http_echo_exec_exec(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_str_t *uri; ngx_str_t *user_args; ngx_str_t args; ngx_uint_t flags; ngx_str_t *computed_arg; computed_arg = computed_args->elts; uri = &computed_arg[0]; if (uri->len == 0) { return NGX_HTTP_BAD_REQUEST; } if (computed_args->nelts > 1) { user_args = &computed_arg[1]; } else { user_args = NULL; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo_exec sees unsafe uri: \"%V\"", uri); return NGX_ERROR; } if (args.len > 0 && user_args == NULL) { user_args = &args; } r->write_event_handler = ngx_http_request_empty_handler; if (uri->data[0] == '@') { if (user_args && user_args->len > 0) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "querystring %V ignored when exec'ing named " "location %V", user_args, uri); } #if 1 /* clear the modules contexts */ ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module); #endif dd("named location: %.*s, c:%d", (int) uri->len, uri->data, (int) r->main->count); return ngx_http_named_location(r, uri); } return ngx_http_internal_redirect(r, uri, user_args); } static ngx_int_t ngx_http_echo_set_content_length_header(ngx_http_request_t *r, off_t len) { ngx_table_elt_t *h, *header; u_char *p; ngx_list_part_t *part; ngx_http_request_t *pr; ngx_uint_t i; r->headers_in.content_length_n = len; if (ngx_list_init(&r->headers_in.headers, r->pool, 20, sizeof(ngx_table_elt_t)) != NGX_OK) { return NGX_ERROR; } h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { return NGX_ERROR; } h->key = ngx_http_echo_content_length_header_key; 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); r->headers_in.content_length = h; p = ngx_palloc(r->pool, NGX_OFF_T_LEN); if (p == NULL) { return NGX_ERROR; } h->value.data = p; h->value.len = ngx_sprintf(h->value.data, "%O", len) - h->value.data; h->hash = ngx_http_echo_content_length_hash; dd("r content length: %.*s", (int)r->headers_in.content_length->value.len, r->headers_in.content_length->value.data); pr = r->parent; if (pr == NULL) { return NGX_OK; } /* forward the parent request's all other request headers */ part = &pr->headers_in.headers.part; header = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].key.len == sizeof("Content-Length") - 1 && ngx_strncasecmp(header[i].key.data, (u_char *) "Content-Length", sizeof("Content-Length") - 1) == 0) { continue; } h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { return NGX_ERROR; } *h = header[i]; } /* XXX maybe we should set those built-in header slot in * ngx_http_headers_in_t too? */ return NGX_OK; } debian/modules/nginx-echo/src/ngx_http_echo_filter.h0000664000000000000000000000046712705233614020047 0ustar #ifndef ECHO_FILTER_H #define ECHO_FILTER_H #include "ngx_http_echo_module.h" extern ngx_http_output_header_filter_pt ngx_http_echo_next_header_filter; extern ngx_http_output_body_filter_pt ngx_http_echo_next_body_filter; ngx_int_t ngx_http_echo_filter_init (ngx_conf_t *cf); #endif /* ECHO_FILTER_H */ debian/modules/nginx-echo/src/ngx_http_echo_handler.h0000664000000000000000000000057712705233614020201 0ustar #ifndef ECHO_HANDLER_H #define ECHO_HANDLER_H #include "ngx_http_echo_module.h" void ngx_http_echo_wev_handler(ngx_http_request_t *r); ngx_int_t ngx_http_echo_handler(ngx_http_request_t *r); ngx_int_t ngx_http_echo_run_cmds(ngx_http_request_t *r); ngx_int_t ngx_http_echo_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc); #endif /* ECHO_HANDLER_H */ debian/modules/nginx-echo/src/ngx_http_echo_subrequest.h0000664000000000000000000000114412705233614020755 0ustar #ifndef ECHO_SUBREQUEST_H #define ECHO_SUBREQUEST_H #include "ngx_http_echo_module.h" ngx_int_t ngx_http_echo_exec_echo_subrequest(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); ngx_int_t ngx_http_echo_exec_echo_subrequest_async(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); ngx_int_t ngx_http_echo_exec_abort_parent(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx); ngx_int_t ngx_http_echo_exec_exec(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); #endif /* ECHO_SUBREQUEST_H */ debian/modules/nginx-echo/src/ngx_http_echo_var.c0000664000000000000000000000517512705233614017346 0ustar #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_var.h" #include "ngx_http_echo_timer.h" #include "ngx_http_echo_request_info.h" #include "ngx_http_echo_foreach.h" static ngx_int_t ngx_http_echo_incr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_http_variable_t ngx_http_echo_variables[] = { { ngx_string("echo_timer_elapsed"), NULL, ngx_http_echo_timer_elapsed_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("echo_request_method"), NULL, ngx_http_echo_request_method_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("echo_cacheable_request_uri"), NULL, ngx_http_echo_cacheable_request_uri_variable, 0, 0, 0 }, { ngx_string("echo_request_uri"), NULL, ngx_http_echo_request_uri_variable, 0, 0, 0 }, { ngx_string("echo_client_request_method"), NULL, ngx_http_echo_client_request_method_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("echo_request_body"), NULL, ngx_http_echo_request_body_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("echo_client_request_headers"), NULL, ngx_http_echo_client_request_headers_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("echo_it"), NULL, ngx_http_echo_it_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("echo_incr"), NULL, ngx_http_echo_incr_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_string("echo_response_status"), NULL, ngx_http_echo_response_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, { ngx_null_string, NULL, NULL, 0, 0, 0 } }; ngx_int_t ngx_http_echo_add_variables(ngx_conf_t *cf) { ngx_http_variable_t *var, *v; for (v = ngx_http_echo_variables; v->name.len; v++) { var = ngx_http_add_variable(cf, &v->name, v->flags); if (var == NULL) { return NGX_ERROR; } var->get_handler = v->get_handler; var->data = v->data; } return NGX_OK; } static ngx_int_t ngx_http_echo_incr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_echo_ctx_t *ctx; u_char *p; ctx = ngx_http_get_module_ctx(r->main, ngx_http_echo_module); if (ctx == NULL) { return NGX_ERROR; } ctx->counter++; p = ngx_palloc(r->pool, NGX_INT_T_LEN); if (p == NULL) { return NGX_ERROR; } v->len = ngx_sprintf(p, "%ui", ctx->counter) - p; v->data = p; v->valid = 1; v->not_found = 0; v->no_cacheable = 1; return NGX_OK; } debian/modules/nginx-echo/src/ngx_http_echo_foreach.h0000664000000000000000000000071212705233614020162 0ustar #ifndef ECHO_FOREACH_H #define ECHO_FOREACH_H #include "ngx_http_echo_module.h" ngx_int_t ngx_http_echo_exec_echo_foreach_split(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); ngx_int_t ngx_http_echo_exec_echo_end(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx); ngx_int_t ngx_http_echo_it_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); #endif /* ECHO_FOREACH_H */ debian/modules/nginx-echo/src/ngx_http_echo_util.c0000664000000000000000000001435412705233614017532 0ustar /* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_util.h" #include "ngx_http_echo_sleep.h" ngx_uint_t ngx_http_echo_content_length_hash = 0; ngx_http_echo_ctx_t * ngx_http_echo_create_ctx(ngx_http_request_t *r) { ngx_http_echo_ctx_t *ctx; ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_echo_ctx_t)); if (ctx == NULL) { return NULL; } ctx->sleep.handler = ngx_http_echo_sleep_event_handler; ctx->sleep.data = r; ctx->sleep.log = r->connection->log; return ctx; } ngx_int_t ngx_http_echo_eval_cmd_args(ngx_http_request_t *r, ngx_http_echo_cmd_t *cmd, ngx_array_t *computed_args, ngx_array_t *opts) { ngx_uint_t i; ngx_array_t *args = cmd->args; ngx_str_t *arg, *raw, *opt; ngx_http_echo_arg_template_t *value; ngx_flag_t expecting_opts = 1; value = args->elts; for (i = 0; i < args->nelts; i++) { raw = &value[i].raw_value; if (value[i].lengths == NULL && raw->len > 0) { if (expecting_opts) { if (raw->len == 1 || raw->data[0] != '-') { expecting_opts = 0; } else if (raw->data[1] == '-') { expecting_opts = 0; continue; } else { opt = ngx_array_push(opts); if (opt == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } opt->len = raw->len - 1; opt->data = raw->data + 1; dd("pushing opt: %.*s", (int) opt->len, opt->data); continue; } } } else { expecting_opts = 0; } arg = ngx_array_push(computed_args); if (arg == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (value[i].lengths == NULL) { /* does not contain vars */ dd("Using raw value \"%.*s\"", (int) raw->len, raw->data); *arg = *raw; } else { if (ngx_http_script_run(r, arg, value[i].lengths->elts, 0, value[i].values->elts) == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } dd("pushed arg: %.*s", (int) arg->len, arg->data); } return NGX_OK; } ngx_int_t ngx_http_echo_send_chain_link(ngx_http_request_t* r, ngx_http_echo_ctx_t *ctx, ngx_chain_t *in) { ngx_int_t rc; rc = ngx_http_echo_send_header_if_needed(r, ctx); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } if (in == NULL) { #if defined(nginx_version) && nginx_version <= 8004 /* earlier versions of nginx does not allow subrequests to send last_buf themselves */ if (r != r->main) { return NGX_OK; } #endif rc = ngx_http_send_special(r, NGX_HTTP_LAST); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_OK; } return ngx_http_output_filter(r, in); } ngx_int_t ngx_http_echo_send_header_if_needed(ngx_http_request_t* r, ngx_http_echo_ctx_t *ctx) { ngx_http_echo_loc_conf_t *elcf; if (!r->header_sent) { elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); r->headers_out.status = (ngx_uint_t) elcf->status; if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); return ngx_http_send_header(r); } return NGX_OK; } ssize_t ngx_http_echo_atosz(u_char *line, size_t n) { ssize_t value; if (n == 0) { return NGX_ERROR; } for (value = 0; n--; line++) { if (*line == '_') { /* we ignore undercores */ continue; } if (*line < '0' || *line > '9') { return NGX_ERROR; } value = value * 10 + (*line - '0'); } if (value < 0) { return NGX_ERROR; } return value; } /* Modified from the ngx_strlcasestrn function in ngx_string.h * Copyright (C) by Igor Sysoev */ u_char * ngx_http_echo_strlstrn(u_char *s1, u_char *last, u_char *s2, size_t n) { ngx_uint_t c1, c2; c2 = (ngx_uint_t) *s2++; last -= n; do { do { if (s1 >= last) { return NULL; } c1 = (ngx_uint_t) *s1++; } while (c1 != c2); } while (ngx_strncmp(s1, s2, n) != 0); return --s1; } ngx_int_t ngx_http_echo_post_request_at_head(ngx_http_request_t *r, ngx_http_posted_request_t *pr) { dd_enter(); if (pr == NULL) { pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t)); if (pr == NULL) { return NGX_ERROR; } } pr->request = r; pr->next = r->main->posted_requests; r->main->posted_requests = pr; return NGX_OK; } u_char * ngx_http_echo_rebase_path(ngx_pool_t *pool, u_char *src, size_t osize, size_t *nsize) { u_char *p, *dst; if (osize == 0) { return NULL; } if (src[0] == '/') { /* being an absolute path already, just add a trailing '\0' */ *nsize = osize; dst = ngx_palloc(pool, *nsize + 1); if (dst == NULL) { *nsize = 0; return NULL; } p = ngx_copy(dst, src, osize); *p = '\0'; return dst; } *nsize = ngx_cycle->prefix.len + osize; dst = ngx_palloc(pool, *nsize + 1); if (dst == NULL) { *nsize = 0; return NULL; } p = ngx_copy(dst, ngx_cycle->prefix.data, ngx_cycle->prefix.len); p = ngx_copy(p, src, osize); *p = '\0'; return dst; } ngx_int_t ngx_http_echo_flush_postponed_outputs(ngx_http_request_t *r) { if (r == r->connection->data && r->postponed) { /* notify the downstream postpone filter to flush the postponed * outputs of the current request */ return ngx_http_output_filter(r, NULL); } /* do nothing */ return NGX_OK; } debian/modules/nginx-echo/src/ngx_http_echo_timer.h0000664000000000000000000000052012705233614017670 0ustar #ifndef ECHO_TIMER_H #define ECHO_TIMER_H #include "ngx_http_echo_module.h" ngx_int_t ngx_http_echo_timer_elapsed_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); ngx_int_t ngx_http_echo_exec_echo_reset_timer(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx); #endif /* ECHO_TIMER_H */ debian/modules/nginx-echo/src/ngx_http_echo_handler.c0000664000000000000000000002624112705233614020170 0ustar /* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_filter.h" #include "ngx_http_echo_handler.h" #include "ngx_http_echo_echo.h" #include "ngx_http_echo_util.h" #include "ngx_http_echo_sleep.h" #include "ngx_http_echo_var.h" #include "ngx_http_echo_timer.h" #include "ngx_http_echo_location.h" #include "ngx_http_echo_subrequest.h" #include "ngx_http_echo_request_info.h" #include "ngx_http_echo_foreach.h" #include #include void ngx_http_echo_wev_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_echo_ctx_t *ctx; dd("wev handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL) { ngx_http_finalize_request(r, NGX_ERROR); return; } dd("waiting: %d, done: %d", (int) ctx->waiting, (int) ctx->done); if (ctx->waiting && ! ctx->done) { if (r == r->connection->data && r->postponed) { if (r->postponed->request) { r->connection->data = r->postponed->request; #if defined(nginx_version) && nginx_version >= 8012 ngx_http_post_request(r->postponed->request, NULL); #else ngx_http_post_request(r->postponed->request); #endif } else { ngx_http_echo_flush_postponed_outputs(r); } } return; } ctx->done = 0; ctx->next_handler_cmd++; rc = ngx_http_echo_run_cmds(r); dd("rc: %d", (int) rc); if (rc == NGX_ERROR || rc == NGX_DONE) { ngx_http_finalize_request(r, rc); return; } if (rc == NGX_AGAIN) { dd("mark busy %d for %.*s", (int) ctx->next_handler_cmd, (int) r->uri.len, r->uri.data); ctx->waiting = 1; ctx->done = 0; } else { dd("mark ready %d", (int) ctx->next_handler_cmd); ctx->waiting = 0; ctx->done = 1; dd("finalizing with rc %d", (int) rc); dd("finalize request %.*s with %d", (int) r->uri.len, r->uri.data, (int) rc); ngx_http_finalize_request(r, rc); } } ngx_int_t ngx_http_echo_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_echo_ctx_t *ctx; dd("subrequest in memory: %d", (int) r->subrequest_in_memory); rc = ngx_http_echo_run_cmds(r); dd("run cmds returned %d", (int) rc); if (rc == NGX_ERROR || rc == NGX_OK || rc == NGX_DONE || rc == NGX_DECLINED) { return rc; } ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { if (ctx && r->header_sent) { return NGX_ERROR; } return rc; } /* rc == NGX_AGAIN */ #if defined(nginx_version) && nginx_version >= 8011 r->main->count++; #endif dd("%d", r->connection->destroyed); dd("%d", r->done); if (ctx) { dd("mark busy %d for %.*s", (int) ctx->next_handler_cmd, (int) r->uri.len, r->uri.data); ctx->waiting = 1; ctx->done = 0; } return NGX_DONE; } ngx_int_t ngx_http_echo_run_cmds(ngx_http_request_t *r) { ngx_http_echo_loc_conf_t *elcf; ngx_http_echo_ctx_t *ctx; ngx_int_t rc; ngx_array_t *cmds; ngx_array_t *computed_args = NULL; ngx_http_echo_cmd_t *cmd; ngx_http_echo_cmd_t *cmd_elts; ngx_array_t *opts = NULL; elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); cmds = elcf->handler_cmds; if (cmds == NULL) { return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL) { ctx = ngx_http_echo_create_ctx(r); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_echo_module); } dd("exec handler: %.*s: %i", (int) r->uri.len, r->uri.data, (int) ctx->next_handler_cmd); cmd_elts = cmds->elts; for (; ctx->next_handler_cmd < cmds->nelts; ctx->next_handler_cmd++) { cmd = &cmd_elts[ctx->next_handler_cmd]; /* evaluate arguments for the current cmd (if any) */ if (cmd->args) { computed_args = ngx_array_create(r->pool, cmd->args->nelts, sizeof(ngx_str_t)); if (computed_args == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } opts = ngx_array_create(r->pool, 1, sizeof(ngx_str_t)); if (opts == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } rc = ngx_http_echo_eval_cmd_args(r, cmd, computed_args, opts); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to evaluate arguments for " "the directive."); return rc; } } /* do command dispatch based on the opcode */ switch (cmd->opcode) { case echo_opcode_echo_sync: rc = ngx_http_echo_exec_echo_sync(r, ctx); break; case echo_opcode_echo: /* XXX moved the following code to a separate * function */ dd("found echo opcode"); rc = ngx_http_echo_exec_echo(r, ctx, computed_args, 0 /* in filter */, opts); break; case echo_opcode_echo_request_body: rc = ngx_http_echo_exec_echo_request_body(r, ctx); break; case echo_opcode_echo_location_async: if (!r->request_body) { /* we require reading the request body before doing * subrequests */ ctx->next_handler_cmd--; /* re-run the current cmd */ goto read_request_body; } dd("found opcode echo location async..."); rc = ngx_http_echo_exec_echo_location_async(r, ctx, computed_args); break; case echo_opcode_echo_location: if (!r->request_body) { /* we require reading the request body before doing * subrequests */ ctx->next_handler_cmd--; /* re-run the current cmd */ goto read_request_body; } return ngx_http_echo_exec_echo_location(r, ctx, computed_args); case echo_opcode_echo_subrequest_async: if (!r->request_body) { /* we require reading the request body before doing * subrequests */ ctx->next_handler_cmd--; /* re-run the current cmd */ goto read_request_body; } dd("found opcode echo subrequest async..."); rc = ngx_http_echo_exec_echo_subrequest_async(r, ctx, computed_args); break; case echo_opcode_echo_subrequest: if (!r->request_body) { /* we require reading the request body before doing * subrequests */ ctx->next_handler_cmd--; /* re-run the current cmd */ goto read_request_body; } return ngx_http_echo_exec_echo_subrequest(r, ctx, computed_args); case echo_opcode_echo_sleep: return ngx_http_echo_exec_echo_sleep(r, ctx, computed_args); case echo_opcode_echo_flush: rc = ngx_http_echo_exec_echo_flush(r, ctx); break; case echo_opcode_echo_blocking_sleep: rc = ngx_http_echo_exec_echo_blocking_sleep(r, ctx, computed_args); break; case echo_opcode_echo_reset_timer: rc = ngx_http_echo_exec_echo_reset_timer(r, ctx); break; case echo_opcode_echo_duplicate: rc = ngx_http_echo_exec_echo_duplicate(r, ctx, computed_args); break; case echo_opcode_echo_read_request_body: read_request_body: ctx->wait_read_request_body = 0; rc = ngx_http_echo_exec_echo_read_request_body(r, ctx); if (rc == NGX_ERROR) { return NGX_ERROR; } if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { #if (nginx_version >= 8011 && nginx_version < 1002006) \ || (nginx_version >= 1003000 && nginx_version < 1003009) r->main->count--; #endif return rc; } #if nginx_version >= 8011 r->main->count--; #endif dd("read request body: %d", (int) rc); if (rc == NGX_OK) { continue; } /* rc == NGX_AGAIN */ ctx->wait_read_request_body = 1; return NGX_AGAIN; case echo_opcode_echo_foreach_split: rc = ngx_http_echo_exec_echo_foreach_split(r, ctx, computed_args); break; case echo_opcode_echo_end: rc = ngx_http_echo_exec_echo_end(r, ctx); break; case echo_opcode_echo_exec: dd("echo_exec"); return ngx_http_echo_exec_exec(r, ctx, computed_args); default: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unknown opcode: %d", cmd->opcode); return NGX_HTTP_INTERNAL_SERVER_ERROR; break; } if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } } rc = ngx_http_echo_send_chain_link(r, ctx, NULL /* indicate LAST */); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (!r->request_body) { if (ngx_http_discard_request_body(r) != NGX_OK) { return NGX_ERROR; } } return NGX_OK; } ngx_int_t ngx_http_echo_post_subrequest(ngx_http_request_t *r, void *data, ngx_int_t rc) { ngx_http_echo_ctx_t *ctx = data; ngx_http_request_t *pr; ngx_http_echo_ctx_t *pr_ctx; dd("echo post_subrequest: %.*s", (int) r->uri.len, r->uri.data); if (ctx->run_post_subrequest) { dd("already run post_subrequest: %p: %.*s", ctx, (int) r->uri.len, r->uri.data); return rc; } dd("setting run_post_subrequest to 1 for %p for %.*s", ctx, (int) r->uri.len, r->uri.data); ctx->run_post_subrequest = 1; pr = r->parent; pr_ctx = ngx_http_get_module_ctx(pr, ngx_http_echo_module); if (pr_ctx == NULL) { return NGX_ERROR; } dd("mark ready %d", (int) pr_ctx->next_handler_cmd); pr_ctx->waiting = 0; pr_ctx->done = 1; pr->write_event_handler = ngx_http_echo_wev_handler; /* work-around issues in nginx's event module */ if (r != r->connection->data && r->postponed && (r->main->posted_requests == NULL || r->main->posted_requests->request != pr)) { #if defined(nginx_version) && nginx_version >= 8012 ngx_http_post_request(pr, NULL); #else ngx_http_post_request(pr); #endif } return rc; } debian/modules/nginx-echo/src/ngx_http_echo_filter.c0000664000000000000000000001701112705233614020033 0ustar #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_filter.h" #include "ngx_http_echo_util.h" #include "ngx_http_echo_echo.h" #include ngx_http_output_header_filter_pt ngx_http_echo_next_header_filter; ngx_http_output_body_filter_pt ngx_http_echo_next_body_filter; static ngx_int_t ngx_http_echo_header_filter(ngx_http_request_t *r); static ngx_int_t ngx_http_echo_body_filter(ngx_http_request_t *r, ngx_chain_t *in); /* filter handlers */ static ngx_int_t ngx_http_echo_exec_filter_cmds(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *cmds, ngx_uint_t *iterator); static volatile ngx_cycle_t *ngx_http_echo_prev_cycle = NULL; ngx_int_t ngx_http_echo_filter_init(ngx_conf_t *cf) { int multi_http_blocks; ngx_http_echo_main_conf_t *emcf; emcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_echo_module); if (ngx_http_echo_prev_cycle != ngx_cycle) { ngx_http_echo_prev_cycle = ngx_cycle; multi_http_blocks = 0; } else { multi_http_blocks = 1; } if (multi_http_blocks || emcf->requires_filter) { dd("top header filter: %ld", (unsigned long) ngx_http_top_header_filter); ngx_http_echo_next_header_filter = ngx_http_top_header_filter; ngx_http_top_header_filter = ngx_http_echo_header_filter; dd("top body filter: %ld", (unsigned long) ngx_http_top_body_filter); ngx_http_echo_next_body_filter = ngx_http_top_body_filter; ngx_http_top_body_filter = ngx_http_echo_body_filter; } return NGX_OK; } static ngx_int_t ngx_http_echo_header_filter(ngx_http_request_t *r) { ngx_http_echo_loc_conf_t *conf; ngx_http_echo_ctx_t *ctx; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo header filter, uri \"%V?%V\"", &r->uri, &r->args); ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); /* XXX we should add option to insert contents for responses * of non-200 status code here... */ /* if (r->headers_out.status != NGX_HTTP_OK) { if (ctx != NULL) { ctx->skip_filter = 1; } return ngx_http_echo_next_header_filter(r); } */ conf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); if (conf->before_body_cmds == NULL && conf->after_body_cmds == NULL) { if (ctx != NULL) { ctx->skip_filter = 1; } return ngx_http_echo_next_header_filter(r); } if (ctx == NULL) { ctx = ngx_http_echo_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_echo_module); } /* enable streaming here (use chunked encoding) */ ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); return ngx_http_echo_next_header_filter(r); } static ngx_int_t ngx_http_echo_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_echo_ctx_t *ctx; ngx_int_t rc; ngx_http_echo_loc_conf_t *conf; unsigned last; ngx_chain_t *cl; ngx_buf_t *b; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo body filter, uri \"%V?%V\"", &r->uri, &r->args); if (in == NULL || r->header_only) { return ngx_http_echo_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL || ctx->skip_filter) { return ngx_http_echo_next_body_filter(r, in); } conf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); if (!ctx->before_body_sent) { ctx->before_body_sent = 1; if (conf->before_body_cmds != NULL) { rc = ngx_http_echo_exec_filter_cmds(r, ctx, conf->before_body_cmds, &ctx->next_before_body_cmd); if (rc != NGX_OK) { return NGX_ERROR; } } } if (conf->after_body_cmds == NULL) { ctx->skip_filter = 1; return ngx_http_echo_next_body_filter(r, in); } last = 0; for (cl = in; cl; cl = cl->next) { dd("cl %p, special %d", cl, ngx_buf_special(cl->buf)); if (cl->buf->last_buf || cl->buf->last_in_chain) { cl->buf->last_buf = 0; cl->buf->last_in_chain = 0; cl->buf->sync = 1; last = 1; } } dd("in %p, last %d", in, (int) last); if (in) { rc = ngx_http_echo_next_body_filter(r, in); #if 0 if (rc == NGX_AGAIN) { return NGX_ERROR; } #endif dd("next filter returns %d, last %d", (int) rc, (int) last); if (rc == NGX_ERROR || rc > NGX_OK || !last) { return rc; } } dd("exec filter cmds for after body cmds"); rc = ngx_http_echo_exec_filter_cmds(r, ctx, conf->after_body_cmds, &ctx->next_after_body_cmd); if (rc == NGX_ERROR || rc > NGX_OK) { dd("FAILED: exec filter cmds for after body cmds"); return NGX_ERROR; } ctx->skip_filter = 1; dd("after body cmds executed...terminating..."); /* XXX we can NOT use * ngx_http_send_special(r, NGX_HTTP_LAST) here * because we should bypass the upstream filters. */ b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } if (r == r->main && !r->post_action) { b->last_buf = 1; } else { b->sync = 1; b->last_in_chain = 1; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->next = NULL; cl->buf = b; return ngx_http_echo_next_body_filter(r, cl); } static ngx_int_t ngx_http_echo_exec_filter_cmds(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *cmds, ngx_uint_t *iterator) { ngx_int_t rc; ngx_array_t *opts = NULL; ngx_array_t *computed_args = NULL; ngx_http_echo_cmd_t *cmd; ngx_http_echo_cmd_t *cmd_elts; for (cmd_elts = cmds->elts; *iterator < cmds->nelts; (*iterator)++) { cmd = &cmd_elts[*iterator]; /* evaluate arguments for the current cmd (if any) */ if (cmd->args) { computed_args = ngx_array_create(r->pool, cmd->args->nelts, sizeof(ngx_str_t)); if (computed_args == NULL) { return NGX_ERROR; } opts = ngx_array_create(r->pool, 1, sizeof(ngx_str_t)); if (opts == NULL) { return NGX_ERROR; } rc = ngx_http_echo_eval_cmd_args(r, cmd, computed_args, opts); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to evaluate arguments for " "the directive."); return rc; } } /* do command dispatch based on the opcode */ switch (cmd->opcode) { case echo_opcode_echo_before_body: case echo_opcode_echo_after_body: dd("exec echo_before_body or echo_after_body..."); rc = ngx_http_echo_exec_echo(r, ctx, computed_args, 1 /* in filter */, opts); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } break; default: break; } } return NGX_OK; } debian/modules/nginx-echo/src/ngx_http_echo_module.h0000664000000000000000000000701012705233614020036 0ustar /* Copyright (C) by agentzh */ #ifndef NGX_HTTP_ECHO_MODULE_H #define NGX_HTTP_ECHO_MODULE_H #include #include #include extern ngx_module_t ngx_http_echo_module; /* config directive's opcode */ typedef enum { echo_opcode_echo_sync, echo_opcode_echo, echo_opcode_echo_request_body, echo_opcode_echo_sleep, echo_opcode_echo_flush, echo_opcode_echo_blocking_sleep, echo_opcode_echo_reset_timer, echo_opcode_echo_before_body, echo_opcode_echo_after_body, echo_opcode_echo_location_async, echo_opcode_echo_location, echo_opcode_echo_subrequest_async, echo_opcode_echo_subrequest, echo_opcode_echo_duplicate, echo_opcode_echo_read_request_body, echo_opcode_echo_foreach_split, echo_opcode_echo_end, echo_opcode_echo_abort_parent, echo_opcode_echo_exec } ngx_http_echo_opcode_t; /* all the various config directives (or commands) are * divided into two categories: "handler commands", * and "filter commands". For instance, the "echo" * directive is a handler command while * "echo_before_body" is a filter one. */ typedef enum { echo_handler_cmd, echo_filter_cmd } ngx_http_echo_cmd_category_t; /* compiled form of a config directive argument's value */ typedef struct { /* holds the raw string of the argument value */ ngx_str_t raw_value; /* fields "lengths" and "values" are set by * the function ngx_http_script_compile, * iff the argument value indeed contains * nginx variables like "$foo" */ ngx_array_t *lengths; ngx_array_t *values; } ngx_http_echo_arg_template_t; /* represent a config directive (or command) like "echo". */ typedef struct { ngx_http_echo_opcode_t opcode; /* each argument is of type echo_arg_template_t: */ ngx_array_t *args; } ngx_http_echo_cmd_t; /* location config struct */ typedef struct { /* elements of the following arrays are of type * ngx_http_echo_cmd_t */ ngx_array_t *handler_cmds; ngx_array_t *before_body_cmds; ngx_array_t *after_body_cmds; unsigned seen_leading_output; ngx_int_t status; } ngx_http_echo_loc_conf_t; typedef struct { ngx_int_t requires_filter; } ngx_http_echo_main_conf_t; typedef struct { ngx_array_t *choices; /* items after splitting */ ngx_uint_t next_choice; /* current item index */ ngx_uint_t cmd_index; /* cmd index for the echo_foreach direcitve */ } ngx_http_echo_foreach_ctx_t; /* context struct in the request handling cycle, holding * the current states of the command evaluator */ typedef struct { /* index of the next handler command in * ngx_http_echo_loc_conf_t's "handler_cmds" array. */ ngx_uint_t next_handler_cmd; /* index of the next before-body filter command in * ngx_http_echo_loc_conf_t's "before_body_cmds" array. */ ngx_uint_t next_before_body_cmd; /* index of the next after-body filter command in * ngx_http_echo_loc_conf_t's "after_body_cmds" array. */ ngx_uint_t next_after_body_cmd; ngx_http_echo_foreach_ctx_t *foreach; ngx_time_t timer_begin; ngx_event_t sleep; ngx_uint_t counter; unsigned before_body_sent:1; unsigned skip_filter:1; unsigned wait_read_request_body:1; unsigned waiting:1; unsigned done:1; unsigned run_post_subrequest:1; } ngx_http_echo_ctx_t; #endif /* NGX_HTTP_ECHO_MODULE_H */ debian/modules/nginx-echo/src/ngx_http_echo_foreach.c0000664000000000000000000001137012705233614020157 0ustar #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_foreach.h" #include "ngx_http_echo_util.h" #include ngx_int_t ngx_http_echo_it_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_echo_ctx_t *ctx; ngx_uint_t i; ngx_array_t *choices; ngx_str_t *choice_elts, *choice; ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx && ctx->foreach != NULL) { choices = ctx->foreach->choices; i = ctx->foreach->next_choice; if (i < choices->nelts) { choice_elts = choices->elts; choice = &choice_elts[i]; v->len = choice->len; v->data = choice->data; v->valid = 1; v->no_cacheable = 1; v->not_found = 0; return NGX_OK; } } v->not_found = 1; return NGX_OK; } ngx_int_t ngx_http_echo_exec_echo_foreach_split(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_http_echo_loc_conf_t *elcf; ngx_str_t *delimiter, *compound; u_char *pos, *last, *end; ngx_str_t *choice; ngx_str_t *computed_arg_elts; ngx_array_t *cmds; ngx_http_echo_cmd_t *cmd; ngx_http_echo_cmd_t *cmd_elts; if (ctx->foreach != NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Nested echo_foreach not supported yet."); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (computed_args->nelts < 2) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "echo_foreach should take at least two arguments. " "(if your delimiter starts with \"-\", preceding it " "with a \"--\".)"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } computed_arg_elts = computed_args->elts; compound = &computed_arg_elts[1]; dd("HEY coumpound len: %u", (int) compound->len); ctx->foreach = ngx_palloc(r->pool, sizeof(ngx_http_echo_foreach_ctx_t)); if (ctx->foreach == NULL) { return NGX_ERROR; } ctx->foreach->cmd_index = ctx->next_handler_cmd; ctx->foreach->next_choice = 0; ctx->foreach->choices = ngx_array_create(r->pool, 10, sizeof(ngx_str_t)); if (ctx->foreach->choices == NULL) { return NGX_ERROR; } delimiter = &computed_arg_elts[0]; pos = compound->data; end = compound->data + compound->len; while ((last = ngx_http_echo_strlstrn(pos, end, delimiter->data, delimiter->len - 1)) != NULL) { dd("entered the loop"); if (last == pos) { dd("!!! len == 0"); pos = last + delimiter->len; continue; } choice = ngx_array_push(ctx->foreach->choices); if (choice == NULL) { return NGX_ERROR; } choice->data = pos; choice->len = last - pos; pos = last + delimiter->len; } if (pos < end) { choice = ngx_array_push(ctx->foreach->choices); if (choice == NULL) { return NGX_ERROR; } choice->data = pos; choice->len = end - pos; } if (ctx->foreach->choices->nelts == 0) { /* skip the foreach body entirely */ elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); cmds = elcf->handler_cmds; cmd_elts = cmds->elts; for (/* void */; ctx->next_handler_cmd < cmds->nelts; ctx->next_handler_cmd++) { cmd = &cmd_elts[ctx->next_handler_cmd + 1]; if (cmd->opcode == echo_opcode_echo_end) { return NGX_OK; } } } return NGX_OK; } ngx_int_t ngx_http_echo_exec_echo_end(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx) { if (ctx->foreach == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Found a echo_end that has no corresponding echo_foreach " "before it."); return NGX_ERROR; } ctx->foreach->next_choice++; if (ctx->foreach->next_choice >= ctx->foreach->choices->nelts) { /* TODO We need to explicitly free the foreach ctx from * the pool */ ctx->foreach = NULL; return NGX_OK; } dd("echo_end: ++ next_choice (total: %u): %u", (unsigned) ctx->foreach->choices->nelts, (unsigned) ctx->foreach->next_choice); /* the main handler dispatcher loop will increment * ctx->next_handler_cmd for us anyway. */ ctx->next_handler_cmd = ctx->foreach->cmd_index; return NGX_OK; } debian/modules/nginx-echo/src/ngx_http_echo_sleep.c0000664000000000000000000001101212705233614017651 0ustar /* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_sleep.h" #include "ngx_http_echo_handler.h" #include #include /* event handler for echo_sleep */ static void ngx_http_echo_post_sleep(ngx_http_request_t *r); static void ngx_http_echo_sleep_cleanup(void *data); ngx_int_t ngx_http_echo_exec_echo_sleep(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_str_t *computed_arg; ngx_str_t *computed_arg_elts; ngx_int_t delay; /* in msec */ ngx_http_cleanup_t *cln; computed_arg_elts = computed_args->elts; computed_arg = &computed_arg_elts[0]; delay = ngx_atofp(computed_arg->data, computed_arg->len, 3); if (delay == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid sleep duration \"%V\"", &computed_arg_elts[0]); return NGX_HTTP_BAD_REQUEST; } dd("adding timer with delay %lu ms, r:%.*s", (unsigned long) delay, (int) r->uri.len, r->uri.data); ngx_add_timer(&ctx->sleep, (ngx_msec_t) delay); /* we don't check broken downstream connections * ourselves so even if the client shuts down * the connection prematurely, nginx will still * go on waiting for our timers to get properly * expired. However, we'd still register a * cleanup handler for completeness. */ cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_echo_sleep_cleanup; cln->data = r; return NGX_AGAIN; } static void ngx_http_echo_post_sleep(ngx_http_request_t *r) { ngx_http_echo_ctx_t *ctx; /* ngx_int_t rc; */ dd("post sleep, r:%.*s", (int) r->uri.len, r->uri.data); ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL) { return; } ctx->waiting = 0; ctx->done = 1; dd("sleep: after get module ctx"); dd("timed out? %d", ctx->sleep.timedout); dd("timer set? %d", ctx->sleep.timer_set); if (!ctx->sleep.timedout) { dd("HERE reached!"); return; } ctx->sleep.timedout = 0; if (ctx->sleep.timer_set) { dd("deleting timer for echo_sleep"); ngx_del_timer(&ctx->sleep); } /* r->write_event_handler = ngx_http_request_empty_handler; */ ngx_http_echo_wev_handler(r); } void ngx_http_echo_sleep_event_handler(ngx_event_t *ev) { ngx_connection_t *c; ngx_http_request_t *r; ngx_http_log_ctx_t *ctx; r = ev->data; c = r->connection; if (c->destroyed) { return; } if (c->error) { ngx_http_finalize_request(r, NGX_ERROR); return; } ctx = c->log->data; ctx->current_request = r; /* XXX when r->done == 1 we should do cleaning immediately * and delete our timer and then quit. */ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "echo sleep handler: \"%V?%V\"", &r->uri, &r->args); /* if (r->done) { return; } */ ngx_http_echo_post_sleep(r); #if defined(nginx_version) dd("before run posted requests"); ngx_http_run_posted_requests(c); dd("after run posted requests"); #endif } ngx_int_t ngx_http_echo_exec_echo_blocking_sleep(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_str_t *computed_arg; ngx_str_t *computed_arg_elts; ngx_int_t delay; /* in msec */ computed_arg_elts = computed_args->elts; computed_arg = &computed_arg_elts[0]; delay = ngx_atofp(computed_arg->data, computed_arg->len, 3); if (delay == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid sleep duration \"%V\"", &computed_arg_elts[0]); return NGX_HTTP_BAD_REQUEST; } dd("blocking delay: %lu ms", (unsigned long) delay); ngx_msleep((ngx_msec_t) delay); return NGX_OK; } static void ngx_http_echo_sleep_cleanup(void *data) { ngx_http_request_t *r = data; ngx_http_echo_ctx_t *ctx; dd("echo sleep cleanup"); ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL) { return; } if (ctx->sleep.timer_set) { dd("cleanup: deleting timer for echo_sleep"); ngx_del_timer(&ctx->sleep); return; } dd("cleanup: timer not set"); } debian/modules/nginx-echo/src/ngx_http_echo_request_info.h0000664000000000000000000000217112705233614021257 0ustar #ifndef ECHO_REQUEST_INFO_H #define ECHO_REQUEST_INFO_H #include "ngx_http_echo_module.h" ngx_int_t ngx_http_echo_exec_echo_read_request_body( ngx_http_request_t* r, ngx_http_echo_ctx_t *ctx); ngx_int_t ngx_http_echo_request_method_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); ngx_int_t ngx_http_echo_client_request_method_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); ngx_int_t ngx_http_echo_request_body_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); ngx_int_t ngx_http_echo_client_request_headers_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); ngx_int_t ngx_http_echo_cacheable_request_uri_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); ngx_int_t ngx_http_echo_request_uri_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); ngx_int_t ngx_http_echo_response_status_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); #endif /* ECHO_REQUEST_INFO_H */ debian/modules/nginx-echo/src/ngx_http_echo_timer.c0000664000000000000000000000412512705233614017670 0ustar #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_timer.h" #include "ngx_http_echo_util.h" #include #include #include ngx_int_t ngx_http_echo_timer_elapsed_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_echo_ctx_t *ctx; ngx_msec_int_t ms; u_char *p; ngx_time_t *tp; size_t size; ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx == NULL) { ctx = ngx_http_echo_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_echo_module); } if (ctx->timer_begin.sec == 0) { ctx->timer_begin.sec = r->start_sec; ctx->timer_begin.msec = (ngx_msec_t) r->start_msec; } /* force the ngx timer to update */ #if (nginx_version >= 8035) || (nginx_version < 8000 && nginx_version >= 7066) ngx_time_update(); #else ngx_time_update(0, 0); #endif tp = ngx_timeofday(); dd("old sec msec: %ld %d\n", (long) ctx->timer_begin.sec, (int) ctx->timer_begin.msec); dd("new sec msec: %ld %d\n", (long) tp->sec, (int) tp->msec); ms = (ngx_msec_int_t) ((tp->sec - ctx->timer_begin.sec) * 1000 + (tp->msec - ctx->timer_begin.msec)); ms = (ms >= 0) ? ms : 0; size = sizeof("-9223372036854775808.000") - 1; p = ngx_palloc(r->pool, size); if (p == NULL) { return NGX_ERROR; } v->len = ngx_snprintf(p, size, "%T.%03M", ms / 1000, ms % 1000) - p; v->data = p; v->valid = 1; v->no_cacheable = 1; v->not_found = 0; return NGX_OK; } ngx_int_t ngx_http_echo_exec_echo_reset_timer(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx) { dd("Exec timer..."); /* force the ngx timer to update */ #if (nginx_version >= 8035) || (nginx_version < 8000 && nginx_version >= 7066) ngx_time_update(); #else ngx_time_update(0, 0); #endif ctx->timer_begin = *ngx_timeofday(); return NGX_OK; } debian/modules/nginx-echo/src/ngx_http_echo_var.h0000664000000000000000000000023312705233614017341 0ustar #ifndef ECHO_VAR_H #define ECHO_VAR_H #include "ngx_http_echo_module.h" ngx_int_t ngx_http_echo_add_variables(ngx_conf_t *cf); #endif /* ECHO_VAR_H */ debian/modules/nginx-echo/src/ngx_http_echo_location.c0000664000000000000000000001053012705233614020355 0ustar #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_util.h" #include "ngx_http_echo_location.h" #include "ngx_http_echo_handler.h" #include static ngx_int_t ngx_http_echo_adjust_subrequest(ngx_http_request_t *sr); ngx_int_t ngx_http_echo_exec_echo_location_async(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_int_t rc; ngx_http_request_t *sr; /* subrequest object */ ngx_str_t *computed_arg_elts; ngx_str_t location; ngx_str_t *url_args; ngx_str_t args; ngx_uint_t flags = 0; dd_enter(); computed_arg_elts = computed_args->elts; location = computed_arg_elts[0]; if (location.len == 0) { return NGX_ERROR; } if (computed_args->nelts > 1) { url_args = &computed_arg_elts[1]; } else { url_args = NULL; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, &location, &args, &flags) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo_location_async sees unsafe uri: \"%V\"", &location); return NGX_ERROR; } if (args.len > 0 && url_args == NULL) { url_args = &args; } rc = ngx_http_echo_send_header_if_needed(r, ctx); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } rc = ngx_http_subrequest(r, &location, url_args, &sr, NULL, 0); if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_http_echo_adjust_subrequest(sr); if (rc != NGX_OK) { return NGX_ERROR; } return NGX_OK; } ngx_int_t ngx_http_echo_exec_echo_location(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_int_t rc; ngx_http_request_t *sr; /* subrequest object */ ngx_str_t *computed_arg_elts; ngx_str_t location; ngx_str_t *url_args; ngx_http_post_subrequest_t *psr; ngx_str_t args; ngx_uint_t flags = 0; ngx_http_echo_ctx_t *sr_ctx; computed_arg_elts = computed_args->elts; location = computed_arg_elts[0]; if (location.len == 0) { return NGX_ERROR; } if (computed_args->nelts > 1) { url_args = &computed_arg_elts[1]; } else { url_args = NULL; } args.data = NULL; args.len = 0; if (ngx_http_parse_unsafe_uri(r, &location, &args, &flags) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "echo_location sees unsafe uri: \"%V\"", &location); return NGX_ERROR; } if (args.len > 0 && url_args == NULL) { url_args = &args; } rc = ngx_http_echo_send_header_if_needed(r, ctx); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } sr_ctx = ngx_http_echo_create_ctx(r); psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { return NGX_ERROR; } psr->handler = ngx_http_echo_post_subrequest; psr->data = sr_ctx; rc = ngx_http_subrequest(r, &location, url_args, &sr, psr, 0); if (rc != NGX_OK) { return NGX_ERROR; } rc = ngx_http_echo_adjust_subrequest(sr); if (rc != NGX_OK) { return NGX_ERROR; } return NGX_AGAIN; } static ngx_int_t ngx_http_echo_adjust_subrequest(ngx_http_request_t *sr) { ngx_http_core_main_conf_t *cmcf; ngx_http_request_t *r; /* we do not inherit the parent request's variables */ cmcf = ngx_http_get_module_main_conf(sr, ngx_http_core_module); r = sr->parent; sr->header_in = r->header_in; /* XXX work-around a bug in ngx_http_subrequest */ if (r->headers_in.headers.last == &r->headers_in.headers.part) { sr->headers_in.headers.last = &sr->headers_in.headers.part; } sr->variables = ngx_pcalloc(sr->pool, cmcf->variables.nelts * sizeof(ngx_http_variable_value_t)); if (sr->variables == NULL) { return NGX_ERROR; } return NGX_OK; } debian/modules/nginx-echo/src/ngx_http_echo_sleep.h0000664000000000000000000000066312705233614017670 0ustar #ifndef ECHO_SLEEP_H #define ECHO_SLEEP_H #include "ngx_http_echo_module.h" ngx_int_t ngx_http_echo_exec_echo_sleep( ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); ngx_int_t ngx_http_echo_exec_echo_blocking_sleep(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); void ngx_http_echo_sleep_event_handler(ngx_event_t *ev); #endif /* ECHO_SLEEP_H */ debian/modules/nginx-echo/src/ngx_http_echo_util.h0000664000000000000000000000276412705233614017541 0ustar /* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef NGX_HTTP_ECHO_UTIL_H #define NGX_HTTP_ECHO_UTIL_H #include "ngx_http_echo_module.h" #define ngx_http_echo_strcmp_const(a, b) \ ngx_strncmp(a, b, sizeof(b) - 1) #define ngx_http_echo_hash_literal(s) \ ngx_http_echo_hash_str((u_char *) s, sizeof(s) - 1) static ngx_inline ngx_uint_t ngx_http_echo_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_echo_content_length_hash; ngx_http_echo_ctx_t * ngx_http_echo_create_ctx(ngx_http_request_t *r); ngx_int_t ngx_http_echo_eval_cmd_args(ngx_http_request_t *r, ngx_http_echo_cmd_t *cmd, ngx_array_t *computed_args, ngx_array_t *opts); ngx_int_t ngx_http_echo_send_header_if_needed(ngx_http_request_t* r, ngx_http_echo_ctx_t *ctx); ngx_int_t ngx_http_echo_send_chain_link(ngx_http_request_t* r, ngx_http_echo_ctx_t *ctx, ngx_chain_t *cl); ssize_t ngx_http_echo_atosz(u_char *line, size_t n); u_char * ngx_http_echo_strlstrn(u_char *s1, u_char *last, u_char *s2, size_t n); ngx_int_t ngx_http_echo_post_request_at_head(ngx_http_request_t *r, ngx_http_posted_request_t *pr); u_char * ngx_http_echo_rebase_path(ngx_pool_t *pool, u_char *src, size_t osize, size_t *nsize); ngx_int_t ngx_http_echo_flush_postponed_outputs(ngx_http_request_t *r); #endif /* NGX_HTTP_ECHO_UTIL_H */ debian/modules/nginx-echo/src/ngx_http_echo_echo.h0000664000000000000000000000136612705233614017477 0ustar #ifndef ECHO_ECHO_H #define ECHO_ECHO_H #include "ngx_http_echo_module.h" ngx_int_t ngx_http_echo_echo_init(ngx_conf_t *cf); ngx_int_t ngx_http_echo_exec_echo_sync(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx); ngx_int_t ngx_http_echo_exec_echo(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args, ngx_flag_t in_filter, ngx_array_t *opts); ngx_int_t ngx_http_echo_exec_echo_request_body(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx); ngx_int_t ngx_http_echo_exec_echo_flush(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx); ngx_int_t ngx_http_echo_exec_echo_duplicate(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); #endif /* ECHO_ECHO_H */ debian/modules/nginx-echo/src/ngx_http_echo_location.h0000664000000000000000000000057412705233614020371 0ustar #ifndef ECHO_LOCATION_H #define ECHO_LOCATION_H #include "ngx_http_echo_module.h" ngx_int_t ngx_http_echo_exec_echo_location_async(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); ngx_int_t ngx_http_echo_exec_echo_location(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args); #endif /* ECHO_LOCATION_H */ debian/modules/nginx-echo/src/ngx_http_echo_module.c0000664000000000000000000004575312705233614020051 0ustar /* * Copyright (C) Yichun Zhang (agentzh) */ #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_handler.h" #include "ngx_http_echo_filter.h" #include "ngx_http_echo_echo.h" #include "ngx_http_echo_request_info.h" #include "ngx_http_echo_var.h" #include "ngx_http_echo_util.h" #include #include #include /* config init handler */ static void * ngx_http_echo_create_loc_conf(ngx_conf_t *cf); static char * ngx_http_echo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); static void *ngx_http_echo_create_main_conf(ngx_conf_t *cf); static ngx_int_t ngx_http_echo_post_config(ngx_conf_t *cf); /* config directive handlers */ static char * ngx_http_echo_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_request_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_sleep(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_flush(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_blocking_sleep(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_reset_timer(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_before_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_after_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_location_async(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_location(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_subrequest_async(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_subrequest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_duplicate(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_read_request_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_foreach_split(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_end(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_abort_parent(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_echo_exec(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char * ngx_http_echo_helper(ngx_http_echo_opcode_t opcode, ngx_http_echo_cmd_category_t cat, ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_http_module_t ngx_http_echo_module_ctx = { NULL, /* preconfiguration */ ngx_http_echo_post_config, /* postconfiguration */ ngx_http_echo_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_echo_create_loc_conf, /* create location configuration */ ngx_http_echo_merge_loc_conf /* merge location configuration */ }; static ngx_command_t ngx_http_echo_commands[] = { { ngx_string("echo"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY, ngx_http_echo_echo, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_request_body"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS, ngx_http_echo_echo_request_body, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_sleep"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, ngx_http_echo_echo_sleep, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_flush"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS, ngx_http_echo_echo_flush, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_blocking_sleep"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, ngx_http_echo_echo_blocking_sleep, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_reset_timer"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS, ngx_http_echo_echo_reset_timer, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_before_body"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY, ngx_http_echo_echo_before_body, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, before_body_cmds), NULL }, { ngx_string("echo_after_body"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_ANY, ngx_http_echo_echo_after_body, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, after_body_cmds), NULL }, { ngx_string("echo_location_async"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, ngx_http_echo_echo_location_async, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_location"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, ngx_http_echo_echo_location, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_subrequest_async"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE, ngx_http_echo_echo_subrequest_async, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_subrequest"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE, ngx_http_echo_echo_subrequest, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_duplicate"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE, ngx_http_echo_echo_duplicate, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_read_request_body"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS, ngx_http_echo_echo_read_request_body, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_foreach_split"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_2MORE, ngx_http_echo_echo_foreach_split, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_end"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS, ngx_http_echo_echo_end, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_abort_parent"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_NOARGS, ngx_http_echo_echo_abort_parent, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_exec"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, ngx_http_echo_echo_exec, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, handler_cmds), NULL }, { ngx_string("echo_status"), NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_echo_loc_conf_t, status), NULL }, ngx_null_command }; ngx_module_t ngx_http_echo_module = { NGX_MODULE_V1, &ngx_http_echo_module_ctx, /* module context */ ngx_http_echo_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING }; static void * ngx_http_echo_create_loc_conf(ngx_conf_t *cf) { ngx_http_echo_loc_conf_t *conf; conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_loc_conf_t)); if (conf == NULL) { return NULL; } /* set by ngx_pcalloc * conf->handler_cmds = NULL * conf->before_body_cmds = NULL * conf->after_body_cmds = NULL * conf->seen_leading_output = 0 * conf->seen_trailing_output = 0 */ conf->status = NGX_CONF_UNSET; return conf; } static char * ngx_http_echo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_echo_loc_conf_t *prev = parent; ngx_http_echo_loc_conf_t *conf = child; if (conf->handler_cmds == NULL) { conf->handler_cmds = prev->handler_cmds; conf->seen_leading_output = prev->seen_leading_output; } if (conf->before_body_cmds == NULL) { conf->before_body_cmds = prev->before_body_cmds; } if (conf->after_body_cmds == NULL) { conf->after_body_cmds = prev->after_body_cmds; } ngx_conf_merge_value(conf->status, prev->status, 200); return NGX_CONF_OK; } static char * ngx_http_echo_helper(ngx_http_echo_opcode_t opcode, ngx_http_echo_cmd_category_t cat, ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *raw_args; ngx_uint_t i, n; ngx_array_t **args_ptr; ngx_array_t **cmds_ptr; ngx_http_echo_cmd_t *echo_cmd; ngx_http_core_loc_conf_t *clcf; ngx_http_script_compile_t sc; ngx_http_echo_main_conf_t *emcf; ngx_http_echo_arg_template_t *arg; emcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_echo_module); /* cmds_ptr points to ngx_http_echo_loc_conf_t's * handler_cmds, before_body_cmds, or after_body_cmds * array, depending on the actual offset */ cmds_ptr = (ngx_array_t**)(((u_char*)conf) + cmd->offset); if (*cmds_ptr == NULL) { *cmds_ptr = ngx_array_create(cf->pool, 1, sizeof(ngx_http_echo_cmd_t)); if (*cmds_ptr == NULL) { return NGX_CONF_ERROR; } if (cat == echo_handler_cmd) { dd("registering the content handler"); /* register the content handler */ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); dd("registering the content handler (2)"); clcf->handler = ngx_http_echo_handler; } else { dd("filter used = 1"); emcf->requires_filter = 1; } } echo_cmd = ngx_array_push(*cmds_ptr); if (echo_cmd == NULL) { return NGX_CONF_ERROR; } echo_cmd->opcode = opcode; args_ptr = &echo_cmd->args; *args_ptr = ngx_array_create(cf->pool, 1, sizeof(ngx_http_echo_arg_template_t)); if (*args_ptr == NULL) { return NGX_CONF_ERROR; } raw_args = cf->args->elts; /* we skip the first arg and start from the second */ for (i = 1 ; i < cf->args->nelts; i++) { arg = ngx_array_push(*args_ptr); if (arg == NULL) { return NGX_CONF_ERROR; } arg->raw_value = raw_args[i]; dd("found raw arg %s", raw_args[i].data); arg->lengths = NULL; arg->values = NULL; n = ngx_http_script_variables_count(&arg->raw_value); if (n > 0) { ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); sc.cf = cf; sc.source = &arg->raw_value; sc.lengths = &arg->lengths; sc.values = &arg->values; sc.variables = n; sc.complete_lengths = 1; sc.complete_values = 1; if (ngx_http_script_compile(&sc) != NGX_OK) { return NGX_CONF_ERROR; } } } /* end for */ return NGX_CONF_OK; } static char * ngx_http_echo_echo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_echo_loc_conf_t *elcf = conf; if (!elcf->seen_leading_output) { elcf->seen_leading_output = 1; } dd("in echo_echo..."); return ngx_http_echo_helper(echo_opcode_echo, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_request_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_echo_loc_conf_t *elcf = conf; if (!elcf->seen_leading_output) { elcf->seen_leading_output = 1; } dd("in echo_echo_request_body..."); return ngx_http_echo_helper(echo_opcode_echo_request_body, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_sleep(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { dd("in echo_sleep..."); return ngx_http_echo_helper(echo_opcode_echo_sleep, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_flush(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_echo_loc_conf_t *elcf = conf; if (!elcf->seen_leading_output) { elcf->seen_leading_output = 1; } dd("in echo_flush..."); return ngx_http_echo_helper(echo_opcode_echo_flush, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_blocking_sleep(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { dd("in echo_blocking_sleep..."); return ngx_http_echo_helper(echo_opcode_echo_blocking_sleep, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_reset_timer(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { return ngx_http_echo_helper(echo_opcode_echo_reset_timer, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_before_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { dd("processing echo_before_body directive..."); return ngx_http_echo_helper(echo_opcode_echo_before_body, echo_filter_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_after_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { return ngx_http_echo_helper(echo_opcode_echo_after_body, echo_filter_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_location_async(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_echo_loc_conf_t *elcf = conf; char *ret; if (!elcf->seen_leading_output) { elcf->seen_leading_output = 1; ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd, cf, cmd, conf); if (ret != NGX_CONF_OK) { return ret; } } return ngx_http_echo_helper(echo_opcode_echo_location_async, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_location(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_echo_loc_conf_t *elcf = conf; char *ret; if (!elcf->seen_leading_output) { elcf->seen_leading_output = 1; ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd, cf, cmd, conf); if (ret != NGX_CONF_OK) { return ret; } } return ngx_http_echo_helper(echo_opcode_echo_location, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_subrequest_async(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *ret; ngx_http_echo_loc_conf_t *elcf = conf; if (!elcf->seen_leading_output) { elcf->seen_leading_output = 1; ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd, cf, cmd, conf); if (ret != NGX_CONF_OK) { return ret; } } return ngx_http_echo_helper(echo_opcode_echo_subrequest_async, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_subrequest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_echo_loc_conf_t *elcf = conf; char *ret; if (!elcf->seen_leading_output) { elcf->seen_leading_output = 1; ret = ngx_http_echo_helper(echo_opcode_echo_sync, echo_handler_cmd, cf, cmd, conf); if (ret != NGX_CONF_OK) { return ret; } } return ngx_http_echo_helper(echo_opcode_echo_subrequest, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_duplicate(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_echo_loc_conf_t *elcf = conf; if (!elcf->seen_leading_output) { elcf->seen_leading_output = 1; } return ngx_http_echo_helper(echo_opcode_echo_duplicate, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_read_request_body(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { return ngx_http_echo_helper(echo_opcode_echo_read_request_body, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_foreach_split(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { return ngx_http_echo_helper(echo_opcode_echo_foreach_split, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_end(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { return ngx_http_echo_helper(echo_opcode_echo_end, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_abort_parent(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { return ngx_http_echo_helper(echo_opcode_echo_abort_parent, echo_handler_cmd, cf, cmd, conf); } static char * ngx_http_echo_echo_exec(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { return ngx_http_echo_helper(echo_opcode_echo_exec, echo_handler_cmd, cf, cmd, conf); } static void * ngx_http_echo_create_main_conf(ngx_conf_t *cf) { ngx_http_echo_main_conf_t *emcf; emcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_echo_main_conf_t)); if (emcf == NULL) { return NULL; } /* set by ngx_pcalloc: * hmcf->requires_filter = 0; */ return emcf; } static ngx_int_t ngx_http_echo_post_config(ngx_conf_t *cf) { ngx_int_t rc; rc = ngx_http_echo_filter_init(cf); if (rc != NGX_OK) { return rc; } rc = ngx_http_echo_echo_init(cf); if (rc != NGX_OK) { return rc; } ngx_http_echo_content_length_hash = ngx_http_echo_hash_literal("content-length"); return ngx_http_echo_add_variables(cf); } debian/modules/nginx-echo/src/ngx_http_echo_echo.c0000664000000000000000000001777612705233614017506 0ustar #ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_echo.h" #include "ngx_http_echo_util.h" #include "ngx_http_echo_filter.h" #include static ngx_buf_t ngx_http_echo_space_buf; static ngx_buf_t ngx_http_echo_newline_buf; ngx_int_t ngx_http_echo_echo_init(ngx_conf_t *cf) { static u_char space_str[] = " "; static u_char newline_str[] = "\n"; dd("global init..."); ngx_memzero(&ngx_http_echo_space_buf, sizeof(ngx_buf_t)); ngx_http_echo_space_buf.memory = 1; ngx_http_echo_space_buf.start = ngx_http_echo_space_buf.pos = space_str; ngx_http_echo_space_buf.end = ngx_http_echo_space_buf.last = space_str + sizeof(space_str) - 1; ngx_memzero(&ngx_http_echo_newline_buf, sizeof(ngx_buf_t)); ngx_http_echo_newline_buf.memory = 1; ngx_http_echo_newline_buf.start = ngx_http_echo_newline_buf.pos = newline_str; ngx_http_echo_newline_buf.end = ngx_http_echo_newline_buf.last = newline_str + sizeof(newline_str) - 1; return NGX_OK; } ngx_int_t ngx_http_echo_exec_echo_sync(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx) { ngx_buf_t *buf; ngx_chain_t *cl = NULL; /* the head of the chain link */ buf = ngx_calloc_buf(r->pool); if (buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } buf->sync = 1; cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->buf = buf; cl->next = NULL; return ngx_http_echo_send_chain_link(r, ctx, cl); } ngx_int_t ngx_http_echo_exec_echo(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args, ngx_flag_t in_filter, ngx_array_t *opts) { ngx_uint_t i; ngx_buf_t *space_buf; ngx_buf_t *newline_buf; ngx_buf_t *buf; ngx_str_t *computed_arg; ngx_str_t *computed_arg_elts; ngx_str_t *opt; ngx_chain_t *cl = NULL; /* the head of the chain link */ ngx_chain_t **ll = &cl; /* always point to the address of the last link */ dd_enter(); if (computed_args == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } computed_arg_elts = computed_args->elts; for (i = 0; i < computed_args->nelts; i++) { computed_arg = &computed_arg_elts[i]; if (computed_arg->len == 0) { buf = NULL; } else { buf = ngx_calloc_buf(r->pool); if (buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } buf->start = buf->pos = computed_arg->data; buf->last = buf->end = computed_arg->data + computed_arg->len; buf->memory = 1; } if (cl == NULL) { cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->buf = buf; cl->next = NULL; ll = &cl->next; } else { /* append a space first */ *ll = ngx_alloc_chain_link(r->pool); if (*ll == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } space_buf = ngx_calloc_buf(r->pool); if (space_buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* nginx clears buf flags at the end of each request handling, * so we have to make a clone here. */ *space_buf = ngx_http_echo_space_buf; (*ll)->buf = space_buf; (*ll)->next = NULL; ll = &(*ll)->next; /* then append the buf only if it's non-empty */ if (buf) { *ll = ngx_alloc_chain_link(r->pool); if (*ll == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } (*ll)->buf = buf; (*ll)->next = NULL; ll = &(*ll)->next; } } } /* end for */ if (cl && cl->buf == NULL) { cl = cl->next; } if (opts && opts->nelts > 0) { opt = opts->elts; if (opt[0].len == 1 && opt[0].data[0] == 'n') { goto done; } } /* append the newline character */ newline_buf = ngx_calloc_buf(r->pool); if (newline_buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } *newline_buf = ngx_http_echo_newline_buf; if (cl == NULL) { cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->buf = newline_buf; cl->next = NULL; /* ll = &cl->next; */ } else { *ll = ngx_alloc_chain_link(r->pool); if (*ll == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } (*ll)->buf = newline_buf; (*ll)->next = NULL; /* ll = &(*ll)->next; */ } done: if (cl == NULL || cl->buf == NULL) { return NGX_OK; } if (in_filter) { return ngx_http_echo_next_body_filter(r, cl); } return ngx_http_echo_send_chain_link(r, ctx, cl); } ngx_int_t ngx_http_echo_exec_echo_flush(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx) { return ngx_http_send_special(r, NGX_HTTP_FLUSH); } ngx_int_t ngx_http_echo_exec_echo_request_body(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx) { ngx_buf_t *b; ngx_chain_t *out, *cl, **ll; if (r->request_body == NULL || r->request_body->bufs == NULL) { return NGX_OK; } out = NULL; ll = &out; for (cl = r->request_body->bufs; cl; cl = cl->next) { if (ngx_buf_special(cl->buf)) { /* we do not want to create zero-size bufs */ continue; } *ll = ngx_alloc_chain_link(r->pool); if (*ll == NULL) { return NGX_ERROR; } b = ngx_alloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } (*ll)->buf = b; (*ll)->next = NULL; ngx_memcpy(b, cl->buf, sizeof(ngx_buf_t)); b->tag = (ngx_buf_tag_t) &ngx_http_echo_exec_echo_request_body; b->last_buf = 0; b->last_in_chain = 0; ll = &(*ll)->next; } if (out == NULL) { return NGX_OK; } return ngx_http_echo_send_chain_link(r, ctx, out); } ngx_int_t ngx_http_echo_exec_echo_duplicate(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_str_t *computed_arg; ngx_str_t *computed_arg_elts; ssize_t i, count; ngx_str_t *str; u_char *p; ngx_int_t rc; ngx_buf_t *buf; ngx_chain_t *cl; dd_enter(); computed_arg_elts = computed_args->elts; computed_arg = &computed_arg_elts[0]; count = ngx_http_echo_atosz(computed_arg->data, computed_arg->len); if (count == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid size specified: \"%V\"", computed_arg); return NGX_HTTP_INTERNAL_SERVER_ERROR; } str = &computed_arg_elts[1]; if (count == 0 || str->len == 0) { rc = ngx_http_echo_send_header_if_needed(r, ctx); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return NGX_OK; } buf = ngx_create_temp_buf(r->pool, count * str->len); if (buf == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } p = buf->pos; for (i = 0; i < count; i++) { p = ngx_copy(p, str->data, str->len); } buf->last = p; cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cl->next = NULL; cl->buf = buf; return ngx_http_echo_send_chain_link(r, ctx, cl); } debian/modules/nginx-echo/valgrind.suppress0000664000000000000000000000124512705233614016320 0ustar { Memcheck:Addr4 fun:lj_str_new fun:lua_setfield fun:ngx_http_lua_cache_store_code } { Memcheck:Addr4 fun:lj_str_new fun:lua_getfield fun:ngx_http_lua_cache_load_code } { Memcheck:Param epoll_ctl(event) fun:epoll_ctl } { Memcheck:Leak fun:malloc fun:ngx_alloc fun:ngx_event_process_init } { 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 } debian/modules/ngx_http_substitutions_filter_module/0000775000000000000000000000000012705233614020427 5ustar debian/modules/ngx_http_substitutions_filter_module/README0000664000000000000000000001005112705233614021304 0ustar nginx_substitutions_filter *Note: this module is not distributed with the Nginx source. Installation instructions can be found below.* Description nginx_substitutions_filter is a filter module which can do both regular expression and fixed string substitutions on response bodies. This module is quite different from the Nginx's native Substitution Module. It scans the output chains buffer and matches string line by line, just like Apache's mod_substitute (). Example location / { subs_filter_types text/html text/css text/xml; subs_filter st(\d*).example.com $1.example.com ir; subs_filter a.example.com s.example.com; } Directives * subs_filter_types * subs_filter subs_filter_types syntax: *subs_filter_types mime-type [mime-types] * default: *subs_filter_types text/html* context: *http, server, location* *subs_filter_types* is used to specify which content types should be checked for *subs_filter*. The default is only *text/html*. This module just works with plain text. If the response is compressed, it can't uncompress the response and will ignore this response. This module can be compatible with gzip filter module. But it will not work with proxy compressed response. You can disable the compressed response like this: proxy_set_header Accept-Encoding ""; subs_filter syntax: *subs_filter source_str destination_str [gior] * default: *none* context: *http, server, location* *subs_filter* allows replacing source string(regular expression or fixed) in the nginx response with destination string. Substitution text may contain variables. More than one substitution rules per location is supported. The meaning of the third flags are: * *g*(default): Replace all the match strings. * *i*: Perform a case-insensitive match. * *o*: Just replace the first one. * *r*: The pattern is treated as a regular expression, default is fixed string. subs_filter_bypass syntax: *subs_filter_bypass $variable1 ...* default: *none* context: *http, server, location* You can sepcify several variables with this directive. If at least one of the variable is not empty and is not equal to '0', this substitution filter will be disabled. Installation To install, get the source with subversion: git clone git://github.com/yaoweibin/ngx_http_substitutions_filter_module.git and then compile nginx with the following option: ./configure --add-module=/path/to/module Known issue * Can't substitute the response header. CHANGES Changes with nginx_substitutions_filter 0.6.4 2014-02-15 * Now non-200 response will work * added the subs_filter_bypass directive Changes with nginx_substitutions_filter 0.6.2 2012-08-26 * fixed a bug of buffer overlap * fixed a bug with last zero buffer Changes with nginx_substitutions_filter 0.6.0 2012-06-30 * refactor this module Changes with nginx_substitutions_filter 0.5.2 2010-08-11 * do many optimizing for this module * fix a bug of buffer overlap * fix a segment fault bug when output chain return NGX_AGAIN. * fix a bug about last buffer with no linefeed. This may cause segment fault. Thanks for Josef Fröhle Changes with nginx_substitutions_filter 0.5 2010-04-15 * refactor the source structure, create branches of dev * fix a bug of small chunk of buffers causing lose content * fix the bug of last_buf and the nginx's compatibility above 0.8.25 * fix a bug with unwanted capture config error in fix string substitution * add feature of regex captures Changes with nginx_substitutions_filter 0.4 2009-12-23 * fix many bugs Changes with nginx_substitutions_filter 0.3 2009-02-04 * Initial public release Reporting a bug Questions/patches may be directed to Weibin Yao, yaoweibin@gmail.com. debian/modules/ngx_http_substitutions_filter_module/util/0000775000000000000000000000000012705233614021404 5ustar debian/modules/ngx_http_substitutions_filter_module/util/wiki2google_code_homepage.pl0000664000000000000000000000065112705233614027024 0ustar #!/usr/bin/env perl use strict; use warnings; use bytes; while (<>) { s{\s\[ ( [^\[\s]+ ) \]\s }{" `[`$1`]` "}gixe; s{ \[\[ ( [^\]\|]+ ) \| ([^\]]*) \]\] }{"[$1 $2]"}gixe; s{'''(.*?)'''}{"`$1`"}ge; s{''(.*?)''}{"_$1_"}ge; s{^\s*<[^/>]+>\s*$}{\{\{\{\n}; s{^\s*\s*$}{\}\}\}}; if (/^\s*$/) { print "\n"; next; } s{^\*}{ \*}; s{^\#}{ \#}; print $_; } debian/modules/ngx_http_substitutions_filter_module/util/wiki2pod.pl0000664000000000000000000000602612705233614023475 0ustar #!/usr/bin/env perl use strict; use warnings; use bytes; my @nl_counts; my $last_nl_count_level; my @bl_counts; my $last_bl_count_level; sub fmt_pos ($) { (my $s = $_[0]) =~ s{\#(.*)}{/"$1"}; $s; } sub fmt_mark ($$) { my ($tag, $s) = @_; my $max_level = 0; while ($s =~ /([<>])\1*/g) { my $level = length $&; if ($level > $max_level) { $max_level = $level; } } my $times = $max_level + 1; if ($times > 1) { $s = " $s "; } return $tag . ('<' x $times) . $s . ('>' x $times); } while (<>) { if ($. == 1) { # strip the leading U+FEFF byte in MS-DOS text files my $first = ord(substr($_, 0, 1)); #printf STDERR "0x%x", $first; #my $second = ord(substr($_, 2, 1)); #printf STDERR "0x%x", $second; if ($first == 0xEF) { substr($_, 0, 1, ''); #warn "Hit!"; } } s{\[(http[^ \]]+) ([^\]]*)\]}{$2 (L<$1>)}gi; s{ \[\[ ( [^\]\|]+ ) \| ([^\]]*) \]\] }{"L<$2|" . fmt_pos($1) . ">"}gixe; s{(.*?)}{fmt_mark('C', $1)}gie; s{'''(.*?)'''}{fmt_mark('B', $1)}ge; s{''(.*?)''}{fmt_mark('I', $1)}ge; if (s{^\s*<[^>]+>\s*$}{}) { next; } if (/^\s*$/) { print "\n"; next; } =begin cmt if ($. == 1) { warn $_; for my $i (0..length($_) - 1) { my $chr = substr($_, $i, 1); warn "chr ord($i): ".ord($chr)." \"$chr\"\n"; } } =end cmt =cut if (/(=+) (.*) \1$/) { #warn "HERE! $_" if $. == 1; my ($level, $title) = (length $1, $2); collapse_lists(); print "\n=head$level $title\n\n"; } elsif (/^(\#+) (.*)/) { my ($level, $txt) = (length($1) - 1, $2); if (defined $last_nl_count_level && $level != $last_nl_count_level) { print "\n=back\n\n"; } $last_nl_count_level = $level; $nl_counts[$level] ||= 0; if ($nl_counts[$level] == 0) { print "\n=over\n\n"; } $nl_counts[$level]++; print "\n=item $nl_counts[$level].\n\n"; print "$txt\n"; } elsif (/^(\*+) (.*)/) { my ($level, $txt) = (length($1) - 1, $2); if (defined $last_bl_count_level && $level != $last_bl_count_level) { print "\n=back\n\n"; } $last_bl_count_level = $level; $bl_counts[$level] ||= 0; if ($bl_counts[$level] == 0) { print "\n=over\n\n"; } $bl_counts[$level]++; print "\n=item *\n\n"; print "$txt\n"; } else { collapse_lists(); print; } } collapse_lists(); sub collapse_lists { while (defined $last_nl_count_level && $last_nl_count_level >= 0) { print "\n=back\n\n"; $last_nl_count_level--; } undef $last_nl_count_level; undef @nl_counts; while (defined $last_bl_count_level && $last_bl_count_level >= 0) { print "\n=back\n\n"; $last_bl_count_level--; } undef $last_bl_count_level; undef @bl_counts; } debian/modules/ngx_http_substitutions_filter_module/util/update-readme.sh0000775000000000000000000000043312705233614024460 0ustar #!/bin/sh perl util/wiki2pod.pl doc/README.wiki > /tmp/a.pod && pod2text /tmp/a.pod > README perl util/wiki2pod.pl doc/README.wiki > /tmp/a.pod && pod2html /tmp/a.pod > doc/README.html perl util/wiki2google_code_homepage.pl doc/README.wiki > doc/README.google_code_home_page.wiki debian/modules/ngx_http_substitutions_filter_module/test/0000775000000000000000000000000012705233614021406 5ustar debian/modules/ngx_http_substitutions_filter_module/test/lib/0000775000000000000000000000000012705233614022154 5ustar debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/0000775000000000000000000000000012705233614023073 5ustar debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/0000775000000000000000000000000012705233614024156 5ustar debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/LWP.pm0000664000000000000000000003366612705233614025174 0ustar package Test::Nginx::LWP; use lib 'lib'; use lib 'inc'; use Test::Base -Base; our $VERSION = '0.17'; our $NoLongString; use LWP::UserAgent; use Time::HiRes qw(sleep); use Test::LongString; use Test::Nginx::Util qw( setup_server_root write_config_file get_canon_version get_nginx_version trim show_all_chars parse_headers run_tests $ServerPortForClient $PidFile $ServRoot $ConfFile $ServerPort $RunTestHelper $NoNginxManager $RepeatEach worker_connections master_process_enabled config_preamble repeat_each no_shuffle no_root_location ); our $UserAgent = LWP::UserAgent->new; $UserAgent->agent(__PACKAGE__); #$UserAgent->default_headers(HTTP::Headers->new); #use Smart::Comments::JSON '##'; our @EXPORT = qw( plan run_tests run_test repeat_each config_preamble worker_connections master_process_enabled no_long_string no_shuffle no_root_location); sub no_long_string () { $NoLongString = 1; } sub run_test_helper ($$); $RunTestHelper = \&run_test_helper; sub parse_request ($$) { my ($name, $rrequest) = @_; open my $in, '<', $rrequest; my $first = <$in>; if (!$first) { Test::More::BAIL_OUT("$name - Request line should be non-empty"); die; } $first =~ s/^\s+|\s+$//g; my ($meth, $rel_url) = split /\s+/, $first, 2; my $url = "http://localhost:$ServerPortForClient" . $rel_url; my $content = do { local $/; <$in> }; if ($content) { $content =~ s/^\s+|\s+$//s; } close $in; return { method => $meth, url => $url, content => $content, }; } sub chunk_it ($$$) { my ($chunks, $start_delay, $middle_delay) = @_; my $i = 0; return sub { if ($i == 0) { if ($start_delay) { sleep($start_delay); } } elsif ($middle_delay) { sleep($middle_delay); } return $chunks->[$i++]; } } sub run_test_helper ($$) { my ($block, $dry_run) = @_; my $request = $block->request; my $name = $block->name; #if (defined $TODO) { #$name .= "# $TODO"; #} my $req_spec = parse_request($name, \$request); ## $req_spec my $method = $req_spec->{method}; my $req = HTTP::Request->new($method); my $content = $req_spec->{content}; if (defined ($block->request_headers)) { my $headers = parse_headers($block->request_headers); while (my ($key, $val) = each %$headers) { $req->header($key => $val); } } #$req->header('Accept', '*/*'); $req->url($req_spec->{url}); if ($content) { if ($method eq 'GET' or $method eq 'HEAD') { croak "HTTP 1.0/1.1 $method request should not have content: $content"; } $req->content($content); } elsif ($method eq 'POST' or $method eq 'PUT') { my $chunks = $block->chunked_body; if (defined $chunks) { if (!ref $chunks or ref $chunks ne 'ARRAY') { Test::More::BAIL_OUT("$name - --- chunked_body should takes a Perl array ref as its value"); } my $start_delay = $block->start_chunk_delay || 0; my $middle_delay = $block->middle_chunk_delay || 0; $req->content(chunk_it($chunks, $start_delay, $middle_delay)); if (!defined $req->header('Content-Type')) { $req->header('Content-Type' => 'text/plain'); } } else { if (!defined $req->header('Content-Type')) { $req->header('Content-Type' => 'text/plain'); } $req->header('Content-Length' => 0); } } if ($block->more_headers) { my @headers = split /\n+/, $block->more_headers; for my $header (@headers) { next if $header =~ /^\s*\#/; my ($key, $val) = split /:\s*/, $header, 2; #warn "[$key, $val]\n"; $req->header($key => $val); } } #warn "req: ", $req->as_string, "\n"; #warn "DONE!!!!!!!!!!!!!!!!!!!!"; my $res = HTTP::Response->new; unless ($dry_run) { $res = $UserAgent->request($req); } #warn "res returned!!!"; if ($dry_run) { SKIP: { Test::More::skip("$name - tests skipped due to the lack of directive $dry_run", 1); } } else { if (defined $block->error_code) { is($res->code, $block->error_code, "$name - status code ok"); } else { is($res->code, 200, "$name - status code ok"); } } if (defined $block->response_headers) { my $headers = parse_headers($block->response_headers); while (my ($key, $val) = each %$headers) { my $expected_val = $res->header($key); if (!defined $expected_val) { $expected_val = ''; } if ($dry_run) { SKIP: { Test::More::skip("$name - tests skipped due to the lack of directive $dry_run", 1); } } else { is $expected_val, $val, "$name - header $key ok"; } } } elsif (defined $block->response_headers_like) { my $headers = parse_headers($block->response_headers_like); while (my ($key, $val) = each %$headers) { my $expected_val = $res->header($key); if (!defined $expected_val) { $expected_val = ''; } if ($dry_run) { SKIP: { Test::More::skip("$name - tests skipped due to the lack of directive $dry_run", 1); } } else { like $expected_val, qr/^$val$/, "$name - header $key like ok"; } } } if (defined $block->response_body) { my $content = $res->content; if (defined $content) { $content =~ s/^TE: deflate,gzip;q=0\.3\r\n//gms; } $content =~ s/^Connection: TE, close\r\n//gms; my $expected = $block->response_body; $expected =~ s/\$ServerPort\b/$ServerPort/g; $expected =~ s/\$ServerPortForClient\b/$ServerPortForClient/g; #warn show_all_chars($content); if ($dry_run) { SKIP: { Test::More::skip("$name - tests skipped due to the lack of directive $dry_run", 1); } } else { if ($NoLongString) { is($content, $expected, "$name - response_body - response is expected"); } else { is_string($content, $expected, "$name - response_body - response is expected"); } #is($content, $expected, "$name - response_body - response is expected"); } } elsif (defined $block->response_body_like) { my $content = $res->content; if (defined $content) { $content =~ s/^TE: deflate,gzip;q=0\.3\r\n//gms; } $content =~ s/^Connection: TE, close\r\n//gms; my $expected_pat = $block->response_body_like; $expected_pat =~ s/\$ServerPort\b/$ServerPort/g; $expected_pat =~ s/\$ServerPortForClient\b/$ServerPortForClient/g; my $summary = trim($content); if ($dry_run) { SKIP: { Test::More::skip("$name - tests skipped due to the lack of directive $dry_run", 1); } } else { like($content, qr/$expected_pat/s, "$name - response_body_like - response is expected ($summary)"); } } elsif (defined $block->response_body_unlike) { my $content = $res->content; if (defined $content) { $content =~ s/^TE: deflate,gzip;q=0\.3\r\n//gms; } $content =~ s/^Connection: TE, close\r\n//gms; my $expected_pat = $block->response_body_unlike; $expected_pat =~ s/\$ServerPort\b/$ServerPort/g; $expected_pat =~ s/\$ServerPortForClient\b/$ServerPortForClient/g; my $summary = trim($content); if ($dry_run) { SKIP: { Test::More::skip("$name - tests skipped due to the lack of directive $dry_run", 1); } } else { unlike($content, qr/$expected_pat/s, "$name - response_body_like - response is expected ($summary)"); } } } 1; __END__ =encoding utf-8 =head1 NAME Test::Nginx::LWP - LWP-backed test scaffold for the Nginx C modules =head1 SYNOPSIS use Test::Nginx::LWP; plan tests => $Test::Nginx::LWP::RepeatEach * 2 * blocks(); run_tests(); __DATA__ === TEST 1: sanity --- config location /echo { echo_before_body hello; echo world; } --- request GET /echo --- response_body hello world --- error_code: 200 === TEST 2: set Server --- config location /foo { echo hi; more_set_headers 'Server: Foo'; } --- request GET /foo --- response_headers Server: Foo --- response_body hi === TEST 3: clear Server --- config location /foo { echo hi; more_clear_headers 'Server: '; } --- request GET /foo --- response_headers_like Server: nginx.* --- response_body hi === TEST 4: set request header at client side and rewrite it --- config location /foo { more_set_input_headers 'X-Foo: howdy'; echo $http_x_foo; } --- request GET /foo --- request_headers X-Foo: blah --- response_headers X-Foo: --- response_body howdy === TEST 3: rewrite content length --- config location /bar { more_set_input_headers 'Content-Length: 2048'; echo_read_request_body; echo_request_body; } --- request eval "POST /bar\n" . "a" x 4096 --- response_body eval "a" x 2048 === TEST 4: timer without explicit reset --- config location /timer { echo_sleep 0.03; echo "elapsed $echo_timer_elapsed sec."; } --- request GET /timer --- response_body_like ^elapsed 0\.0(2[6-9]|3[0-6]) sec\.$ === TEST 5: small buf (using 2-byte buf) --- config chunkin on; location /main { client_body_buffer_size 2; echo "body:"; echo $echo_request_body; echo_request_body; } --- request POST /main --- start_chunk_delay: 0.01 --- middle_chunk_delay: 0.01 --- chunked_body eval ["hello", "world"] --- error_code: 200 --- response_body eval "body: helloworld" =head1 DESCRIPTION This module provides a test scaffold based on L for automated testing in Nginx C module development. This class inherits from L, thus bringing all its declarative power to the Nginx C module testing practices. You need to terminate or kill any Nginx processes before running the test suite if you have changed the Nginx server binary. Normally it's as simple as killall nginx PATH=/path/to/your/nginx-with-memc-module:$PATH prove -r t This module will create a temporary server root under t/servroot/ of the current working directory and starts and uses the nginx executable in the PATH environment. You will often want to look into F when things go wrong ;) =head1 Sections supported The following sections are supported: =over =item config =item http_config =item request =item request_headers =item more_headers =item response_body =item response_body_like =item response_headers =item response_headers_like =item error_code =item chunked_body =item middle_chunk_delay =item start_chunk_delay =back =head1 Samples You'll find live samples in the following Nginx 3rd-party modules: =over =item ngx_echo L =item ngx_headers_more L =item ngx_chunkin L =item ngx_memc L =back =head1 SOURCE REPOSITORY This module has a Git repository on Github, which has access for all. http://github.com/agentzh/test-nginx If you want a commit bit, feel free to drop me a line. =head1 AUTHOR agentzh (章亦春) C<< >> =head1 COPYRIGHT & LICENSE Copyright (c) 2009-2011, Taobao Inc., Alibaba Group (L). Copyright (c) 2009-2011, agentzh C<< >>. 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: =over =item * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. =item * 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. =item * Neither the name of the Taobao Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. =back 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. =head1 SEE ALSO L, L. debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/Util.pm0000664000000000000000000005645412705233614025447 0ustar package Test::Nginx::Util; use strict; use warnings; our $VERSION = '0.17'; use base 'Exporter'; use POSIX qw( SIGQUIT SIGKILL SIGTERM ); use File::Spec (); use HTTP::Response; use Cwd qw( cwd ); use List::Util qw( shuffle ); use Time::HiRes qw( sleep ); use ExtUtils::MakeMaker (); our $LatestNginxVersion = 0.008039; our $NoNginxManager = $ENV{TEST_NGINX_NO_NGINX_MANAGER} || 0; our $Profiling = 0; our $RepeatEach = 1; our $MAX_PROCESSES = 10; our $NoShuffle = $ENV{TEST_NGINX_NO_SHUFFLE} || 0; our $UseValgrind = $ENV{TEST_NGINX_USE_VALGRIND}; our $EventType = $ENV{TEST_NGINX_EVENT_TYPE}; sub no_shuffle () { $NoShuffle = 1; } sub no_nginx_manager () { $NoNginxManager = 1; } our $ForkManager; if ($Profiling || $UseValgrind) { eval "use Parallel::ForkManager"; if ($@) { die "Failed to load Parallel::ForkManager: $@\n"; } $ForkManager = new Parallel::ForkManager($MAX_PROCESSES); } our $NginxBinary = $ENV{TEST_NGINX_BINARY} || 'nginx'; our $Workers = 1; our $WorkerConnections = 64; our $LogLevel = $ENV{TEST_NGINX_LOG_LEVEL} || 'debug'; our $MasterProcessEnabled = $ENV{TEST_NGINX_MASTER_PROCESS} || 'off'; our $DaemonEnabled = 'on'; our $ServerPort = $ENV{TEST_NGINX_SERVER_PORT} || $ENV{TEST_NGINX_PORT} || 1984; our $ServerPortForClient = $ENV{TEST_NGINX_CLIENT_PORT} || $ENV{TEST_NGINX_PORT} || 1984; our $NoRootLocation = 0; our $TestNginxSleep = $ENV{TEST_NGINX_SLEEP} || 0; our $BuildSlaveName = $ENV{TEST_NGINX_BUILDSLAVE}; our $ForceRestartOnTest = (defined $ENV{TEST_NGINX_FORCE_RESTART_ON_TEST}) ? $ENV{TEST_NGINX_FORCE_RESTART_ON_TEST} : 1; sub server_port (@) { if (@_) { $ServerPort = shift; } else { $ServerPort; } } sub repeat_each (@) { if (@_) { $RepeatEach = shift; } else { return $RepeatEach; } } sub worker_connections (@) { if (@_) { $WorkerConnections = shift; } else { return $WorkerConnections; } } sub no_root_location () { $NoRootLocation = 1; } sub workers (@) { if (@_) { #warn "setting workers to $_[0]"; $Workers = shift; } else { return $Workers; } } sub log_level (@) { if (@_) { $LogLevel = shift; } else { return $LogLevel; } } sub master_on () { $MasterProcessEnabled = 'on'; } sub master_process_enabled (@) { if (@_) { $MasterProcessEnabled = shift() ? 'on' : 'off'; } else { return $MasterProcessEnabled; } } our @EXPORT_OK = qw( setup_server_root write_config_file get_canon_version get_nginx_version trim show_all_chars parse_headers run_tests $ServerPortForClient $ServerPort $NginxVersion $PidFile $ServRoot $ConfFile $RunTestHelper $NoNginxManager $RepeatEach worker_connections workers master_on config_preamble repeat_each master_process_enabled log_level no_shuffle no_root_location html_dir server_root server_port no_nginx_manager ); if ($Profiling || $UseValgrind) { $DaemonEnabled = 'off'; $MasterProcessEnabled = 'off'; } our $ConfigPreamble = ''; sub config_preamble ($) { $ConfigPreamble = shift; } our $RunTestHelper; our $NginxVersion; our $NginxRawVersion; our $TODO; #our ($PrevRequest) our $PrevConfig; our $ServRoot = $ENV{TEST_NGINX_SERVROOT} || File::Spec->catfile(cwd() || '.', 't/servroot'); our $LogDir = File::Spec->catfile($ServRoot, 'logs'); our $ErrLogFile = File::Spec->catfile($LogDir, 'error.log'); our $AccLogFile = File::Spec->catfile($LogDir, 'access.log'); our $HtmlDir = File::Spec->catfile($ServRoot, 'html'); our $ConfDir = File::Spec->catfile($ServRoot, 'conf'); our $ConfFile = File::Spec->catfile($ConfDir, 'nginx.conf'); our $PidFile = File::Spec->catfile($LogDir, 'nginx.pid'); sub html_dir () { return $HtmlDir; } sub server_root () { return $ServRoot; } sub bail_out ($) { Test::More::BAIL_OUT(@_); } sub run_tests () { $NginxVersion = get_nginx_version(); if (defined $NginxVersion) { #warn "[INFO] Using nginx version $NginxVersion ($NginxRawVersion)\n"; } for my $block ($NoShuffle ? Test::Base::blocks() : shuffle Test::Base::blocks()) { #for (1..3) { run_test($block); #} } if ($Profiling || $UseValgrind) { $ForkManager->wait_all_children; } } sub setup_server_root () { if (-d $ServRoot) { # Take special care, so we won't accidentally remove # real user data when TEST_NGINX_SERVROOT is mis-used. system("rm -rf $ConfDir > /dev/null") == 0 or die "Can't remove $ConfDir"; system("rm -rf $HtmlDir > /dev/null") == 0 or die "Can't remove $HtmlDir"; system("rm -rf $LogDir > /dev/null") == 0 or die "Can't remove $LogDir"; system("rm -rf $ServRoot/*_temp > /dev/null") == 0 or die "Can't remove $ServRoot/*_temp"; system("rmdir $ServRoot > /dev/null") == 0 or die "Can't remove $ServRoot (not empty?)"; } mkdir $ServRoot or die "Failed to do mkdir $ServRoot\n"; mkdir $LogDir or die "Failed to do mkdir $LogDir\n"; mkdir $HtmlDir or die "Failed to do mkdir $HtmlDir\n"; my $index_file = "$HtmlDir/index.html"; open my $out, ">$index_file" or die "Can't open $index_file for writing: $!\n"; print $out 'It works!It works!'; close $out; mkdir $ConfDir or die "Failed to do mkdir $ConfDir\n"; } sub write_user_files ($) { my $block = shift; my $name = $block->name; if ($block->user_files) { my $raw = $block->user_files; open my $in, '<', \$raw; my @files; my ($fname, $body, $date); while (<$in>) { if (/>>> (\S+)(?:\s+(.+))?/) { if ($fname) { push @files, [$fname, $body, $date]; } $fname = $1; $date = $2; undef $body; } else { $body .= $_; } } if ($fname) { push @files, [$fname, $body, $date]; } for my $file (@files) { my ($fname, $body, $date) = @$file; #warn "write file $fname with content [$body]\n"; if (!defined $body) { $body = ''; } if ($fname =~ /(.*)\//) { my $dir = "$HtmlDir/$1"; if (! -d $dir) { mkdir $dir or die "$name - Cannot create directory ", $dir; } } open my $out, ">$HtmlDir/$fname" or die "$name - Cannot open $HtmlDir/$fname for writing: $!\n"; print $out $body; close $out; if ($date) { my $cmd = "touch -t '$date' $HtmlDir/$fname"; system($cmd) == 0 or die "Failed to run shell command: $cmd\n"; } } } } sub write_config_file ($$$) { my ($config, $http_config, $main_config) = @_; $http_config = expand_env_in_config($http_config); if (!defined $config) { $config = ''; } if (!defined $http_config) { $http_config = ''; } if (!defined $main_config) { $main_config = ''; } open my $out, ">$ConfFile" or die "Can't open $ConfFile for writing: $!\n"; print $out <<_EOC_; worker_processes $Workers; daemon $DaemonEnabled; master_process $MasterProcessEnabled; error_log $ErrLogFile $LogLevel; pid $PidFile; $main_config http { access_log $AccLogFile; default_type text/plain; keepalive_timeout 68; $http_config server { listen $ServerPort; server_name 'localhost'; client_max_body_size 30M; #client_body_buffer_size 4k; # Begin preamble config... $ConfigPreamble # End preamble config... # Begin test case config... $config # End test case config. _EOC_ if (! $NoRootLocation) { print $out <<_EOC_; location / { root $HtmlDir; index index.html index.htm; } _EOC_ } print $out <<_EOC_; } } events { worker_connections $WorkerConnections; _EOC_ if ($EventType) { print $out <<_EOC_; use $EventType; _EOC_ } print $out "}\n"; close $out; } sub get_canon_version (@) { sprintf "%d.%03d%03d", $_[0], $_[1], $_[2]; } sub get_nginx_version () { my $out = `$NginxBinary -V 2>&1`; if (!defined $out || $? != 0) { warn "Failed to get the version of the Nginx in PATH.\n"; } if ($out =~ m{(?:nginx|ngx_openresty)/(\d+)\.(\d+)\.(\d+)}s) { $NginxRawVersion = "$1.$2.$3"; return get_canon_version($1, $2, $3); } warn "Failed to parse the output of \"nginx -V\": $out\n"; return undef; } sub get_pid_from_pidfile ($) { my ($name) = @_; open my $in, $PidFile or bail_out("$name - Failed to open the pid file $PidFile for reading: $!"); my $pid = do { local $/; <$in> }; chomp $pid; #warn "Pid: $pid\n"; close $in; return $pid; } sub trim ($) { (my $s = shift) =~ s/^\s+|\s+$//g; $s =~ s/\n/ /gs; $s =~ s/\s{2,}/ /gs; $s; } sub show_all_chars ($) { my $s = shift; $s =~ s/\n/\\n/gs; $s =~ s/\r/\\r/gs; $s =~ s/\t/\\t/gs; $s; } sub parse_headers ($) { my $s = shift; my %headers; open my $in, '<', \$s; while (<$in>) { s/^\s+|\s+$//g; my $neg = ($_ =~ s/^!\s*//); #warn "neg: $neg ($_)"; if ($neg) { $headers{$_} = undef; } else { my ($key, $val) = split /\s*:\s*/, $_, 2; $headers{$key} = $val; } } close $in; return \%headers; } sub expand_env_in_config ($) { my $config = shift; if (!defined $config) { return; } $config =~ s/\$(TEST_NGINX_[_A-Z0-9]+)/ if (!defined $ENV{$1}) { bail_out "No environment $1 defined.\n"; } $ENV{$1}/eg; $config; } sub check_if_missing_directives () { open my $in, $ErrLogFile or bail_out "check_if_missing_directives: Cannot open $ErrLogFile for reading: $!\n"; while (<$in>) { #warn $_; if (/\[emerg\] \S+?: unknown directive "([^"]+)"/) { #warn "MATCHED!!! $1"; return $1; } } close $in; #warn "NOT MATCHED!!!"; return 0; } sub run_test ($) { my $block = shift; my $name = $block->name; my $config = $block->config; $config = expand_env_in_config($config); my $dry_run = 0; my $should_restart = 1; my $should_reconfig = 1; if (!defined $config) { if (!$NoNginxManager) { # Manager without config. if (!defined $PrevConfig) { bail_out("$name - No '--- config' section specified and could not get previous one. Use TEST_NGINX_NO_NGINX_MANAGER ?"); die; } $should_reconfig = 0; # There is nothing to reconfig to. $should_restart = $ForceRestartOnTest; } # else: not manager without a config. This is not a problem at all. # setting these values to something meaningful but should not be used $should_restart = 0; $should_reconfig = 0; } elsif ($NoNginxManager) { # One config but not manager: it's worth a warning. Test::Base::diag("NO_NGINX_MANAGER activated: config for $name ignored"); # Like above: setting them to something meaningful just in case. $should_restart = 0; $should_reconfig = 0; } else { # One config and manager. Restart only if forced to or if config # changed. if ((!defined $PrevConfig) || ($config ne $PrevConfig)) { $should_reconfig = 1; } else { $should_reconfig = 0; } if ($should_reconfig || $ForceRestartOnTest) { $should_restart = 1; } else { $should_restart = 0; } } my $skip_nginx = $block->skip_nginx; my $skip_nginx2 = $block->skip_nginx2; my $skip_slave = $block->skip_slave; my ($tests_to_skip, $should_skip, $skip_reason); if (defined $skip_nginx) { if ($skip_nginx =~ m{ ^ \s* (\d+) \s* : \s* ([<>]=?) \s* (\d+)\.(\d+)\.(\d+) (?: \s* : \s* (.*) )? \s*$}x) { $tests_to_skip = $1; my ($op, $ver1, $ver2, $ver3) = ($2, $3, $4, $5); $skip_reason = $6; #warn "$ver1 $ver2 $ver3"; my $ver = get_canon_version($ver1, $ver2, $ver3); if ((!defined $NginxVersion and $op =~ /^]=?) \s* (\d+)\.(\d+)\.(\d+) \s* (or|and) \s* ([<>]=?) \s* (\d+)\.(\d+)\.(\d+) (?: \s* : \s* (.*) )? \s*$}x) { $tests_to_skip = $1; my ($opa, $ver1a, $ver2a, $ver3a) = ($2, $3, $4, $5); my $opx = $6; my ($opb, $ver1b, $ver2b, $ver3b) = ($7, $8, $9, $10); $skip_reason = $11; my $vera = get_canon_version($ver1a, $ver2a, $ver3a); my $verb = get_canon_version($ver1b, $ver2b, $ver3b); if ((!defined $NginxVersion) or (($opx eq "or") and (eval "$NginxVersion $opa $vera" or eval "$NginxVersion $opb $verb")) or (($opx eq "and") and (eval "$NginxVersion $opa $vera" and eval "$NginxVersion $opb $verb"))) { $should_skip = 1; } } else { bail_out("$name - Invalid --- skip_nginx2 spec: " . $skip_nginx2); die; } } elsif (defined $skip_slave and defined $BuildSlaveName) { if ($skip_slave =~ m{ ^ \s* (\d+) \s* : \s* (\w+) \s* (?: (\w+) \s* )? (?: (\w+) \s* )? (?: \s* : \s* (.*) )? \s*$}x) { $tests_to_skip = $1; my ($slave1, $slave2, $slave3) = ($2, $3, $4); $skip_reason = $5; if ((defined $slave1 and $slave1 eq "all") or (defined $slave1 and $slave1 eq $BuildSlaveName) or (defined $slave2 and $slave2 eq $BuildSlaveName) or (defined $slave3 and $slave3 eq $BuildSlaveName) ) { $should_skip = 1; } } else { bail_out("$name - Invalid --- skip_slave spec: " . $skip_slave); die; } } if (!defined $skip_reason) { $skip_reason = "various reasons"; } my $todo_nginx = $block->todo_nginx; my ($should_todo, $todo_reason); if (defined $todo_nginx) { if ($todo_nginx =~ m{ ^ \s* ([<>]=?) \s* (\d+)\.(\d+)\.(\d+) (?: \s* : \s* (.*) )? \s*$}x) { my ($op, $ver1, $ver2, $ver3) = ($1, $2, $3, $4); $todo_reason = $5; my $ver = get_canon_version($ver1, $ver2, $ver3); if ((!defined $NginxVersion and $op =~ /^ /dev/null") == 0) { #warn "found running nginx..."; write_config_file($config, $block->http_config, $block->main_config); if (kill(SIGQUIT, $pid) == 0) { # send quit signal #warn("$name - Failed to send quit signal to the nginx process with PID $pid"); } sleep 0.02; if (system("ps $pid > /dev/null") == 0) { #warn "killing with force...\n"; kill(SIGKILL, $pid); sleep 0.02; } undef $nginx_is_running; } else { unlink $PidFile or die "Failed to remove pid file $PidFile\n"; undef $nginx_is_running; } } else { undef $nginx_is_running; } start_nginx: unless ($nginx_is_running) { #system("killall -9 nginx"); #warn "*** Restarting the nginx server...\n"; setup_server_root(); write_user_files($block); write_config_file($config, $block->http_config, $block->main_config); #warn "nginx binary: $NginxBinary"; if ( ! can_run($NginxBinary) ) { bail_out("$name - Cannot find the nginx executable in the PATH environment"); die; } #if (system("nginx -p $ServRoot -c $ConfFile -t") != 0) { #Test::More::BAIL_OUT("$name - Invalid config file"); #} #my $cmd = "nginx -p $ServRoot -c $ConfFile > /dev/null"; if (!defined $NginxVersion) { $NginxVersion = $LatestNginxVersion; } my $cmd; if ($NginxVersion >= 0.007053) { $cmd = "$NginxBinary -p $ServRoot/ -c $ConfFile > /dev/null"; } else { $cmd = "$NginxBinary -c $ConfFile > /dev/null"; } if ($UseValgrind) { if (-f 'valgrind.suppress') { $cmd = "valgrind -q --leak-check=full --gen-suppressions=all --suppressions=valgrind.suppress $cmd"; } else { $cmd = "valgrind -q --leak-check=full --gen-suppressions=all $cmd"; } warn "$name\n"; #warn "$cmd\n"; } if ($Profiling || $UseValgrind) { my $pid = $ForkManager->start; if (!$pid) { # child process exec $cmd; =begin cmt if (system($cmd) != 0) { Test::More::BAIL_OUT("$name - Cannot start nginx using command \"$cmd\"."); } $ForkManager->finish; # terminate the child process =end cmt =cut } #warn "sleeping"; if ($TestNginxSleep) { sleep $TestNginxSleep; } else { sleep 1; } } else { if (system($cmd) != 0) { if ($ENV{TEST_NGINX_IGNORE_MISSING_DIRECTIVES} and my $directive = check_if_missing_directives()) { $dry_run = $directive; } else { bail_out("$name - Cannot start nginx using command \"$cmd\"."); } } } sleep 0.1; } } if ($block->init) { eval $block->init; if ($@) { bail_out("$name - init failed: $@"); } } my $i = 0; while ($i++ < $RepeatEach) { if ($should_skip) { SKIP: { Test::More::skip("$name - $skip_reason", $tests_to_skip); $RunTestHelper->($block, $dry_run); } } elsif ($should_todo) { TODO: { local $TODO = "$name - $todo_reason"; $RunTestHelper->($block, $dry_run); } } else { $RunTestHelper->($block, $dry_run); } } if (my $total_errlog = $ENV{TEST_NGINX_ERROR_LOG}) { my $errlog = "$LogDir/error.log"; if (-s $errlog) { open my $out, ">>$total_errlog" or die "Failed to append test case title to $total_errlog: $!\n"; print $out "\n=== $0 $name\n"; close $out; system("cat $errlog >> $total_errlog") == 0 or die "Failed to append $errlog to $total_errlog. Abort.\n"; } } if ($Profiling || $UseValgrind) { #warn "Found quit..."; if (-f $PidFile) { #warn "found pid file..."; my $pid = get_pid_from_pidfile($name); if (system("ps $pid > /dev/null") == 0) { write_config_file($config, $block->http_config, $block->main_config); if (kill(SIGQUIT, $pid) == 0) { # send quit signal warn("$name - Failed to send quit signal to the nginx process with PID $pid"); } if ($TestNginxSleep) { sleep $TestNginxSleep; } else { sleep 0.1; } if (-f $PidFile) { #warn "killing with force (valgrind or profile)...\n"; kill(SIGKILL, $pid); sleep 0.02; } else { #warn "nginx killed"; } } else { unlink $PidFile or die "Failed to remove pid file $PidFile\n"; } } else { #warn "pid file not found"; } } } END { if ($UseValgrind || !$ENV{TEST_NGINX_NO_CLEAN}) { local $?; # to avoid confusing Test::Builder::_ending if (-f $PidFile) { my $pid = get_pid_from_pidfile(''); if (!$pid) { die "No pid found."; } if (system("ps $pid > /dev/null") == 0) { if (kill(SIGQUIT, $pid) == 0) { # send quit signal #warn("Failed to send quit signal to the nginx process with PID $pid"); } if ($TestNginxSleep) { sleep $TestNginxSleep; } else { sleep 0.02; } if (system("ps $pid > /dev/null") == 0) { #warn "killing with force...\n"; kill(SIGKILL, $pid); sleep 0.02; } } else { unlink $PidFile; } } } } # check if we can run some command sub can_run { my ($cmd) = @_; #warn "can run: @_\n"; my $_cmd = $cmd; return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { next if $dir eq ''; my $abs = File::Spec->catfile($dir, $_[0]); return $abs if (-x $abs or $abs = MM->maybe_command($abs)); } return; } 1; debian/modules/ngx_http_substitutions_filter_module/test/lib/Test/Nginx/Socket.pm0000664000000000000000000015416212705233614025755 0ustar package Test::Nginx::Socket; use lib 'lib'; use lib 'inc'; use Test::Base -Base; our $VERSION = '0.17'; use Encode; use Data::Dumper; use Time::HiRes qw(sleep time); use Test::LongString; use List::MoreUtils qw( any ); use IO::Select (); our $ServerAddr = 'localhost'; our $Timeout = $ENV{TEST_NGINX_TIMEOUT} || 2; use Test::Nginx::Util qw( setup_server_root write_config_file get_canon_version get_nginx_version trim show_all_chars parse_headers run_tests $ServerPortForClient $ServerPort $PidFile $ServRoot $ConfFile $RunTestHelper $RepeatEach worker_connections master_process_enabled config_preamble repeat_each workers master_on log_level no_shuffle no_root_location server_root html_dir server_port no_nginx_manager ); #use Smart::Comments::JSON '###'; use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); use POSIX qw(EAGAIN); use IO::Socket; #our ($PrevRequest, $PrevConfig); our $NoLongString = undef; our @EXPORT = qw( plan run_tests run_test repeat_each config_preamble worker_connections master_process_enabled no_long_string workers master_on log_level no_shuffle no_root_location server_addr server_root html_dir server_port timeout no_nginx_manager ); sub send_request ($$$$@); sub run_test_helper ($$); sub error_event_handler ($); sub read_event_handler ($); sub write_event_handler ($); sub no_long_string () { $NoLongString = 1; } sub server_addr (@) { if (@_) { #warn "setting server addr to $_[0]\n"; $ServerAddr = shift; } else { return $ServerAddr; } } sub timeout (@) { if (@_) { $Timeout = shift; } else { $Timeout; } } $RunTestHelper = \&run_test_helper; # This will parse a "request"" string. The expected format is: # - One line for the HTTP verb (POST, GET, etc.) plus optional relative URL # (default is /) plus optional HTTP version (default is HTTP/1.1). # - More lines considered as the body of the request. # Most people don't care about headers and this is enough. # # This function will return a reference to a hash with the parsed elements # plus information on the parsing itself like "how many white spaces were # skipped before the VERB" (skipped_before_method), "was the version provided" # (http_ver_size = 0). sub parse_request ($$) { my ( $name, $rrequest ) = @_; open my $in, '<', $rrequest; my $first = <$in>; if ( !$first ) { Test::More::BAIL_OUT("$name - Request line should be non-empty"); die; } #$first =~ s/^\s+|\s+$//gs; my ($before_meth, $meth, $after_meth); my ($rel_url, $rel_url_size, $after_rel_url); my ($http_ver, $http_ver_size, $after_http_ver); my $end_line_size; if ($first =~ /^(\s*)(\S+)( *)((\S+)( *))?((\S+)( *))?(\s*)/) { $before_meth = defined $1 ? length($1) : undef; $meth = $2; $after_meth = defined $3 ? length($3) : undef; $rel_url = $5; $rel_url_size = defined $5 ? length($5) : undef; $after_rel_url = defined $6 ? length($6) : undef; $http_ver = $8; if (!defined $8) { $http_ver_size = undef; } else { $http_ver_size = defined $8 ? length($8) : undef; } if (!defined $9) { $after_http_ver = undef; } else { $after_http_ver = defined $9 ? length($9) : undef; } $end_line_size = defined $10 ? length($10) : undef; } else { Test::More::BAIL_OUT("$name - Request line is not valid. Should be 'meth [url [version]]'"); die; } if ( !defined $rel_url ) { $rel_url = '/'; $rel_url_size = 0; $after_rel_url = 0; } if ( !defined $http_ver ) { $http_ver = 'HTTP/1.1'; $http_ver_size = 0; $after_http_ver = 0; } #my $url = "http://localhost:$ServerPortForClient" . $rel_url; my $content = do { local $/; <$in> }; my $content_size; if ( !defined $content ) { $content = ""; $content_size = 0; } else { $content_size = length($content); } #warn Dumper($content); close $in; return { method => $meth, url => $rel_url, content => $content, http_ver => $http_ver, skipped_before_method => $before_meth, method_size => length($meth), skipped_after_method => $after_meth, url_size => $rel_url_size, skipped_after_url => $after_rel_url, http_ver_size => $http_ver_size, skipped_after_http_ver => $after_http_ver + $end_line_size, content_size => $content_size, }; } # From a parsed request, builds the "moves" to apply to the original request # to transform it (e.g. add missing version). Elements of the returned array # are of 2 types: # - d : number of characters to remove. # - s_* : number of characters (s_s) to replace by value (s_v). sub get_moves($) { my ($parsed_req) = @_; return ({d => $parsed_req->{skipped_before_method}}, {s_s => $parsed_req->{method_size}, s_v => $parsed_req->{method}}, {d => $parsed_req->{skipped_after_method}}, {s_s => $parsed_req->{url_size}, s_v => $parsed_req->{url}}, {d => $parsed_req->{skipped_after_url}}, {s_s => $parsed_req->{http_ver_size}, s_v => $parsed_req->{http_ver}}, {d => $parsed_req->{skipped_after_http_ver}}, {s_s => 0, s_v => $parsed_req->{headers}}, {s_s => $parsed_req->{content_size}, s_v => $parsed_req->{content}} ); } # Apply moves (see above) to an array of packets that correspond to a request. # The use of this function is explained in the build_request_from_packets # function. sub apply_moves($$) { my ($r_packet, $r_move) = @_; my $current_packet = shift @$r_packet; my $current_move = shift @$r_move; my $in_packet_cursor = 0; my @result = (); while (defined $current_packet) { if (!defined $current_move) { push @result, $current_packet; $current_packet = shift @$r_packet; $in_packet_cursor = 0; } elsif (defined $current_move->{d}) { # Remove stuff from packet if ($current_move->{d} > length($current_packet) - $in_packet_cursor) { # Eat up what is left of packet. $current_move->{d} -= length($current_packet) - $in_packet_cursor; if ($in_packet_cursor > 0) { # Something in packet from previous iteration. push @result, $current_packet; } $current_packet = shift @$r_packet; $in_packet_cursor = 0; } else { # Remove from current point in current packet substr($current_packet, $in_packet_cursor, $current_move->{d}) = ''; $current_move = shift @$r_move; } } else { # Substitute stuff if ($current_move->{s_s} > length($current_packet) - $in_packet_cursor) { # {s_s=>3, s_v=>GET} on ['GE', 'T /foo'] $current_move->{s_s} -= length($current_packet) - $in_packet_cursor; substr($current_packet, $in_packet_cursor) = substr($current_move->{s_v}, 0, length($current_packet) - $in_packet_cursor); push @result, $current_packet; $current_move->{s_v} = substr($current_move->{s_v}, length($current_packet) - $in_packet_cursor); $current_packet = shift @$r_packet; $in_packet_cursor = 0; } else { substr($current_packet, $in_packet_cursor, $current_move->{s_s}) = $current_move->{s_v}; $in_packet_cursor += length($current_move->{s_v}); $current_move = shift @$r_move; } } } return \@result; } # Given a request as an array of packets, will parse it, append the appropriate # headers and return another array of packets. # The function implemented here can be high-level summarized as: # 1 - Concatenate all packets to obtain a string representation of request. # 2 - Parse the string representation # 3 - Get the "moves" from the parsing # 4 - Apply the "moves" to the packets. sub build_request_from_packets($$$$$) { my ( $name, $more_headers, $is_chunked, $conn_header, $request_packets ) = @_; # Concatenate packets as a string my $parsable_request = ''; my @packet_length; for my $one_packet (@$request_packets) { $parsable_request .= $one_packet; push @packet_length, length($one_packet); } # Parse the string representation. my $parsed_req = parse_request( $name, \$parsable_request ); # Append headers my $len_header = ''; if ( !$is_chunked && defined $parsed_req->{content} && $parsed_req->{content} ne '' && $more_headers !~ /\bContent-Length:/ ) { $parsed_req->{content} =~ s/^\s+|\s+$//gs; $len_header .= "Content-Length: " . length( $parsed_req->{content} ) . "\r\n"; } $parsed_req->{method} .= ' '; $parsed_req->{url} .= ' '; $parsed_req->{http_ver} .= "\r\n"; $parsed_req->{headers} = "Host: localhost\r\nConnection: $conn_header\r\n$more_headers$len_header\r\n"; # Get the moves from parsing my @elements_moves = get_moves($parsed_req); # Apply them to the packets. return apply_moves($request_packets, \@elements_moves); } # Returns an array of array of hashes from the block. Each element of # the first-level array is a request. # Each request is an array of the "packets" to be sent. Each packet is a # string to send, with an (optionnal) delay before sending it. # This function parses (and therefore defines the syntax) of "request*" # sections. See documentation for supported syntax. sub get_req_from_block ($) { my ($block) = @_; my $name = $block->name; my @req_list = (); if ( defined $block->raw_request ) { # Should be deprecated. if ( ref $block->raw_request && ref $block->raw_request eq 'ARRAY' ) { # User already provided an array. So, he/she specified where the # data should be split. This allows for backward compatibility but # should use request with arrays as it provides the same functionnality. my @rr_list = (); for my $elt ( @{ $block->raw_request } ) { push @rr_list, {value => $elt}; } push @req_list, \@rr_list; } else { push @req_list, [{value => $block->raw_request}]; } } else { my $request; if ( defined $block->request_eval ) { diag "$name - request_eval DEPRECATED. Use request eval instead."; $request = eval $block->request_eval; if ($@) { warn $@; } } else { $request = $block->request; } my $is_chunked = 0; my $more_headers = ''; if ( $block->more_headers ) { my @headers = split /\n+/, $block->more_headers; for my $header (@headers) { next if $header =~ /^\s*\#/; my ( $key, $val ) = split /:\s*/, $header, 2; if ( lc($key) eq 'transfer-encoding' and $val eq 'chunked' ) { $is_chunked = 1; } #warn "[$key, $val]\n"; $more_headers .= "$key: $val\r\n"; } } if ( $block->pipelined_requests ) { my $reqs = $block->pipelined_requests; if ( !ref $reqs || ref $reqs ne 'ARRAY' ) { Test::More::BAIL_OUT( "$name - invalid entries in --- pipelined_requests"); } my $i = 0; my $prq = ""; for my $request (@$reqs) { my $conn_type; if ( $i++ == @$reqs - 1 ) { $conn_type = 'close'; } else { $conn_type = 'keep-alive'; } my $r_br = build_request_from_packets($name, $more_headers, $is_chunked, $conn_type, [$request] ); $prq .= $$r_br[0]; } push @req_list, [{value =>$prq}]; } else { # request section. if (!ref $request) { # One request and it is a good old string. my $r_br = build_request_from_packets($name, $more_headers, $is_chunked, 'Close', [$request] ); push @req_list, [{value => $$r_br[0]}]; } elsif (ref $request eq 'ARRAY') { # A bunch of requests... for my $one_req (@$request) { if (!ref $one_req) { # This request is a good old string. my $r_br = build_request_from_packets($name, $more_headers, $is_chunked, 'Close', [$one_req] ); push @req_list, [{value => $$r_br[0]}]; } elsif (ref $one_req eq 'ARRAY') { # Request expressed as a serie of packets my @packet_array = (); for my $one_packet (@$one_req) { if (!ref $one_packet) { # Packet is a string. push @packet_array, $one_packet; } elsif (ref $one_packet eq 'HASH'){ # Packet is a hash with a value... push @packet_array, $one_packet->{value}; } else { Test::More::BAIL_OUT "$name - Invalid syntax. $one_packet should be a string or hash with value."; } } my $transformed_packet_array = build_request_from_packets($name, $more_headers, $is_chunked, 'Close', \@packet_array); my @transformed_req = (); my $idx = 0; for my $one_transformed_packet (@$transformed_packet_array) { if (!ref $$one_req[$idx]) { push @transformed_req, {value => $one_transformed_packet}; } else { # Is a HASH (checked above as $one_packet) $$one_req[$idx]->{value} = $one_transformed_packet; push @transformed_req, $$one_req[$idx]; } $idx++; } push @req_list, \@transformed_req; } else { Test::More::BAIL_OUT "$name - Invalid syntax. $one_req should be a string or an array of packets."; } } } else { Test::More::BAIL_OUT( "$name - invalid ---request : MUST be string or array of requests"); } } } return \@req_list; } sub run_test_helper ($$) { my ( $block, $dry_run ) = @_; my $name = $block->name; my $r_req_list = get_req_from_block($block); if ( $#$r_req_list < 0 ) { Test::More::BAIL_OUT("$name - request empty"); } #warn "request: $req\n"; my $timeout = $block->timeout; if ( !defined $timeout ) { $timeout = $Timeout; } my $req_idx = 0; for my $one_req (@$r_req_list) { my $raw_resp; if ($dry_run) { $raw_resp = "200 OK HTTP/1.0\r\nContent-Length: 0\r\n\r\n"; } else { $raw_resp = send_request( $one_req, $block->raw_request_middle_delay, $timeout, $block->name ); } #warn "raw resonse: [$raw_resp]\n"; my ($n, $need_array); if ($block->pipelined_requests) { $n = @{ $block->pipelined_requests }; $need_array = 1; } else { $need_array = $#$r_req_list > 0; } again: #warn "!!! resp: [$raw_resp]"; if (!defined $raw_resp) { $raw_resp = ''; } my ( $res, $raw_headers, $left ) = parse_response( $name, $raw_resp ); if (!$n) { if ($left) { my $name = $block->name; $left =~ s/([\0-\037\200-\377])/sprintf('\x{%02x}',ord $1)/eg; warn "WARNING: $name - unexpected extra bytes after last chunk in ", "response: \"$left\"\n"; } } else { $raw_resp = $left; $n--; } check_error_code($block, $res, $dry_run, $req_idx, $need_array); check_raw_response_headers($block, $raw_headers, $dry_run, $req_idx, $need_array); check_response_headers($block, $res, $raw_headers, $dry_run, $req_idx, $need_array); check_response_body($block, $res, $dry_run, $req_idx, $need_array); $req_idx++; if ($n) { goto again; } } } # Helper function to retrieve a "check" (e.g. error_code) section. This also # checks that tests with arrays of requests are arrays themselves. sub get_indexed_value($$$$) { my ($name, $value, $req_idx, $need_array) = @_; if ($need_array) { if (ref $value && ref $value eq 'ARRAY') { return $$value[$req_idx]; } else { Test::More::BAIL_OUT("$name - You asked for many requests, the expected results should be arrays as well."); } } else { # One element but still provided as an array. if (ref $value && ref $value eq 'ARRAY') { if ($req_idx != 0) { Test::More::BAIL_OUT("$name - SHOULD NOT HAPPEN: idx != 0 and don't need array."); } else { return $$value[0]; } } else { return $value; } } } sub check_error_code($$$$$) { my ($block, $res, $dry_run, $req_idx, $need_array) = @_; my $name = $block->name; SKIP: { skip "$name - tests skipped due to the lack of directive $dry_run", 1 if $dry_run; if ( defined $block->error_code ) { is( $res->code || '', get_indexed_value($name, $block->error_code, $req_idx, $need_array), "$name - status code ok" ); } else { is( $res->code || '', 200, "$name - status code ok" ); } } } sub check_raw_response_headers($$$$$) { my ($block, $raw_headers, $dry_run, $req_idx, $need_array) = @_; my $name = $block->name; if ( defined $block->raw_response_headers_like ) { SKIP: { skip "$name - tests skipped due to the lack of directive $dry_run", 1 if $dry_run; my $expected = get_indexed_value($name, $block->raw_response_headers_like, $req_idx, $need_array); like $raw_headers, qr/$expected/s, "$name - raw resp headers like"; } } } sub check_response_headers($$$$$) { my ($block, $res, $raw_headers, $dry_run, $req_idx, $need_array) = @_; my $name = $block->name; if ( defined $block->response_headers ) { my $headers = parse_headers( get_indexed_value($name, $block->response_headers, $req_idx, $need_array)); while ( my ( $key, $val ) = each %$headers ) { if ( !defined $val ) { #warn "HIT"; SKIP: { skip "$name - tests skipped due to the lack of directive $dry_run", 1 if $dry_run; unlike $raw_headers, qr/^\s*\Q$key\E\s*:/ms, "$name - header $key not present in the raw headers"; } next; } my $actual_val = $res->header($key); if ( !defined $actual_val ) { $actual_val = ''; } SKIP: { skip "$name - tests skipped due to the lack of directive $dry_run", 1 if $dry_run; is $actual_val, $val, "$name - header $key ok"; } } } elsif ( defined $block->response_headers_like ) { my $headers = parse_headers( get_indexed_value($name, $block->response_headers_like, $req_idx, $need_array) ); while ( my ( $key, $val ) = each %$headers ) { my $expected_val = $res->header($key); if ( !defined $expected_val ) { $expected_val = ''; } SKIP: { skip "$name - tests skipped due to the lack of directive $dry_run", 1 if $dry_run; like $expected_val, qr/^$val$/, "$name - header $key like ok"; } } } } sub check_response_body() { my ($block, $res, $dry_run, $req_idx, $need_array) = @_; my $name = $block->name; if ( defined $block->response_body || defined $block->response_body_eval ) { my $content = $res->content; if ( defined $content ) { $content =~ s/^TE: deflate,gzip;q=0\.3\r\n//gms; $content =~ s/^Connection: TE, close\r\n//gms; } my $expected; if ( $block->response_body_eval ) { diag "$name - response_body_eval is DEPRECATED. Use response_body eval instead."; $expected = eval get_indexed_value($name, $block->response_body_eval, $req_idx, $need_array); if ($@) { warn $@; } } else { $expected = get_indexed_value($name, $block->response_body, $req_idx, $need_array); } if ( $block->charset ) { Encode::from_to( $expected, 'UTF-8', $block->charset ); } unless (ref $expected) { $expected =~ s/\$ServerPort\b/$ServerPort/g; $expected =~ s/\$ServerPortForClient\b/$ServerPortForClient/g; } #warn show_all_chars($content); #warn "no long string: $NoLongString"; SKIP: { skip "$name - tests skipped due to the lack of directive $dry_run", 1 if $dry_run; if (ref $expected) { like $content, $expected, "$name - response_body - like"; } else { if ($NoLongString) { is( $content, $expected, "$name - response_body - response is expected" ); } else { is_string( $content, $expected, "$name - response_body - response is expected" ); } } } } elsif ( defined $block->response_body_like ) { my $content = $res->content; if ( defined $content ) { $content =~ s/^TE: deflate,gzip;q=0\.3\r\n//gms; } $content =~ s/^Connection: TE, close\r\n//gms; my $expected_pat = get_indexed_value($name, $block->response_body_like, $req_idx, $need_array); $expected_pat =~ s/\$ServerPort\b/$ServerPort/g; $expected_pat =~ s/\$ServerPortForClient\b/$ServerPortForClient/g; my $summary = trim($content); SKIP: { skip "$name - tests skipped due to the lack of directive $dry_run", 1 if $dry_run; like( $content, qr/$expected_pat/s, "$name - response_body_like - response is expected ($summary)" ); } } elsif ( defined $block->response_body_unlike ) { my $content = $res->content; if ( defined $content ) { $content =~ s/^TE: deflate,gzip;q=0\.3\r\n//gms; } $content =~ s/^Connection: TE, close\r\n//gms; my $expected_pat = get_indexed_value($name, $block->response_body_unlike, $req_idx, $need_array); $expected_pat =~ s/\$ServerPort\b/$ServerPort/g; $expected_pat =~ s/\$ServerPortForClient\b/$ServerPortForClient/g; my $summary = trim($content); SKIP: { skip "$name - tests skipped due to the lack of directive $dry_run", 1 if $dry_run; unlike( $content, qr/$expected_pat/s, "$name - response_body_like - response is expected ($summary)" ); } } sub parse_response($$) { my ( $name, $raw_resp ) = @_; my $left; my $raw_headers = ''; if ( $raw_resp =~ /(.*?\r\n)\r\n/s ) { #warn "\$1: $1"; $raw_headers = $1; } #warn "raw headers: $raw_headers\n"; my $res = HTTP::Response->parse($raw_resp); my $enc = $res->header('Transfer-Encoding'); my $len = $res->header('Content-Length'); if ( defined $enc && $enc eq 'chunked' ) { #warn "Found chunked!"; my $raw = $res->content; if ( !defined $raw ) { $raw = ''; } my $decoded = ''; while (1) { if ( $raw =~ /\G 0 [\ \t]* \r\n \r\n /gcsx ) { if ( $raw =~ /\G (.+) /gcsx ) { $left = $1; } last; } if ( $raw =~ m{ \G [\ \t]* ( [A-Fa-f0-9]+ ) [\ \t]* \r\n }gcsx ) { my $rest = hex($1); #warn "chunk size: $rest\n"; my $bit_sz = 32765; while ( $rest > 0 ) { my $bit = $rest < $bit_sz ? $rest : $bit_sz; #warn "bit: $bit\n"; if ( $raw =~ /\G(.{$bit})/gcs ) { $decoded .= $1; #warn "decoded: [$1]\n"; } else { fail( "$name - invalid chunked data received (not enought octets for the data section)" ); return; } $rest -= $bit; } if ( $raw !~ /\G\r\n/gcs ) { fail( "$name - invalid chunked data received (expected CRLF)." ); return; } } elsif ( $raw =~ /\G.+/gcs ) { fail "$name - invalid chunked body received: $&"; return; } else { fail "$name - no last chunk found - $raw"; return; } } #warn "decoded: $decoded\n"; $res->content($decoded); } elsif (defined $len && $len ne '' && $len >= 0) { my $raw = $res->content; if (length $raw < $len) { warn "WARNING: $name - response body truncated: ", "$len expected, but got ", length $raw, "\n"; } elsif (length $raw > $len) { my $content = substr $raw, 0, $len; $left = substr $raw, $len; $res->content($content); #warn "parsed body: [", $res->content, "]\n"; } } return ( $res, $raw_headers, $left ); } sub send_request ($$$$@) { my ( $req, $middle_delay, $timeout, $name, $tries ) = @_; my $sock = IO::Socket::INET->new( PeerAddr => $ServerAddr, PeerPort => $ServerPortForClient, Proto => 'tcp' ); if (! defined $sock) { $tries ||= 0; if ($tries < 3) { warn "Can't connect to $ServerAddr:$ServerPortForClient: $!\n"; sleep 1; return send_request($req, $middle_delay, $timeout, $name, $tries + 1); } else { die "Can't connect to $ServerAddr:$ServerPortForClient: $!\n"; } } my @req_bits = ref $req ? @$req : ($req); my $flags = fcntl $sock, F_GETFL, 0 or die "Failed to get flags: $!\n"; fcntl $sock, F_SETFL, $flags | O_NONBLOCK or die "Failed to set flags: $!\n"; my $ctx = { resp => '', write_offset => 0, buf_size => 1024, req_bits => \@req_bits, write_buf => (shift @req_bits)->{"value"}, middle_delay => $middle_delay, sock => $sock, name => $name, }; my $readable_hdls = IO::Select->new($sock); my $writable_hdls = IO::Select->new($sock); my $err_hdls = IO::Select->new($sock); while (1) { if ( $readable_hdls->count == 0 && $writable_hdls->count == 0 && $err_hdls->count == 0 ) { last; } my ( $new_readable, $new_writable, $new_err ) = IO::Select->select( $readable_hdls, $writable_hdls, $err_hdls, $timeout ); if ( !defined $new_err && !defined $new_readable && !defined $new_writable ) { # timed out timeout_event_handler($ctx); last; } for my $hdl (@$new_err) { next if !defined $hdl; error_event_handler($ctx); if ( $err_hdls->exists($hdl) ) { $err_hdls->remove($hdl); } if ( $readable_hdls->exists($hdl) ) { $readable_hdls->remove($hdl); } if ( $writable_hdls->exists($hdl) ) { $writable_hdls->remove($hdl); } for my $h (@$readable_hdls) { next if !defined $h; if ( $h eq $hdl ) { undef $h; last; } } for my $h (@$writable_hdls) { next if !defined $h; if ( $h eq $hdl ) { undef $h; last; } } close $hdl; } for my $hdl (@$new_readable) { next if !defined $hdl; my $res = read_event_handler($ctx); if ( !$res ) { # error occured if ( $err_hdls->exists($hdl) ) { $err_hdls->remove($hdl); } if ( $readable_hdls->exists($hdl) ) { $readable_hdls->remove($hdl); } if ( $writable_hdls->exists($hdl) ) { $writable_hdls->remove($hdl); } for my $h (@$writable_hdls) { next if !defined $h; if ( $h eq $hdl ) { undef $h; last; } } close $hdl; } } for my $hdl (@$new_writable) { next if !defined $hdl; my $res = write_event_handler($ctx); if ( !$res ) { # error occured if ( $err_hdls->exists($hdl) ) { $err_hdls->remove($hdl); } if ( $readable_hdls->exists($hdl) ) { $readable_hdls->remove($hdl); } if ( $writable_hdls->exists($hdl) ) { $writable_hdls->remove($hdl); } close $hdl; } elsif ( $res == 2 ) { if ( $writable_hdls->exists($hdl) ) { $writable_hdls->remove($hdl); } } } } return $ctx->{resp}; } sub timeout_event_handler ($) { my $ctx = shift; warn "ERROR: socket client: timed out - $ctx->{name}\n"; } sub error_event_handler ($) { warn "exception occurs on the socket: $!\n"; } sub write_event_handler ($) { my ($ctx) = @_; while (1) { return undef if !defined $ctx->{write_buf}; my $rest = length( $ctx->{write_buf} ) - $ctx->{write_offset}; #warn "offset: $write_offset, rest: $rest, length ", length($write_buf), "\n"; #die; if ( $rest > 0 ) { my $bytes; eval { $bytes = syswrite( $ctx->{sock}, $ctx->{write_buf}, $rest, $ctx->{write_offset} ); }; if ($@) { my $errmsg = "write failed: $@"; warn "$errmsg\n"; $ctx->{resp} = $errmsg; return undef; } if ( !defined $bytes ) { if ( $! == EAGAIN ) { #warn "write again..."; #sleep 0.002; return 1; } my $errmsg = "write failed: $!"; warn "$errmsg\n"; if ( !$ctx->{resp} ) { $ctx->{resp} = "$errmsg"; } return undef; } #warn "wrote $bytes bytes.\n"; $ctx->{write_offset} += $bytes; } else { my $next_send = shift @{ $ctx->{req_bits} } or return 2; $ctx->{write_buf} = $next_send->{'value'}; $ctx->{write_offset} = 0; my $wait_time; if (!defined $next_send->{'delay_before'}) { if (defined $ctx->{middle_delay}) { $wait_time = $ctx->{middle_delay}; } } else { $wait_time = $next_send->{'delay_before'}; } if ($wait_time) { #warn "sleeping.."; sleep $wait_time; } } } # impossible to reach here... return undef; } sub read_event_handler ($) { my ($ctx) = @_; while (1) { my $read_buf; my $bytes = sysread( $ctx->{sock}, $read_buf, $ctx->{buf_size} ); if ( !defined $bytes ) { if ( $! == EAGAIN ) { #warn "read again..."; #sleep 0.002; return 1; } $ctx->{resp} = "500 read failed: $!"; return undef; } if ( $bytes == 0 ) { return undef; # connection closed } $ctx->{resp} .= $read_buf; #warn "read $bytes ($read_buf) bytes.\n"; } # impossible to reach here... return undef; } 1; __END__ =encoding utf-8 =head1 NAME Test::Nginx::Socket - Socket-backed test scaffold for the Nginx C modules =head1 SYNOPSIS use Test::Nginx::Socket; plan tests => $Test::Nginx::Socket::RepeatEach * 2 * blocks(); run_tests(); __DATA__ === TEST 1: sanity --- config location /echo { echo_before_body hello; echo world; } --- request GET /echo --- response_body hello world --- error_code: 200 === TEST 2: set Server --- config location /foo { echo hi; more_set_headers 'Server: Foo'; } --- request GET /foo --- response_headers Server: Foo --- response_body hi === TEST 3: clear Server --- config location /foo { echo hi; more_clear_headers 'Server: '; } --- request GET /foo --- response_headers_like Server: nginx.* --- response_body hi === TEST 3: chunk size too small --- config chunkin on; location /main { echo_request_body; } --- more_headers Transfer-Encoding: chunked --- request eval "POST /main 4\r hello\r 0\r \r " --- error_code: 400 --- response_body_like: 400 Bad Request =head1 DESCRIPTION This module provides a test scaffold based on non-blocking L for automated testing in Nginx C module development. This class inherits from L, thus bringing all its declarative power to the Nginx C module testing practices. You need to terminate or kill any Nginx processes before running the test suite if you have changed the Nginx server binary. Normally it's as simple as killall nginx PATH=/path/to/your/nginx-with-memc-module:$PATH prove -r t This module will create a temporary server root under t/servroot/ of the current working directory and starts and uses the nginx executable in the PATH environment. You will often want to look into F when things go wrong ;) =head1 Sections supported The following sections are supported: =head2 config Content of this section will be included in the "server" part of the generated config file. This is the place where you want to put the "location" directive enabling the module you want to test. Example: location /echo { echo_before_body hello; echo world; } Sometimes you simply don't want to bother copying ten times the same configuration for the ten tests you want to run against your module. One way to do this is to write a config section only for the first test in your C<.t> file. All subsequent tests will re-use the same config. Please note that this depends on the order of test, so you should run C with variable C (see below for more on this variable). Please note that config section goes through environment variable expansion provided the variables to expand start with TEST_NGINX. So, the following is a perfectly legal (provided C is set correctly): location /main { echo_subrequest POST /sub -f $TEST_NGINX_HTML_DIR/blah.txt; } =head2 http_config Content of this section will be included in the "http" part of the generated config file. This is the place where you want to put the "upstream" directive you might want to test. Example: upstream database { postgres_server 127.0.0.1:$TEST_NGINX_POSTGRESQL_PORT dbname=ngx_test user=ngx_test password=wrong_pass; } As you guessed from the example above, this section goes through environment variable expansion (variables have to start with TEST_NGINX). =head2 main_config Content of this section will be included in the "main" part of the generated config file. This is very rarely used, except if you are testing nginx core itself. This section goes through environment variable expansion (variables have to start with TEST_NGINX). =head2 request This is probably the most important section. It defines the request(s) you are going to send to the nginx server. It offers a pretty powerful grammar which we are going to walk through one example at a time. In its most basic form, this section looks like that: --- request GET This will just do a GET request on the root (i.e. /) of the server using HTTP/1.1. Of course, you might want to test something else than the root of your web server and even use a different version of HTTP. This is possible: --- request GET /foo HTTP/1.0 Please note that specifying HTTP/1.0 will not prevent Test::Nginx from sending the C header. Actually Test::Nginx always sends 2 headers: C (with value localhost) and C (with value Close for simple requests and keep-alive for all but the last pipelined_requests). You can also add a content to your request: --- request POST /foo Hello world Test::Nginx will automatically calculate the content length and add the corresponding header for you. This being said, as soon as you want to POST real data, you will be interested in using the more_headers section and using the power of Test::Base filters to urlencode the content you are sending. Which gives us a slightly more realistic example: --- more_headers Content-type: application/x-www-form-urlencoded --- request eval use URI::Escape; "POST /rrd/foo value=".uri_escape("N:12345") Sometimes a test is more than one request. Typically you want to POST some data and make sure the data has been taken into account with a GET. You can do it using arrays: --- request eval ["POST /users name=foo", "GET /users/foo"] This way, REST-like interfaces are pretty easy to test. When you develop nifty nginx modules you will eventually want to test things with buffers and "weird" network conditions. This is where you split your request into network packets: --- request eval [["POST /users\nna", "me=foo"]] Here, Test::Nginx will first send the request line, the headers it automatically added for you and the first two letters of the body ("na" in our example) in ONE network packet. Then, it will send the next packet (here it's "me=foo"). When we talk about packets here, this is nto exactly correct as there is no way to guarantee the behavior of the TCP/IP stack. What Test::Nginx can guarantee is that this will result in two calls to C. A good way to make I sure the two calls result in two packets is to introduce a delay (let's say 2 seconds)before sending the second packet: --- request eval [["POST /users\nna", {value => "me=foo", delay_before => 2}]] Of course, everything can be combined till your brain starts boiling ;) : --- request eval use URI::Escape; my $val="value=".uri_escape("N:12346"); [["POST /rrd/foo ".substr($val, 0, 6), {value => substr($val, 6, 5), delay_before=>5}, substr($val, 11)], "GET /rrd/foo"] =head2 request_eval Use of this section is deprecated and tests using it should replace it with a C section with an C filter. More explicitly: --- request_eval "POST /echo_body hello\x00\x01\x02 world\x03\x04\xff" should be replaced by: --- request eval "POST /echo_body hello\x00\x01\x02 world\x03\x04\xff" =head2 pipelined_requests Specify pipelined requests that use a single keep-alive connection to the server. Here is an example from ngx_lua's test suite: === TEST 7: discard body --- config location = /foo { content_by_lua ' ngx.req.discard_body() ngx.say("body: ", ngx.var.request_body) '; } location = /bar { content_by_lua ' ngx.req.read_body() ngx.say("body: ", ngx.var.request_body) '; } --- pipelined_requests eval ["POST /foo hello, world", "POST /bar hiya, world"] --- response_body eval ["body: nil\n", "body: hiya, world\n"] =head2 more_headers Adds the content of this section as headers to the request being sent. Example: --- more_headers X-Foo: blah This will add C to the request (on top of the automatically generated headers like C, C and potentially C). =head2 response_body The expected value for the body of the submitted request. --- response_body hello If the test is made of multiple requests, then the response_body B be an array and each request B return the corresponding expected body: --- request eval ["GET /hello", "GET /world"] --- response_body eval ["hello", "world"] =head2 response_body_eval Use of this section is deprecated and tests using it should replace it with a C section with an C filter. Therefore: --- response_body_eval "hello\x00\x01\x02 world\x03\x04\xff" should be replaced by: --- response_body eval "hello\x00\x01\x02 world\x03\x04\xff" =head2 response_body_like The body returned by the request MUST match the pattern provided by this section. Example: --- response_body_like ^elapsed 0\.00[0-5] sec\.$ If the test is made of multiple requests, then response_body_like B be an array and each request B match the corresponding pattern. =head2 response_headers The headers specified in this section are in the response sent by nginx. --- response_headers Content-Type: application/x-resty-dbd-stream Of course, you can specify many headers in this section: --- response_headers X-Resty-DBD-Module: Content-Type: application/x-resty-dbd-stream The test will be successful only if all headers are found in the response with the appropriate values. If the test is made of multiple requests, then response_headers B be an array and each element of the array is checked against the response to the corresponding request. =head2 response_headers_like The value of the headers returned by nginx match the patterns. --- response_headers_like X-Resty-DBD-Module: ngx_drizzle \d+\.\d+\.\d+ Content-Type: application/x-resty-dbd-stream This will check that the response's C is application/x-resty-dbd-stream and that the C matches C. The test will be successful only if all headers are found in the response and if the values match the patterns. If the test is made of multiple requests, then response_headers_like B be an array and each element of the array is checked against the response to the corresponding request. =head2 raw_response_headers_like Checks the headers part of the response against this pattern. This is particularly useful when you want to write tests of redirect functions that are not bound to the value of the port your nginx server (under test) is listening to: --- raw_response_headers_like: Location: http://localhost(?::\d+)?/foo\r\n As usual, if the test is made of multiple requests, then raw_response_headers_like B be an array. =head2 error_code The expected value of the HTTP response code. If not set, this is assumed to be 200. But you can expect other things such as a redirect: --- error_code: 302 If the test is made of multiple requests, then error_code B be an array with the expected value for the response status of each request in the test. =head2 raw_request The exact request to send to nginx. This is useful when you want to test soem behaviors that are not available with "request" such as an erroneous C header or splitting packets right in the middle of headers: --- raw_request eval ["POST /rrd/taratata HTTP/1.1\r Host: localhost\r Connection: Close\r Content-Type: application/", "x-www-form-urlencoded\r Content-Length:15\r\n\r\nvalue=N%3A12345"] This can also be useful to tests "invalid" request lines: --- raw_request GET /foo HTTP/2.0 THE_FUTURE_IS_NOW =head2 user_files With this section you can create a file that will be copied in the html directory of the nginx server under test. For example: --- user_files >>> blah.txt Hello, world will create a file named C in the html directory of the nginx server tested. The file will contain the text "Hello, world". =head2 skip_nginx =head2 skip_nginx2 Both string scalar and string arrays are supported as values. =head2 raw_request_middle_delay Delay in sec between sending successive packets in the "raw_request" array value. Also used when a request is split in packets. =head1 Environment variables All environment variables starting with C are expanded in the sections used to build the configuration of the server that tests automatically starts. The following environment variables are supported by this module: =head2 TEST_NGINX_NO_NGINX_MANAGER Defaults to 0. If set to 1, Test::Nginx module will not manage (configure/start/stop) the C process. Can be useful to run tests against an already configured (and running) nginx server. =head2 TEST_NGINX_NO_SHUFFLE Dafaults to 0. If set to 1, will make sure the tests are run in the order they appear in the test file (and not in random order). =head2 TEST_NGINX_USE_VALGRIND If set to 1, will start nginx with valgrind. nginx is actually started with C, the suppressions option being used only if there is actually a valgrind.suppress file. =head2 TEST_NGINX_BINARY The command to start nginx. Defaults to C. Can be used as an alternative to setting C to run a specific nginx instance. =head2 TEST_NGINX_LOG_LEVEL Value of the last argument of the C configuration directive. Defaults to C. =head2 TEST_NGINX_MASTER_PROCESS Value of the C configuration directive. Defaults to C. =head2 TEST_NGINX_SERVER_PORT Value of the port the server started by Test::Nginx will listen to. If not set, C is used. If C is not set, then C<1984> is used. See below for typical use. =head2 TEST_NGINX_CLIENT_PORT Value of the port Test::Nginx will diirect requests to. If not set, C is used. If C is not set, then C<1984> is used. A typical use of this feature is to test extreme network conditions by adding a "proxy" between Test::Nginx and nginx itself. This is described in the C section of this module README. =head2 TEST_NGINX_PORT A shortcut for setting both C and C. =head2 TEST_NGINX_SLEEP How much time (in seconds) should Test::Nginx sleep between two calls to C when sending request data. Defaults to 0. =head2 TEST_NGINX_FORCE_RESTART_ON_TEST Defaults to 1. If set to 0, Test::Nginx will not restart the nginx server when the config does not change between two tests. =head2 TEST_NGINX_SERVROOT The root of the nginx "hierarchy" (where you find the conf, *_tmp and logs directories). This value will be used with the C<-p> option of C. Defaults to appending C to the current directory. =head2 TEST_NGINX_IGNORE_MISSING_DIRECTIVES If set to 1 will SKIP all tests which C sections resulted in a C when trying to start C. Useful when you want to run tests on a build of nginx that does not include all modules it should. By default, these tests will FAIL. =head2 TEST_NGINX_EVENT_TYPE This environment can be used to specify a event API type to be used by Nginx. Possible values are C, C, C