Commit 954cd07b authored by Geoff Simmons's avatar Geoff Simmons

WIP

parents
((nil . ((indent-tabs-mode . t)))
(c-mode . ((c-file-style . "BSD"))))
Makefile
Makefile.in
.deps/
.libs/
*.o
*.lo
*.la
*~
*.[1-9]
.dirstamp
/aclocal.m4
/ar-lib
/autom4te.cache/
/compile
/config.guess
/config.h
/config.h.in
/config.log
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/missing
/stamp-h1
/test-driver
/m4/
/src/vcc_if.c
/src/vcc_if.h
/src/vmod_*rst
/src/tests/*.log
/src/tests/*.trs
/src/test-suite.log
CONTRIBUTING
============
To contribute code or documentation, submit a pull request at the
`source repository website
<https://code.uplex.de/uplex-varnish/libvdp-pesi>`_.
If you have a problem or discover a bug, you can post an `issue
<https://code.uplex.de/uplex-varnish/libvdp-pesi/issues>`_ at
the website. You can also write to <varnish-support@uplex.de>.
For developers
--------------
The VDP source code is in C, and compilation has been tested with gcc
and clang. The code MUST always compile successfully with both of
them.
The build specifies C99 conformance for C sources (``-std=c99``). All
compiler warnings are turned on, and all warnings are considered
errors (``-Werror -Wall -Wextra``). The code MUST always build
without warnings or errors under these constraints.
By default, ``CFLAGS`` is set to ``-g -O2``, so that symbols are
included in the shared library, and optimization is at level
``O2``. To change or disable these options, set ``CFLAGS`` explicitly
before calling ``configure`` (it may be set to the empty string).
For development/debugging cycles, the ``configure`` option
``--enable-debugging`` is recommended (off by default). This will turn
off optimizations and function inlining, so that a debugger will step
through the code as expected.
By default, the VMOD is built with the stack protector enabled
(compile option ``-fstack-protector``), but it can be disabled with
the ``configure`` option ``--disable-stack-protector``.
See LICENSE for details.
INSTALLATION
============
Building from source
~~~~~~~~~~~~~~~~~~~~
The VDP is built against a Varnish installation, and the autotools use
``pkg-config(1)`` to locate the necessary header files and other
resources for Varnish. This sequence will install the VDP::
> ./autogen.sh # for builds from the git repo
> ./configure
> make
> make check # to run unit tests in src/tests/*.vtc
> make distcheck # run check and prepare a distribution tarball
> sudo make install
See `CONTRIBUTING.rst <CONTRIBUTING.rst>`_ for notes about building
from source.
If you have installed Varnish in non-standard directories, call
``autogen.sh`` and ``configure`` with the ``PKG_CONFIG_PATH``
environment variable set to include the paths where the ``.pc`` file
can be located for ``varnishapi``. For example, when varnishd
configure was called with ``--prefix=$PREFIX``, use::
> PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig
> export PKG_CONFIG_PATH
By default, the ``configure`` script installs the VDP in the same
directory as Varnish, determined via ``pkg-config(1)``. The vmod
installation directory can be overridden by passing the ``VMOD_DIR``
variable to ``configure``.
Other files such as the man-page are installed in the locations
determined by ``configure``, which inherits its default ``--prefix``
setting from Varnish.
Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL 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.
ACLOCAL_AMFLAGS = -I m4 -I ${VARNISHAPI_DATAROOTDIR}/aclocal
SUBDIRS = src
DISTCHECK_CONFIGURE_FLAGS = \
VMOD_DIR='$${libdir}/varnish/vmods'
EXTRA_DIST = README.rst LICENSE COPYING CONTRIBUTING.rst INSTALL.rst
doc_DATA = README.rst LICENSE COPYING CONTRIBUTING.rst INSTALL.rst
README.rst: src/vdp_pesi.vcc
$(MAKE) $(AM_MAKEFLAGS) -C src vmod_pesi.man.rst
cp src/vmod_pesi.man.rst README.rst
%.1 %.2 %.3 %.4 %.5 %.6 %.7 %.8 %.9:
if HAVE_RST2MAN
${RST2MAN} $< $@
else
@echo "========================================"
@echo "You need rst2man installed to make dist"
@echo "========================================"
@false
endif
..
.. NB: This file is machine generated, DO NOT EDIT!
..
.. Edit vmod.vcc and run make instead
..
.. role:: ref(emphasis)
=========
VMOD pesi
=========
----------------------------------------------------
Varnish Delivery Processor for parallel ESI includes
----------------------------------------------------
:Manual section: 3
SYNOPSIS
========
::
import pesi;
# VDP version
STRING pesi.version()
DESCRIPTION
===========
VDP pesi is a Varnish Delivery Processor for parallel Edge Side
Includes (ESI). ...
.. _vmod_pesi.version:
STRING version()
----------------
Return the version string for this VDP.
Example::
std.log("Using VDP pesi version: " + pesi.version());
REQUIREMENTS
============
The VDP currently requires the Varnish master branch. ...
INSTALLATION
============
See `INSTALL.rst <INSTALL.rst>`_ in the source repository.
SEE ALSO
========
* varnishd(1)
* vcl(7)
* VMOD source repository: https://code.uplex.de/uplex-varnish/libvdp-pesi
COPYRIGHT
=========
::
Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
All rights reserved
Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
See LICENSE
#!/bin/sh
warn() {
echo "WARNING: $@" 1>&2
}
case `uname -s` in
Darwin)
LIBTOOLIZE=glibtoolize
;;
FreeBSD)
LIBTOOLIZE=libtoolize
;;
Linux)
LIBTOOLIZE=libtoolize
;;
SunOS)
LIBTOOLIZE=libtoolize
;;
*)
warn "unrecognized platform:" `uname -s`
LIBTOOLIZE=libtoolize
esac
automake_version=`automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+'`
if [ -z "$automake_version" ] ; then
warn "unable to determine automake version"
else
case $automake_version in
0.*|1.[0-8]|1.[0-8][.-]*)
warn "automake ($automake_version) detected; 1.9 or newer recommended"
;;
*)
;;
esac
fi
# check for varnishapi.m4 in custom paths
dataroot=$(pkg-config --variable=datarootdir varnishapi 2>/dev/null)
if [ -z "$dataroot" ] ; then
cat >&2 <<'EOF'
Package varnishapi was not found in the pkg-config search path.
Perhaps you should add the directory containing `varnishapi.pc'
to the PKG_CONFIG_PATH environment variable
EOF
exit 1
fi
set -ex
aclocal -I m4 -I ${dataroot}/aclocal
$LIBTOOLIZE --copy --force
autoheader
automake --add-missing --copy --foreign
autoconf
AC_PREREQ(2.68)
AC_COPYRIGHT([Copyright (c) 2019 UPLEX - Nils Goroll Systemoptimierung])
AC_INIT([libvdp-pesi], [trunk], [varnish-support@uplex.de], [vdp-pesi])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR(src/vdp_pesi.vcc)
AM_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AC_LANG(C)
AM_INIT_AUTOMAKE([1.12 -Wall -Werror foreign parallel-tests])
AM_SILENT_RULES([yes])
AM_PROG_AR
LT_PREREQ([2.2.6])
LT_INIT([dlopen disable-static])
AC_PROG_CC
AC_PROG_CC_STDC
if test "x$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([Could not find a C99 compatible compiler])
fi
AC_PROG_CPP
AX_PTHREAD(,[AC_MSG_ERROR([Could not configure pthreads support])])
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
AC_ARG_WITH([rst2man],
AS_HELP_STRING(
[--with-rst2man=PATH],
[Location of rst2man (auto)]),
[RST2MAN="$withval"],
AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], []))
AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"])
m4_ifndef([VARNISH_PREREQ], AC_MSG_ERROR([Need varnish.m4 -- see README.rst]))
VARNISH_PREREQ([trunk])
VARNISH_VMODS([pesi])
VMOD_TESTS="$(cd $srcdir/src && echo tests/*.vtc)"
AC_SUBST(VMOD_TESTS)
PKG_CHECK_VAR([LIBVARNISHAPI_LIBDIR], [varnishapi], [libdir])
AC_SUBST([VARNISH_LIBRARY_PATH],
[$LIBVARNISHAPI_LIBDIR:$LIBVARNISHAPI_LIBDIR/varnish])
# Checks for C sources
# AC_CHECK_FUNCS([strdup])
AC_ARG_VAR([VARNISHSRC], [path to Varnish source tree (REQUIRED)])
if test "${VARNISHSRC+set}" != set; then
AC_MSG_ERROR([VARNISHSRC must be set (path to Varnish source tree)])
fi
AC_CHECK_FILE(["$VARNISHSRC/include/miniobj.h"],
[AC_MSG_RESULT([VARNISHSRC (Varnish source dir)... $VARNISHSRC])],
[AC_MSG_ERROR([VARNISHSRC ($VARNISHSRC) is not a Varnish source dir])])
# --enable-stack-protector
AC_ARG_ENABLE(stack-protector,
AS_HELP_STRING([--enable-stack-protector],[enable stack protector (default is YES)]),
[],
[enable_stack_protector=yes])
if test "x$enable_stack_protector" != "xno"; then
AX_CHECK_COMPILE_FLAG([-fstack-protector],
AX_CHECK_LINK_FLAG([-fstack-protector],
[CFLAGS="${CFLAGS} -fstack-protector"], [], []),
[], [])
fi
# --enable-debugging
AC_ARG_ENABLE(debugging,
AS_HELP_STRING([--enable-debugging],[enable debugging (default is NO)]),
[],
[enable_debugging=no])
# AC_PROG_CC sets CFLAGS to '-g -O2' unless already set, so there's no
# need to add -g. Disable or change by explicitly setting CFLAGS. If
# this option is enabled, then -Og or -O0 becomes the last
# optimization option, and hence takes precedence.
if test "x$enable_debugging" != "xno"; then
CFLAGS="${CFLAGS} -fno-inline"
AX_CHECK_COMPILE_FLAG([-Og],
[CFLAGS="${CFLAGS} -O0 -Og"],
[CFLAGS="${CFLAGS} -O0"],
[])
fi
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_OUTPUT
AUTOMAKE_OPTIONS = subdir-objects
AM_CFLAGS = $(VARNISHAPI_CFLAGS) -I$(VARNISHSRC)/include \
-I$(VARNISHSRC)/bin/varnishd -I$(VARNISHSRC)/lib/libvgz \
-Wall -Werror -Wextra -std=c99
AM_LDFLAGS = $(VARNISHAPI_LIBS) $(VMOD_LDFLAGS) -ldl
vmod_LTLIBRARIES = libvmod_pesi.la
libvmod_pesi_la_SOURCES = \
vdp_pesi.c \
foreign/cache_esi_deliver.h \
foreign/cache_esi_deliver.c
nodist_libvmod_pesi_la_SOURCES = \
vcc_if.c \
vcc_if.h
dist_man_MANS = vdp_pesi.3
vdp_pesi.lo: $(nodist_libvmod_pesi_la_SOURCES)
vcc_if.h vmod_pesi.rst vmod_pesi.man.rst: vcc_if.c
vcc_if.c: vdp_pesi.vcc
$(AM_V_VMODTOOL) $(PYTHON) $(VMODTOOL) -o vcc_if $(srcdir)/vdp_pesi.vcc
vdp_pesi.3: vmod_pesi.man.rst
$(AM_V_GEN) $(RST2MAN) vmod_pesi.man.rst vdp_pesi.3
AM_TESTS_ENVIRONMENT = \
PATH="$(VMOD_TEST_PATH)" \
LD_LIBRARY_PATH="$(VARNISH_LIBRARY_PATH)"
TEST_EXTENSIONS = .vtc
VTC_LOG_COMPILER = varnishtest -v -L -t 10
AM_VTC_LOG_FLAGS = -Dvmod_pesi="$(VMOD_PESI)"
# To test an individual VTC test named test.vtc:
# $ cd src/
# $ make check TESTS=tests/test.vtc
TESTS = @VMOD_TESTS@
EXTRA_DIST = \
vdp_pesi.vcc \
$(VMOD_TESTS)
CLEANFILES = \
$(builddir)/vcc_if.c \
$(builddir)/vcc_if.h \
$(builddir)/vmod_pesi.rst \
$(builddir)/vmod_pesi.man.rst \
$(builddir)/vdp_pesi.3
This diff is collapsed.
/*-
* Copyright (c) 2011 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL 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.
*
* VED - Varnish Esi Delivery
*/
#include <limits.h>
/* Sentinel length for a gzip-in-gzip tailbuf, for updating CRC */
#define GZIP_TAILBUF SSIZE_MAX
const struct vdp ved_pretend_gz;
const struct vdp ved_gzgz;
const struct vdp ved_ved;
struct ecx {
unsigned magic;
#define ECX_MAGIC 0x0b0f9163
const uint8_t *p;
const uint8_t *e;
struct req *preq;
struct worker *wrk;
struct bytes_node *parent;
struct bytes_node *node;
struct bytes_node *child;
ssize_t l;
#if 0
ssize_t l_crc;
uint32_t crc;
int isgzip;
#endif
int state;
int woken;
};
struct ved_foo {
unsigned magic;
#define VED_FOO_MAGIC 0x6a5a262d
struct ecx *ecx;
ssize_t start, last, stop, lpad;
ssize_t ll;
uint64_t olen;
uint8_t dbits[8];
uint8_t tailbuf[8];
};
# looks like -*- vcl -*-
varnishtest "vcl.use and .discard, and version string"
varnish v1 -vcl {
import ${vmod_pesi};
backend b { .host = "${bad_ip}"; }
} -start
varnish v1 -vcl {backend b { .host = "${bad_ip}"; }}
varnish v1 -cli "vcl.list"
varnish v1 -cli "vcl.use vcl1"
varnish v1 -cli "vcl.use vcl2"
varnish v1 -cli "vcl.use vcl1"
varnish v1 -cli "vcl.show vcl1"
varnish v1 -cli "vcl.use vcl2"
varnish v1 -cli "vcl.discard vcl1"
varnish v1 -cli "vcl.list"
varnish v1 -vcl {
import ${vmod_pesi};
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.x-version = pesi.version();
if (!resp.http.x-version) {
set resp.status = 500;
}
return(deliver);
}
}
client c1 {
txreq -url "/"
rxresp
expect resp.status == 200
expect resp.http.x-version ~ "^.+$"
} -run
varnishtest "pESI test with no ESI content"
server s1 {
rxreq
txresp -body {
-This is a test: Hello world
}
} -start
varnish v1 -arg "-p debug=+syncvsl" -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
logexpect l1 -v v1 -g raw {
expect * * ESI_xmlerror esi_disable_xml_check
expect * 1001 End
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 33
expect resp.body == {
-This is a test: Hello world
}
}
client c1 -run
logexpect l1 -wait
varnish v1 -expect esi_errors == 0
varnishtest "pESI:remove"
server s1 {
rxreq
txresp -body {
<esi:remove>
This is a test: Unseen University
<esi:include src="trick question">
<!--esi XXX -->
</esi:remove>
<esX>This is a test: Hello world
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
logexpect l1 -v v1 -g raw {
expect * * ESI_xmlerror {^ERR after 3 ESI 1.0 <esi:include> element nested in <esi:remove>}
expect 0 = ESI_xmlerror {^ERR after 3 ESI 1.0 Nested <!--esi element in <esi:remove>}
expect * 1001 End
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 40
expect resp.body == {
<esX>This is a test: Hello world
}
}
client c1 -run
logexpect l1 -wait
varnish v1 -expect esi_errors == 2
varnishtest "ESI CDATA"
server s1 {
rxreq
txresp -body {
<esi:remove>
<![CDATA[</esi:remove>]]>
This is a test: Unseen University
</esi:remove>
This is a test: Hello world
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 35
expect resp.body == {
This is a test: Hello world
}
}
client c1 -run
varnish v1 -expect esi_errors == 0
varnishtest "ESI include"
server s1 {
rxreq
expect req.http.esi0 == "foo"
txresp -body {
<html>
Before include
<esi:include src="/body" sr="foo"/>
After include
</html>
}
} -start
server s2 {
rxreq
expect req.url == "/body1"
expect req.http.esi0 != "foo"
txresp -body {
Included file
}
} -start
varnish v1 -arg "-p debug=+syncvsl" -vcl+backend {
import ${vmod_pesi};
sub vcl_recv {
if (req.esi_level > 0) {
set req.url = req.url + req.esi_level;
} else {
set req.http.esi0 = "foo";
}
}
sub vcl_backend_fetch {
if (bereq.url == "/") {
set bereq.backend = s1;
}
else {
set bereq.backend = s2;
}
}
sub vcl_backend_response {
if (bereq.url == "/") {
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
logexpect l1 -v v1 -g request {
expect 0 1001 Begin "^req .* rxreq"
# ReqAcct body counts include chunked overhead
expect * = ReqAcct "^29 0 29 187 104 291$"
expect 0 = End
} -start
logexpect l2 -v v1 -g request {
expect * 1002 Begin "^bereq "
expect * = End
} -start
logexpect l3 -v v1 -g request {
expect * 1003 Begin "^req .* esi"
expect * = ReqAcct "^0 0 0 0 18 18$"
expect 0 = End
} -start
logexpect l4 -v v1 -g request {
expect * 1004 Begin "^bereq "
expect * = End
} -start
logexpect l5 -v v1 -g request {
expect * 1005 Begin "^req .* rxreq"
# ReqAcct body counts include chunked overhead
# Header bytes is 5 larger than in l1 due to two item X-Varnish hdr
expect * = ReqAcct "^29 0 29 192 104 296$"
expect 0 = End
} -start
client c1 {
txreq -hdr "Host: foo"
rxresp
expect resp.bodylen == 75
expect resp.status == 200
delay .1
# test that there is no difference on miss/hit
txreq -hdr "Host: foo"
rxresp
expect resp.bodylen == 75
expect resp.status == 200
}
client c1 -run
varnish v1 -expect esi_errors == 0
logexpect l1 -wait
logexpect l2 -wait
logexpect l3 -wait
logexpect l4 -wait
logexpect l5 -wait
varnishtest "ESI commented include"
server s1 {
rxreq
txresp -body {
<html>
Before include
<!--esi <esi:include src="/body"/> -->
After include
}
rxreq
expect req.url == "/body"
txresp -body {
Included file
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
if (bereq.url != "/body") {
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 67
}
client c1 -run
varnish v1 -expect esi_errors == 0
varnishtest "ESI relative include"
server s1 {
rxreq
expect req.url == "/foo/bar"
txresp -body {
<html>
Before include
<!--esi <esi:include src="body"/> -->
After include
}
rxreq
expect req.url == "/foo/body"
txresp -body {
Included file
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
if (bereq.url != "/foo/body") {
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq -url /foo/bar
rxresp
expect resp.status == 200
expect resp.bodylen == 67
}
client c1 -run
varnish v1 -expect esi_errors == 0
varnishtest "ESI include with http://"
server s1 {
rxreq
expect req.url == "/foo/bar"
txresp -body {
<html>
Before include
<!--esi <esi:include src="http://bozz/body"/> -->
After include
}
} -start
server s2 {
rxreq
expect req.url == "/body"
txresp -body {
<pre>Included file</pre>
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_fetch {
if (bereq.http.host == "bozz") {
set bereq.backend = s2;
} else {
set bereq.backend = s1;
}
}
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq -url /foo/bar -hdr "Host: froboz"
rxresp
expect resp.status == 200
expect resp.bodylen == 78
}
client c1 -run
varnish v1 -expect esi_errors == 0
# Now try with invalid URLs
server s1 {
rxreq
expect req.url == /http
txresp -body {<esi:include src="http://foobar" />1234}
rxreq
expect req.url == /https
txresp -body {<esi:include src="https://foobar" />123456}
} -start
varnish v1 -vcl+backend {
sub vcl_recv {
set req.backend_hint = s2;
set req.backend_hint = s1;
}
sub vcl_backend_response {
set beresp.do_esi = true;
}
}
varnish v1 -cliok "param.set feature +esi_ignore_https"
logexpect l1 -v v1 -g raw {
expect * * ESI_xmlerror "ERR after 0 ESI 1.0 <esi:include> invalid src= URL"
expect * * ESI_xmlerror "WARN after 0 ESI 1.0 <esi:include> https:// treated as http://"
expect * * ESI_xmlerror "ERR after 0 ESI 1.0 <esi:include> invalid src= URL"
} -start
client c1 {
txreq -url /http
rxresp
expect resp.status == 200
expect resp.bodylen == 4
txreq -url /https
rxresp
expect resp.status == 200
expect resp.bodylen == 6
}
client c1 -run
logexpect l1 -wait
varnish v1 -expect esi_errors == 2
varnishtest "ESI spanning storage bits"
# NB! The layout of the body in the response is very carefully
# NB! tuned to give the desired code coverage.
# NB! It should look like this in the varnishlog:
# NB! 7 Debug c "Fetch 32 byte segments:"
# NB! 7 Debug c "%0a%09%09<html>filler%0a%09%09This is before"
# NB! 7 Debug c " the test%0a%09%09<![CDATA[foooooooooo"
# NB! 7 Debug c "ooooooooobar]]>%0a%09%09filler<esi:rem"
# NB! 7 Debug c "ove>%0a%09%09This is a test: Unseen Un"
# NB! 7 Debug c "iversity%0a%09%09Department of cruel a"
# NB! 7 Debug c "nd unjust geography%0a%09%09</esi:remo"
# NB! 7 Debug c "ve>%0a%09%09This is a test: Hello worl"
# NB! 7 Debug c "d%0a%09"
server s1 {
rxreq
expect req.url == "/foo/bar"
send "HTTP/1.0 200 OK\n"
send "Connection: close\n"
send "\n"
send {
<html>filler
This is before the test
<![CDATA[fooooooooooooooooooobar]]>
filler<esi:remove>
This is a test: Unseen University
Department of cruel and unjust geography
</esi:remove>
This is a test: Hello world
}
} -start
varnish v1 -arg "-sdefault,2m" -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "debug.fragfetch 32"
client c1 {
txreq -url /foo/bar -hdr "Host: froboz"
rxresp
expect resp.status == 200
expect resp.bodylen == 120
}
client c1 -run
varnish v1 -expect esi_errors == 0
varnishtest "ESI parsing errors"
server s1 {
rxreq
txresp -body {
<html> 1
Before include 2
<!--esi <esi:include src="/body"/> --> 3
After include 4
<!-- normal comment --> 5
<esi:bogosity/> 6
<esi:comment> 7
foo 8
</esi:comment> 9
<esi:comment bar /> 10
11
<esi:remove> 12
<esi:comment foo/> 13
</esi:remove> 14
15
<esi:remove> 16
<esi:remove> 17
bar 18
</esi:remove> 19
</esi:remove> 20
</> 21
<esi:remove/> 22
23
<esi:include 24

> 25
26
<esi:include aaa /> 27
<esi:include k?=./> 28
<esi:include src/> 29
<esi:include src=/> 30
<esi:include src= /> 31
</esi:include> 32
<!----> 33
</!-- bogocommentt --> 34
</![CDATA[ bogo-cdata ]]> 35
<esi:include src="foofof /> 36
<esi:include foo=bar src=/body2 /> 37
<esi:include src="/body 2" /> 38
}
} -start
server s2 {
rxreq
expect req.url == "/body"
txresp -body {
<pre>Included file</pre>
<esi:remove>
<Aaa
}
} -start
server s3 {
rxreq
expect req.url == "/body2"
txresp -body {
<pre>Included file 2</pre>
<!--esi
<![CDATA[fooo
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_backend_fetch {
if (bereq.url == "/") {
set bereq.backend = s1;
}
elsif (bereq.url == "/body") {
set bereq.backend = s2;
}
elsif (bereq.url == "/body2") {
set bereq.backend = s3;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
logexpect l1 -v v1 -g vxid {
expect * * BereqURL {^/$}
expect * * ESI_xmlerror {^ERR after 134 ESI 1.0 <esi:bogus> element$}
expect 0 = ESI_xmlerror {^ERR after 157 ESI 1.0 <esi:comment> needs final '/'$}
expect 0 = ESI_xmlerror {^ERR after 192 ESI 1.0 </esi:comment> illegal end-tag$}
expect 0 = ESI_xmlerror {^ERR after 251 ESI 1.0 <esi:comment> element nested in <esi:remove>$}
expect 0 = ESI_xmlerror {^ERR after 330 ESI 1.0 <esi:remove> already open$}
expect 0 = ESI_xmlerror {^ERR after 407 ESI 1.0 <esi:remove> not open$}
expect 0 = ESI_xmlerror {^ERR after 442 ESI 1.0 <esi:remove/> not legal$}
expect 0 = ESI_xmlerror {^ERR after 474 XML 1.0 Illegal attribute start char$}
expect 0 = ESI_xmlerror {^ERR after 525 ESI 1.0 <esi:include> lacks src attr$}
expect 0 = ESI_xmlerror {^ERR after 553 XML 1.0 Illegal attr char$}
expect 0 = ESI_xmlerror {^ERR after 581 ESI 1.0 <esi:include> lacks src attr$}
expect 0 = ESI_xmlerror {^ERR after 608 XML 1.0 Missing end attribute delimiter$}
expect 0 = ESI_xmlerror {^ERR after 636 XML 1.0 Illegal attribute delimiter$}
expect 0 = ESI_xmlerror {^ERR after 665 ESI 1.0 </esi:include> illegal end-tag$}
expect 0 = ESI_xmlerror {^ERR after 767 XML 1.0 Missing end attribute delimiter$}
expect 0 = ESI_xmlerror {^ERR after 843 ESI 1.0 <esi:include> has whitespace in src= attribute$}
expect 0 = BackendReuse
} -start
logexpect l2 -v v1 -g vxid {
expect * * BereqURL {^/body$}
expect * = ESI_xmlerror {^ERR after 30 VEP ended inside a tag$}
expect 0 = BackendReuse
} -start
logexpect l3 -v v1 -g vxid {
expect * * BereqURL {^/body2$}
expect * = ESI_xmlerror {^ERR after 39 VEP ended inside a tag$}
expect 0 = BackendReuse
} -start
varnish v1 -cliok "param.set debug +esi_chop"
varnish v1 -cliok "param.set debug +syncvsl"
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 472
}
client c1 -run
logexpect l1 -wait
logexpect l2 -wait
logexpect l3 -wait
varnish v1 -expect esi_errors == 18
varnishtest "ESI binary detector"
server s1 {
rxreq
txresp -body {
Before include
<esi:remove>
bar
</esi:remove>
}
rxreq
txresp -body {
Before include
<esi:remove>
bar
</esi:remove>
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
logexpect l1 -v v1 -g raw {
expect * 1002 ESI_xmlerror esi_disable_xml_check
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 57
} -run
logexpect l1 -wait
varnish v1 -cli "param.set feature +esi_disable_xml_check"
client c1 {
txreq -url bar
rxresp
expect resp.status == 200
expect resp.bodylen == 22
expect resp.http.transfer-encoding == "chunked"
} -run
varnish v1 -expect esi_errors == 0
varnishtest "Ignoring non esi elements"
server s1 {
rxreq
txresp -body {
<f<esi?
<esi:remove>
bar
</esi:remove>
foo
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start -cli "param.set feature +esi_ignore_other_elements"
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 21
} -run
varnish v1 -expect esi_errors == 0
varnishtest "Make sure that PASS'ed ESI requests use GET for includes"
server s1 {
rxreq
expect req.method == POST
expect req.url == /foobar
txresp -body {<HTML>
FOO
<esi:include src="/bar"/>
}
rxreq
expect req.method == GET
txresp -hdr "Set-Cookie: Foo=bar" -body {<HTML>
BAR
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.uncacheable = true;
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq -req POST -url /foobar -body {
A debugged program is one for which you have
not yet found the conditions that make it fail.
-- Jerry Ogdin
}
rxresp
expect resp.status == 200
expect resp.bodylen == 31
} -run
varnish v1 -expect esi_errors == 0
varnishtest "ESI includes for pre HTTP/1.1 cannot used chunked encoding"
server s1 {
rxreq
expect req.url == "/foo/bar"
txresp -body {
<html>
Before include
<!--esi <esi:include src="body"/> -->
After include
}
rxreq
expect req.url == "/foo/body"
txresp -body {
Included file
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
if (bereq.url != "/foo/body") {
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq -url /foo/bar -proto HTTP/1.1
rxresp
expect resp.status == 200
expect resp.bodylen == 67
expect resp.http.Transfer-Encoding == "chunked"
} -run
client c1 {
txreq -url /foo/bar -proto HTTP/1.0
rxresp
expect resp.status == 200
expect resp.bodylen == 67
expect resp.http.Transfer-Encoding == <undef>
expect resp.http.Content-Length == <undef>
expect resp.http.Connection == "close"
} -run
varnish v1 -expect esi_errors == 0
varnishtest "All white-space object, in multiple storage segments"
server s1 {
rxreq
expect req.url == "/foo"
txresp -nolen -hdr "Transfer-Encoding: chunked"
chunked {<x> }
chunkedlen 0
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "debug.fragfetch 4"
client c1 {
txreq -url /foo
rxresp
} -run
varnish v1 -expect esi_errors == 0
varnishtest "Check <esi: detector"
server s1 {
rxreq
expect req.url == "/foo"
send "HTTP/1.0 200 OK\n"
send "Connection: close\n"
send "\n"
send { <a> <esi/> }
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "debug.fragfetch 4"
client c1 {
txreq -url /foo
rxresp
expect resp.bodylen == 49
} -run
varnish v1 -expect esi_errors == 0
varnishtest "ESI requests turned off"
server s1 {
rxreq
expect req.url == /
txresp -body {
<html>
Before include
<esi:include src="/body"/>
After include
}
rxreq
txresp -body {
<html>
Before include
<esi:include src="/body"/>
After include
}
rxreq
expect req.url == "/body"
txresp -body {
<pre>Included file</pre>
}
} -start
varnish v1 -syntax 4.0 -vcl+backend {
import ${vmod_pesi};
sub vcl_recv {
if (req.url == "/") {
set req.esi = false;
}
}
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (req.url != "/" && resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
elsif (req.url != "/") {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.bodylen == 73
expect resp.status == 200
txreq -url "/esi"
rxresp
expect resp.bodylen == 76
expect resp.status == 200
} -run
varnish v1 -vsl_catchup
varnish v1 -expect esi_errors == 0
server s1 {
rxreq
expect req.url == /top2
txresp -body {
<html>
Before include
<esi:include src="/body"/>
After include
}
} -start
varnish v1 -syntax 4.1 -vcl+backend {
import ${vmod_pesi};
sub vcl_deliver {
set resp.http.was = resp.do_esi;
if (req.url == "/top2") {
set resp.do_esi = false;
}
if (req.url != "/top2" && resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
elsif (req.url != "/top2") {
set resp.filters = resp.filters + " pesi";
}
}
sub vcl_backend_response {
set beresp.do_esi = true;
}
}
client c1 {
txreq -url /top2
rxresp
expect resp.bodylen == 73
expect resp.status == 200
expect resp.http.was == true
txreq -url "/esi"
rxresp
expect resp.bodylen == 76
expect resp.status == 200
expect resp.http.was == true
} -run
varnish v1 -expect esi_errors == 0
varnishtest "ESI request can't be turned off midstream"
server s1 {
rxreq
txresp -body {
<html>
Before include
<esi:include src="/body"/>
<esi:include src="/body3"/>
After include
}
} -start
server s2 {
rxreq
expect req.url == "/body"
txresp -body {
<esi:include src="/body2"/>
}
} -start
server s3 {
rxreq
expect req.url == "/body2"
txresp -body {
included
}
} -start
server s4 {
rxreq
expect req.url == "/body3"
txresp -body {
included body3
}
} -start
varnish v1 \
-syntax 4.0 \
-arg "-p feature=+esi_disable_xml_check" \
-vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_backend_fetch {
if (bereq.url == "/") {
set bereq.backend = s1;
}
elsif (bereq.url == "/body") {
set bereq.backend = s2;
}
elsif (bereq.url == "/body2") {
set bereq.backend = s3;
}
elsif (bereq.url == "/body3") {
set bereq.backend = s4;
}
}
sub vcl_deliver {
/* set req.esi = true;
if (req.url == "/body") {
set req.esi = false;
}
if (req.url != "/body" && resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
elsif (req.url != "/body") {
set resp.filters = resp.filters + " pesi";
}
*/
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.bodylen == 105
expect resp.status == 200
}
client c1 -run
varnish v1 -expect esi_errors == 0
varnishtest "Aggressive use of ESI include"
server s1 {
rxreq
txresp -body {
<html>
Before include
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/00"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/01"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/02"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/03"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/04"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/05"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/06"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/07"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/08"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/09"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/10"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/11"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/12"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/13"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/14"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/15"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/16"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/17"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/18"/>
<esi:include src="/some/very/long/url/with/dozen/of/information/for/esi/subquery/to/munch/and/also/to/try/to/make/object/workspace/explode/by/dumping/a/core/in/some/obscure/directory/on/my/file/system/19"/>
After include
}
} -start
server s2 {
rxreq
txresp -body { <pre>Included file 00</pre> }
} -start
server s3 {
rxreq
txresp -body { <pre>Included file 01</pre> }
} -start
server s4 {
rxreq
txresp -body { <pre>Included file 02</pre> }
} -start
server s5 {
rxreq
txresp -body { <pre>Included file 03</pre> }
} -start
server s6 {
rxreq
txresp -body { <pre>Included file 04</pre> }
} -start
server s7 {
rxreq
txresp -body { <pre>Included file 05</pre> }
} -start
server s8 {
rxreq
txresp -body { <pre>Included file 06</pre> }
} -start
server s9 {
rxreq
txresp -body { <pre>Included file 07</pre> }
} -start
server s10 {
rxreq
txresp -body { <pre>Included file 08</pre> }
} -start
server s11 {
rxreq
txresp -body { <pre>Included file 09</pre> }
} -start
server s12 {
rxreq
txresp -body { <pre>Included file 10</pre> }
} -start
server s13 {
rxreq
txresp -body { <pre>Included file 11</pre> }
} -start
server s14 {
rxreq
txresp -body { <pre>Included file 12</pre> }
} -start
server s15 {
rxreq
txresp -body { <pre>Included file 13</pre> }
} -start
server s16 {
rxreq
txresp -body { <pre>Included file 14</pre> }
} -start
server s17 {
rxreq
txresp -body { <pre>Included file 15</pre> }
} -start
server s18 {
rxreq
txresp -body { <pre>Included file 16</pre> }
} -start
server s19 {
rxreq
txresp -body { <pre>Included file 17</pre> }
} -start
server s20 {
rxreq
txresp -body { <pre>Included file 18</pre> }
} -start
server s21 {
rxreq
txresp -body { <pre>Included file 19</pre> }
} -start
varnish v1 -arg "-p thread_pool_min=100" -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_backend_fetch {
if (bereq.url == "/") {
set bereq.backend = s1;
}
elsif (bereq.url ~ "/00$") {
set bereq.backend = s2;
}
elsif (bereq.url ~ "/01$") {
set bereq.backend = s3;
}
elsif (bereq.url ~ "/02$") {
set bereq.backend = s4;
}
elsif (bereq.url ~ "/03$") {
set bereq.backend = s5;
}
elsif (bereq.url ~ "/04$") {
set bereq.backend = s6;
}
elsif (bereq.url ~ "/05$") {
set bereq.backend = s7;
}
elsif (bereq.url ~ "/06$") {
set bereq.backend = s8;
}
elsif (bereq.url ~ "/07$") {
set bereq.backend = s9;
}
elsif (bereq.url ~ "/08$") {
set bereq.backend = s10;
}
elsif (bereq.url ~ "/09$") {
set bereq.backend = s11;
}
elsif (bereq.url ~ "/10$") {
set bereq.backend = s12;
}
elsif (bereq.url ~ "/11$") {
set bereq.backend = s13;
}
elsif (bereq.url ~ "/12$") {
set bereq.backend = s14;
}
elsif (bereq.url ~ "/13$") {
set bereq.backend = s15;
}
elsif (bereq.url ~ "/14$") {
set bereq.backend = s16;
}
elsif (bereq.url ~ "/15$") {
set bereq.backend = s17;
}
elsif (bereq.url ~ "/16$") {
set bereq.backend = s18;
}
elsif (bereq.url ~ "/17$") {
set bereq.backend = s19;
}
elsif (bereq.url ~ "/18$") {
set bereq.backend = s20;
}
elsif (bereq.url ~ "/19$") {
set bereq.backend = s21;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
# before 29, includes 20*(29+3), after 15
expect resp.bodylen == 684
expect resp.body == {
<html>
Before include
<pre>Included file 00</pre>
<pre>Included file 01</pre>
<pre>Included file 02</pre>
<pre>Included file 03</pre>
<pre>Included file 04</pre>
<pre>Included file 05</pre>
<pre>Included file 06</pre>
<pre>Included file 07</pre>
<pre>Included file 08</pre>
<pre>Included file 09</pre>
<pre>Included file 10</pre>
<pre>Included file 11</pre>
<pre>Included file 12</pre>
<pre>Included file 13</pre>
<pre>Included file 14</pre>
<pre>Included file 15</pre>
<pre>Included file 16</pre>
<pre>Included file 17</pre>
<pre>Included file 18</pre>
<pre>Included file 19</pre>
After include
}
}
client c1 -run
varnish v1 -expect esi_errors == 0
varnishtest "Test XML 1.0 entity references"
server s1 {
rxreq
expect req.url == "/"
txresp -body {
<esi:include src="&amp;"/>
<esi:include src="&lt;"/>
<esi:include src="&gt;"/>
<esi:include src="&apos;"/>
<esi:include src="&quot;"/>
}
} -start
server s2 {
rxreq
expect req.url == "/&"
txresp -body "1"
} -start
server s3 {
rxreq
expect req.url == "/<"
txresp -body "22"
} -start
server s4 {
rxreq
expect req.url == "/>"
txresp -body "333"
} -start
server s5 {
rxreq
expect req.url == {/'}
txresp -body "4444"
} -start
server s6 {
rxreq
expect req.url == {/"}
txresp -body "55555"
} -start
varnish v1 -arg "-p thread_pool_min=100" -arg "-p debug=+syncvsl,+processors" -vcl+backend {
import ${vmod_pesi};
sub vcl_recv {
return (pass);
}
sub vcl_backend_response {
if (bereq.url == "/") {
set beresp.do_esi = true;
}
}
sub vcl_backend_fetch {
if (bereq.url == "/") {
set bereq.backend = s1;
}
elsif (bereq.url == "/&") {
set bereq.backend = s2;
}
elsif (bereq.url == "/<") {
set bereq.backend = s3;
}
elsif (bereq.url == "/>") {
set bereq.backend = s4;
}
elsif (bereq.url == "/'") {
set bereq.backend = s5;
}
elsif (bereq.url == {"/""}) {
set bereq.backend = s6;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 32
} -run
varnishtest "Push corners in new ESI parser"
server s1 {
rxreq
txresp -nolen -hdr "Transfer-encoding: chunked"
chunked {<1></esi:comment foo><1>}
chunked {<2><esi:comment / ><esi:comment doo><2>}
chunked {<3><esi:remove foo="bar"></esi:remove><3>}
chunked {<4><esi:include src="foo"><esi:incl><4>}
chunked {<H1><esi:remove>}
chunkedlen 256
chunked {</esi:remove></H1>}
chunked {<H2><esi:remove>}
chunkedlen 65536
chunked {</esi:remove></H2>}
chunked {<esi:comment/>}
chunkedlen 256
chunked {<esi:comment/>}
chunkedlen 65536
chunked {<esi:comment/>}
chunked {<!--e}
delay .4
chunked {nd:comment>}
chunkedlen 0
} -start
# The included object gets served from a different backend.
# This is to avoid a race between when a backend connection
# gets put up for reuse because of background fetches in
# Varnish 4
server s2 {
rxreq
expect req.url == "bar/foo"
txresp -body {<INCL>}
} -start
varnish v1 -arg "-p thread_pool_min=100" -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_fetch {
if (bereq.url != "bar") {
set bereq.backend = s2;
}
}
sub vcl_backend_response {
if (bereq.url == "bar") {
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "param.set debug +esi_chop"
varnish v1 -cliok "param.set debug +syncvsl"
logexpect l1 -v v1 -g vxid {
expect * * Fetch_Body
expect 0 = ESI_xmlerror {^ERR after 3 ESI 1.0 </esi:comment> illegal end-tag$}
expect 0 = ESI_xmlerror {^ERR after 27 XML 1.0 '>' does not follow '/' in tag$}
expect 0 = ESI_xmlerror {^ERR after 43 ESI 1.0 <esi:comment> needs final '/'$}
expect 0 = ESI_xmlerror {^WARN after 107 ESI 1.0 <esi:include> lacks final '/'$}
expect 0 = ESI_xmlerror {^ERR after 130 ESI 1.0 <esi:bogus> element$}
expect 0 = ESI_xmlerror {^ERR after 131837 VEP ended inside a tag$}
expect 0 = BackendReuse
} -start
client c1 {
txreq -url bar
rxresp
expect resp.status == 200
expect resp.bodylen == 65856
} -run
logexpect l1 -wait
varnish v1 -expect esi_errors == 5
varnish v1 -expect esi_warnings == 1
varnishtest "ESI:remove"
server s1 {
rxreq
txresp -gzipbody {
<esi:remove>
This is a test: Unseen University
<esi:include src="trick question">
<!--esi XXX -->
</esi:remove>
<esX>This is a test: Hello world
}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
set beresp.do_gunzip = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "param.set http_gzip_support true"
logexpect l1 -v v1 -g vxid {
expect * * Fetch_Body
expect 0 = ESI_xmlerror {^ERR after 3 ESI 1.0 <esi:include> element nested in <esi:remove>$}
expect 0 = ESI_xmlerror {^ERR after 3 ESI 1.0 Nested <!--esi element in <esi:remove>$}
expect 0 = Gzip {^U}
expect 0 = BackendReuse
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 40
}
client c1 -run
varnish v1 -expect esi_errors == 2
logexpect l1 -wait
varnishtest "ESI ability to stitch gzip files together"
server s1 {
rxreq
txresp -body {
<esi:remove>
This is a test: Unseen University
<esi:include src="trick question">
<!--esi XXX -->
</esi:remove>
<esX>This is a test: Hello world
}
} -start
varnish v1 -syntax 4.0 -vcl+backend {
import ${vmod_pesi};
sub vcl_recv {
set req.esi = true;
}
sub vcl_backend_response {
set beresp.do_esi = true;
set beresp.do_gzip = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "param.set debug +esi_chop"
varnish v1 -cliok "param.set http_gzip_support true"
client c1 {
txreq -hdr "Accept-Encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
gunzip
expect resp.status == 200
expect resp.bodylen == 40
}
client c1 -run
varnish v1 -expect esi_errors == 2
varnishtest "ESI ability to stitch gzip files together"
server s1 {
rxreq
expect req.http.accept-encoding == gzip
txresp -gzipbody {
<esi:remove>
This is a test: Unseen University
<esi:include src="trick question">
<!--esi XXX -->
</esi:remove>
<esX>This is a test: Hello world
}
} -start
varnish v1 -syntax 4.0 -arg "-p thread_pool_stack=262144" -vcl+backend {
import ${vmod_pesi};
sub vcl_recv {
set req.esi = true;
}
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "param.set debug +esi_chop"
varnish v1 -cliok "param.set http_gzip_support true"
varnish v1 -cliok "param.set gzip_memlevel 1"
logexpect l1 -v v1 -g vxid {
expect * * Fetch_Body
expect 0 = ESI_xmlerror {^ERR after 24 ESI 1.0 <esi:include> element nested in <esi:remove>$}
expect 0 = ESI_xmlerror {^ERR after 24 ESI 1.0 Nested <!--esi element in <esi:remove>$}
expect 0 = Gzip {^G}
expect 0 = Gzip {^U}
expect 0 = BackendReuse
} -start
client c1 {
txreq -hdr "Accept-Encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
gunzip
expect resp.status == 200
expect resp.bodylen == 40
}
client c1 -run
varnish v1 -expect esi_errors == 2
logexpect l1 -wait
varnishtest "Include gzip'ed and ungzip'ed (ESI) objects in a gzip'ed ESI object"
server s1 {
rxreq
expect req.http.accept-encoding == gzip
txresp -gzipbody {
<html> 1
Before includes 2
<esi:include src="/foo"/> 3
Between includes 4
<esi:include src="/bar"/> 5
Between includes 6
<esi:include src="/fooz"/> 7
Between includes 8
<esi:include src="/barz"/> 9
After includes 10
}
} -start
server s2 {
rxreq
expect req.url == "/foo"
txresp -body {<h1>/////<h2>}
} -start
server s3 {
rxreq
expect req.url == "/bar"
txresp -body {*****}
} -start
server s4 {
rxreq
expect req.http.accept-encoding == gzip
expect req.url == "/fooz"
txresp -gzipbody {<h1>-----<h2>}
} -start
server s5 {
rxreq
expect req.http.accept-encoding == gzip
expect req.url == "/barz"
txresp -gzipbody {#####}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.http.filter1 = beresp.filters;
set beresp.do_esi = true;
set beresp.http.filter2 = beresp.filters;
}
sub vcl_backend_fetch {
if (bereq.url == "/") {
set bereq.backend = s1;
}
elsif (bereq.url == "/foo") {
set bereq.backend = s2;
}
elsif (bereq.url == "/bar") {
set bereq.backend = s3;
}
elsif (bereq.url == "/fooz") {
set bereq.backend = s4;
}
elsif (bereq.url == "/barz") {
set bereq.backend = s5;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "param.set http_gzip_support true"
varnish v1 -cliok "param.set debug +esi_chop"
varnish v1 -cliok "param.set feature +esi_disable_xml_check"
varnish v1 -cliok "param.set debug +syncvsl"
client c1 {
txreq -hdr "Accept-Encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
gunzip
expect resp.status == 200
expect resp.bodylen == 192
expect resp.body == {
<html> 1
Before includes 2
<h1>/////<h2> 3
Between includes 4
***** 5
Between includes 6
<h1>-----<h2> 7
Between includes 8
##### 9
After includes 10
}
}
client c1 -run
varnish v1 -expect esi_errors == 0
varnishtest "Test all 8 gzip stopbit residuals"
server s1 {
rxreq
expect req.http.accept-encoding == gzip
txresp -gzipbody {
<html> 1
Before includes 2
{<esi:include src="/bit0"/>} bit0 3
{<esi:include src="/bit1"/>} bit1 4
{<esi:include src="/bit2"/>} bit2 5
{<esi:include src="/bit3"/>} bit3 6
{<esi:include src="/bit4"/>} bit4 7
{<esi:include src="/bit5"/>} bit5 8
{<esi:include src="/bit6"/>} bit6 9
{<esi:include src="/bit7"/>} bit7 10
After includes 11
}
} -start
server s2 {
rxreq
expect req.url == "/bit0"
expect req.http.accept-encoding == gzip
txresp -gzipresidual 0 -gziplevel 9 -gzipbody {e04c8d0fd604c}
} -start
server s3 {
rxreq
expect req.url == "/bit1"
expect req.http.accept-encoding == gzip
txresp -gzipresidual 1 -gziplevel 9 -gzipbody {1ea86e6cf31bf4ec3d7a86}
} -start
server s4 {
rxreq
expect req.url == "/bit2"
expect req.http.accept-encoding == gzip
txresp -gzipresidual 2 -gziplevel 9 -gzipbody {10}
} -start
server s5 {
rxreq
expect req.url == "/bit3"
expect req.http.accept-encoding == gzip
txresp -gzipresidual 3 -gziplevel 9 -gzipbody {a5e2e2e1c2e2}
} -start
server s6 {
rxreq
expect req.url == "/bit4"
expect req.http.accept-encoding == gzip
txresp -gzipresidual 4 -gziplevel 9 -gzipbody {71c5d18ec5d5d1}
} -start
server s7 {
rxreq
expect req.url == "/bit5"
expect req.http.accept-encoding == gzip
txresp -gzipresidual 5 -gziplevel 9 -gzipbody {39886d28a6d2988}
} -start
server s8 {
rxreq
expect req.url == "/bit6"
expect req.http.accept-encoding == gzip
txresp -gzipresidual 6 -gziplevel 9 -gzipbody {80000}
} -start
server s9 {
rxreq
expect req.url == "/bit7"
expect req.http.accept-encoding == gzip
txresp -gzipresidual 7 -gziplevel 9 -gzipbody {386811868}
} -start
varnish v1 -arg "-p thread_pool_min=100" -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
if (bereq.url == "/") {
set beresp.do_esi = true;
}
}
sub vcl_backend_fetch {
if (bereq.url == "/") {
set bereq.backend = s1;
}
elsif (bereq.url == "/bit0") {
set bereq.backend = s2;
}
elsif (bereq.url == "/bit1") {
set bereq.backend = s3;
}
elsif (bereq.url == "/bit2") {
set bereq.backend = s4;
}
elsif (bereq.url == "/bit3") {
set bereq.backend = s5;
}
elsif (bereq.url == "/bit4") {
set bereq.backend = s6;
}
elsif (bereq.url == "/bit5") {
set bereq.backend = s7;
}
elsif (bereq.url == "/bit6") {
set bereq.backend = s8;
}
elsif (bereq.url == "/bit7") {
set bereq.backend = s9;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "param.set http_gzip_support true"
varnish v1 -cliok "param.set debug +esi_chop"
varnish v1 -cliok "param.set debug +syncvsl"
client c1 {
txreq -hdr "Accept-Encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
gunzip
expect resp.status == 200
expect resp.bodylen == 252
txreq
rxresp
expect resp.http.content-encoding == <undef>
expect resp.status == 200
expect resp.bodylen == 252
} -run
varnish v1 -expect esi_errors == 0
varnishtest "Test that esi+gzip correctly bypasses Vary: accept-encoding"
server s1 {
rxreq
expect req.http.accept-encoding == gzip
txresp -hdr "Vary: Accept-encoding" -gzipbody {FOO}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq -hdr "Accept-encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
expect resp.status == 200
gunzip
expect resp.bodylen == 3
txreq
rxresp
expect resp.http.content-encoding == <undef>
expect resp.status == 200
expect resp.bodylen == 3
} -run
varnishtest "Test esi-include + gzip edgecase with respect to gzip hdr"
server s1 {
rxreq
expect req.url == "/foo"
txresp -gzipbody {<h1>/////<h2>}
rxreq
expect req.url == "/1"
expect req.http.accept-encoding == gzip
txresp -gzipbody {B<esi:include src="/foo"/>A}
rxreq
expect req.url == "/2"
expect req.http.accept-encoding == gzip
txresp -gzipbody {B<esi:include src="/foo"/>}
rxreq
expect req.url == "/3"
expect req.http.accept-encoding == gzip
txresp -gzipbody {<esi:include src="/foo"/>A}
rxreq
expect req.url == "/4"
expect req.http.accept-encoding == gzip
txresp -gzipbody {<esi:include src="/foo"/>}
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
if (bereq.url != "/foo") {
set beresp.do_esi = true;
}
}
sub vcl_deliver {
if (req.url != "/foo" && resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
elsif (req.url != "/foo") {
set resp.filters = resp.filters + " pesi";
}
}
} -start
varnish v1 -cliok "param.set feature +esi_disable_xml_check"
varnish v1 -cliok "param.set debug +syncvsl,+workspace"
client c1 {
txreq -url /foo -hdr "Accept-Encoding: gzip"
rxresp
gunzip
expect resp.status == 200
expect resp.bodylen == 13
expect resp.body == {<h1>/////<h2>}
txreq -url /1 -hdr "Accept-Encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
gunzip
expect resp.status == 200
expect resp.bodylen == 15
expect resp.body == {B<h1>/////<h2>A}
txreq -url /2 -hdr "Accept-Encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
gunzip
expect resp.status == 200
expect resp.bodylen == 14
expect resp.body == {B<h1>/////<h2>}
txreq -url /3 -hdr "Accept-Encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
gunzip
expect resp.status == 200
expect resp.bodylen == 14
expect resp.body == {<h1>/////<h2>A}
txreq -url /4 -hdr "Accept-Encoding: gzip"
rxresp
expect resp.http.content-encoding == gzip
gunzip
expect resp.status == 200
expect resp.bodylen == 13
expect resp.body == {<h1>/////<h2>}
}
client c1 -run
varnish v1 -expect esi_errors == 0
varnishtest "test HEAD against ESI processing"
server s1 {
rxreq
expect req.url == "/1"
txresp -bodylen 1
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq -url "/1"
rxresp
expect resp.status == 200
expect resp.bodylen == 1
txreq -req "HEAD" -url "/1"
rxresp -no_obj
expect resp.status == 200
} -run
varnishtest "Test Vary with ESI and gzip/gunzip"
server s1 {
rxreq
expect req.url == "/foo"
txresp -body "foo"
rxreq
expect req.url == "/bar"
txresp -gzipbody "bar"
rxreq
expect req.url == "/baz"
txresp -body "baz"
rxreq
expect req.url == "/qux"
txresp -hdr "Vary: qux" -gzipbody "qux"
rxreq
expect req.url == "/fubar"
txresp -hdr "Vary: fubar, Accept-Encoding" -gzipbody "fubar"
rxreq
expect req.url == "/foobar"
txresp -gzipbody "foobar"
rxreq
expect req.url == "/foobaz"
txresp -hdr "Vary: foobaz" -gzipbody "foobaz"
rxreq
expect req.url == "/fooqux"
txresp -hdr "Vary: fooqux, Accept-Encoding" -gzipbody "fooqux"
} -start
varnish v1 -arg "-p feature=+esi_disable_xml_check" -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.http.filters1 = beresp.filters;
set beresp.do_esi = true;
if (bereq.url ~ "/baz") {
set beresp.do_gzip = true;
} elif (bereq.url ~ "/foo(bar|baz|qux)") {
set beresp.do_gunzip = true;
}
set beresp.http.filters2 = beresp.filters;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
# /foo
txreq -url /foo
rxresp
expect resp.body == "foo"
expect resp.http.Vary == <undef>
txreq -url /foo -hdr "Accept-Encoding: gzip"
rxresp
expect resp.body == "foo"
expect resp.http.Vary == <undef>
# /bar
txreq -url /bar
rxresp
expect resp.body == "bar"
expect resp.http.Vary == "Accept-Encoding"
txreq -url /bar -hdr "Accept-Encoding: gzip"
rxresp
expect resp.bodylen == 34
expect resp.http.Vary == "Accept-Encoding"
# /baz
txreq -url /baz
rxresp
expect resp.body == "baz"
expect resp.http.Vary == "Accept-Encoding"
txreq -url /baz -hdr "Accept-Encoding: gzip"
rxresp
expect resp.bodylen == 34
expect resp.http.Vary == "Accept-Encoding"
# /qux
txreq -url /qux
rxresp
expect resp.body == "qux"
expect resp.http.Vary == "qux, Accept-Encoding"
txreq -url /qux -hdr "Accept-Encoding: gzip"
rxresp
expect resp.bodylen == 34
expect resp.http.Vary == "qux, Accept-Encoding"
# /fubar
txreq -url /fubar
rxresp
expect resp.body == "fubar"
expect resp.http.Vary == "fubar, Accept-Encoding"
txreq -url /fubar -hdr "Accept-Encoding: gzip"
rxresp
expect resp.bodylen == 36
expect resp.http.Vary == "fubar, Accept-Encoding"
# /foobar
txreq -url /foobar
rxresp
expect resp.body == "foobar"
expect resp.http.Vary == <undef>
txreq -url /foobar -hdr "Accept-Encoding: gzip"
rxresp
expect resp.body == "foobar"
expect resp.http.Vary == <undef>
# /foobaz
txreq -url /foobaz
rxresp
expect resp.body == "foobaz"
expect resp.http.Vary == "foobaz"
txreq -url /foobaz -hdr "Accept-Encoding: gzip"
rxresp
expect resp.body == "foobaz"
expect resp.http.Vary == "foobaz"
# /fooqux
txreq -url /fooqux
rxresp
expect resp.body == "fooqux"
expect resp.http.Vary == "fooqux, Accept-Encoding"
txreq -url /fooqux -hdr "Accept-Encoding: gzip"
rxresp
expect resp.body == "fooqux"
expect resp.http.Vary == "fooqux, Accept-Encoding"
} -run
varnishtest "Test req_top.* in an ESI context"
varnish v1 -arg "-p feature=+esi_disable_xml_check" \
-errvcl {Variable is read only.} {
sub vcl_recv {
set req_top.url = "/foo";
}
}
server s1 {
rxreq
expect req.http.top-url == "/"
expect req.http.top-method == "GET"
expect req.http.top-proto == "HTTP/1.1"
expect req.http.top-foo == "bar"
txresp -body {
<html>
Before include
<esi:include src="/a"/>
<esi:include src="/b"/>
After include
</html>
}
} -start
server s2 {
rxreq
expect req.url == "/a1"
expect req.http.top-url == "/"
expect req.http.top-method == "GET"
expect req.http.top-proto == "HTTP/1.1"
expect req.http.top-foo == "bar"
txresp -body {
Included file
<esi:include src="/c"/>
}
} -start
server s3 {
rxreq
expect req.http.top-url == "/"
expect req.http.top-method == "GET"
expect req.http.top-proto == "HTTP/1.1"
expect req.http.top-foo == "bar"
expect req.url == "/c2"
txresp
} -start
server s4 {
rxreq
expect req.http.top-url == "/"
expect req.http.top-method == "GET"
expect req.http.top-proto == "HTTP/1.1"
expect req.http.top-foo == "bar"
expect req.url == "/b1"
txresp
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_recv {
if (req.esi_level > 0) {
set req.url = req.url + req.esi_level;
} else {
set req.http.foo = "bar";
}
set req.http.top-url = req_top.url;
set req.http.top-method = req_top.method;
set req.http.top-proto = req_top.proto;
set req.http.top-foo = req_top.http.foo;
}
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_backend_fetch {
if (bereq.url == "/") {
set bereq.backend = s1;
}
elsif (bereq.url == "/a1") {
set bereq.backend = s2;
}
elsif (bereq.url == "/c2") {
set bereq.backend = s3;
}
elsif (bereq.url == "/b1") {
set bereq.backend = s4;
}
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.bodylen == 81
} -run
varnish v1 -expect esi_errors == 0
varnishtest "ESI with http_gzip_support off"
server s1 {
rxreq
txresp -gzipbody {<esi:include src="/foo">}
rxreq
txresp -gzipbody "bar"
} -start
varnish v1 -arg "-p http_gzip_support=off -p debug=+processors" -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
gunzip
expect resp.body == "bar"
} -run
varnishtest "Exercise ESI+gzip in pass mode"
server s1 {
rxreq
txresp -gzipbody {<esi:include src="/foo"/>}
rxreq
txresp -gzipbody "foo"
} -start
varnish v1 -vcl+backend {
import ${vmod_pesi};
sub vcl_recv {
return (pass);
}
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq -hdr "Accept-Encoding: gzip"
rxresp
expect resp.status == 200
gunzip
expect resp.bodylen == 3
expect resp.body == "foo"
} -run
varnishtest "waitinglists at multiple ESI depths"
barrier b1 cond 2
server s1 {
rxreq
txresp -body {<esi:include src="someurl"/>}
rxreq
txresp -body {<esi:include src="otherurl"/>}
rxreq
barrier b1 sync
delay 1
txresp -body {DATA}
} -start
varnish v1 -arg "-p debug=+waitinglist" -vcl+backend {
import ${vmod_pesi};
sub vcl_backend_response {
set beresp.do_esi = true;
}
sub vcl_deliver {
if (resp.filters ~ "esi") {
set resp.filters = regsub(resp.filters, "\besi\b", "pesi");
}
else {
set resp.filters = resp.filters + " pesi";
}
}
} -start
client c1 {
txreq
rxresp
expect resp.body == "DATA"
} -start
client c2 {
txreq
barrier b1 sync
rxresp
expect resp.body == "DATA"
} -run
client c1 {
txreq
rxresp
expect resp.body == "DATA"
} -run
This diff is collapsed.
/*-
* Copyright (c) 2011 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL 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.
*/
VSTAILQ_HEAD(children, bytes_node);
struct bytes_node {
unsigned magic;
#define BYTES_NODE_MAGIC 0xe31edef3
struct children children;
VSTAILQ_ENTRY(bytes_node) sibling;
struct bytes_node *parent;
struct req *req;
const void *ptr;
struct storage *st;
ssize_t len;
enum vdp_action act;
unsigned pending:1;
unsigned include:1;
unsigned fini:1;
};
struct bytes_tree {
unsigned magic;
#define BYTES_TREE_MAGIC 0x49c59d46
pthread_mutex_t lock;
pthread_cond_t cond;
struct bytes_node *root;
struct bytes_node *front;
unsigned npending;
int retval;
};
struct ecx {
unsigned magic;
#define ECX_MAGIC 0x0b0f9163
ssize_t l;
int isgzip;
struct req *preq;
ssize_t l_crc;
uint32_t crc;
pthread_mutex_t
vdp_lock;
struct bytes_tree
*tree;
};
/*
* ecx is a global context for the entire ESI tree started at level 0.
* req_priv is local to each subrequest, allocated in req WS.
*/
struct req_priv {
unsigned magic;
#define REQ_PRIV_MAGIC 0xcab067da
struct worker *wrk;
struct bytes_node *parent;
struct bytes_node *node;
struct bytes_node *child;
const uint8_t *p;
const uint8_t *e;
int state;
int woken;
};
struct pesi {
unsigned magic;
#define PESI_MAGIC 0xa6ba54a0
struct ecx *ecx;
struct req_priv *priv;
};
#-
# Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
# All rights reserved
#
# Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
#
# See LICENSE
#
$Module pesi 3 "Varnish Delivery Processor for parallel ESI includes"
$Synopsis manual
SYNOPSIS
========
::
import pesi;
# VDP version
STRING pesi.version()
DESCRIPTION
===========
VDP pesi is a Varnish Delivery Processor for parallel Edge Side
Includes (ESI). ...
$Function STRING version()
Return the version string for this VDP.
Example::
std.log("Using VDP pesi version: " + pesi.version());
REQUIREMENTS
============
The VDP currently requires the Varnish master branch. ...
INSTALLATION
============
See `INSTALL.rst <INSTALL.rst>`_ in the source repository.
SEE ALSO
========
* varnishd(1)
* vcl(7)
* VMOD source repository: https://code.uplex.de/uplex-varnish/libvdp-pesi
$Event event
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment