Changes in Varnish Cache 9.1

For information about updating your current Varnish deployment to the new version, see Upgrading to Varnish 9.1.

A more detailed and technical account of changes in Varnish Cache, with links to issues that have been fixed and pull requests that have been merged, may be found in the change log.

varnishd

Parameters

  • varnishd -x parameter-json has been added to output the parameter documentation in JSON format. (4378)

  • varnishd now checks for an already running instance before modifying the working directory. -C should not be used together with -n.

  • The esi_ignore_https, esi_disable_xml_check, esi_ignore_other_elements and esi_remove_bom feature flags can now be overridden per response with the new beresp.esi_ignore_https, beresp.esi_disable_xml_check, beresp.esi_ignore_other_elements and beresp.esi_remove_bom variables. (4518)

  • Object references are now retained until the end of a client task, such that object attributes accessed from VCL remain valid across restarts without being copied to the workspace. Consequently, max_restarts and max_retries gained upper limits of 32766 and 65534, respectively. (4269)

  • storage.Synth, as configured through the -sSynth=... varnishd startup parameter is now the default resp.storage used for synthetic responses created in vcl_synth{}. (4492)

  • The lock witness facility is now disabled at compile time by default and needs to be enabled with the --enable-witness configure option. (4574). Note that even if enabled at compile time, it still also needs to be activated at runtime using param.set debug +witness as before.

Protocol framing fixes:

HTTP/1 message framing checks have been tightened (4581):

  • Backend responses with invalid body framing now fail the fetch.
  • Multiple Transfer-Encoding fields are now considered as a whole, such that duplicate chunked codings are refused.
  • Multiple Content-Length fields and values are now accepted if they all agree (leading zeroes are tolerated) and consolidated into a single canonical header, any disagreement is refused.
  • Transfer-Encoding on an HTTP/1.0 request is now refused. For HTTP/1.0 backend responses, the new vcl_beresp_http10 built-in subroutine abandons the fetch, which VCL can override.
  • The backend connection is now closed when the range check of a response fails, to avoid reusing a connection with an unread body.
  • An existing, correct Connection response header is no longer overwritten when closing: other tokens are preserved and close or keep-alive are added as needed. If a Connection was not present, or was incorrect, we create a new, correct one. (4498)
  • HTTP header parsing now only accepts SP and TAB as optional white space. (4583)

  • Range processing is now only applied to GET requests as mandated by RFC 9110, and the builtin VCL removes the Range header from other requests. (4533)

  • Fetching of HTTP/1.1 chunked bodies has been optimized: Chunked body fetches now use readahead instead of the previous single byte read operations which were wasteful and inefficient. (4508)

  • Improved support for delivery processors (VDPs) changing the length of a request body: Content-Length is rewritten or removed and chunked encoding is used as required.

  • The range VDP now removes any existing Content-Range header to avoid duplicates.

  • A deficiency in HTTP/2 request parsing has been fixed by properly comparing pseudo-header names instead of doing a prefix match. (VSV00019)

  • Handling of Connection: close has been made more consistent if the Connection header also contains other tokens. (4495)

Ban improvements

  • The obj.hfm, obj.hfp, and obj.uncacheable ban variables have been added to allow banning hit-for-miss and hit-for-pass and uncachable (both) objects. (4532)

Synth storage engine

  • A new synth storage engine has been added, which avoids copying data for synthetic response bodies by referencing the constituents directly. It is used by default as the Synth storage. (4365)

VCC fixes

  • VCC now refuses empty quoted header names as in req.http."", which could previously result in a C compiler error. (4577)
  • Fixed a VCC bug where include of a BLOB literal file could fail with a spurious "Missing colon" error.
  • make install now honours DESTDIR when creating VARNISH_STATE_DIR. (4512)

  • During build, the new configure option --with-statedir now allows to set the VARNISH_STATE_DIR directly, which is the default for VARNISH_DEFAULT_N, which, in turn, is the default for the -n argument to varnishd and varnish{log,ncsa,hist,top}. (4483)

  • The default for VARNISH_STATE_DIR has been changed back to ${localstatedir}/varnish. (4483)

Other fixes & improvements

  • Worker pool shutdown has been reworked: Acceptor tasks and waiters now terminate promptly, dying pools no longer starve queued tasks and worker threads are waited for before a pool is dismantled. The worker process now ignores SIGUSR1, which is used internally to interrupt blocking accept(2) calls. (4538).

  • PROXY v2 parsing now validates the length of the CRC32C TLV, avoiding an out-of-bounds read. (4560)

  • Fixed the alphabet of the built-in base64 encoder used when converting BLOBs to strings. (4522)

  • Starting sub-processes has become faster on systems with a high file descriptor limit by only closing file descriptors which are actually open. (3891)

  • A previous fix regarding false/true defaults for VMOD function BOOL arguments was incomplete and has been corrected. (4452)

  • Fixed a manager abort when the worker process failed to cool a VCL being discarded, which also prevented auto_restart from taking effect.

    (4563)

  • Fixed a panic when a delivery processor (VDP) failed to initialize before allocating the private pointer. This changes the VDP api in that a VDP that returns non-zero from its .init() callback will no longer see its .fini() method called, which implies that all failure scenarios during .init() must clean up any allocated data before returning. (4539)

  • Fixed a bug in the poll waiter which could delay handling of events whose deadline had already passed. (4561)

  • When the worker process terminates, varnishd now reports resource usage in the Child dies usr=%f sys=%f message, usr and sys being the "user" and "system" time used as reported by getrusage().

  • Worker pools are now shut down during a worker process stop as initiated by varnishadm stop. This improves shutdown speed by releasing VCL references earlier.

    The behavior now matches that with the drop_pools experimental parameter set, which has been removed.

  • Failed objects no longer get added to LRU. (4428)

  • IPv4 compatible and IPv4 mapped IPv6 addresses now get rewritten to IPv4 addresses, which is relevant for ACL matches in particular. (4474)

  • A workspace buffer overflow vulnerability was fixed in the .upper() and .lower() VCL string type methods. (VSV00020)

Changes to VCL

  • The req0.method, req0.url, req0.proto and req0.http.* variables have been added for read access to the request almost exactly as it was originally received. In vrt.h, struct vrt_ctx gained the http_req0 member and enum gethdr_e gained HDR_REQ0.

  • Setting req.max_age = 0s now forces a cache miss with request coalescing, where it previously had no effect. (4041)

  • The HTTP QUERY method has been added to the well known request methods and is passed by default in the builtin VCL. (4531)

  • The new resp.esi_include_onerror variable allows to override the esi_include_onerror feature flag in vcl_deliver {}. (4054)

  • The synthetic() VCL action has been removed. Since Varnish Cache 5.0.0, body data can be created by setting beresp.body in vcl_backend_error {} and by setting resp.body in vcl_synth {}, and these continue to be available as the one way to create body data, as in these examples:

    • set resp.body = "string" + " more strings";
    • set resp.body += " appending even " + "more strings";
    • set resp.body = :blob:;
    • set resp.body += :blobappend:;

    These examples equally work on beresp.body in vcl_backend_error {}.

    The direct replacement for synthetic(<string>); is set resp.body += <string>; in vcl_synth {} and set beresp.body += <string>; in vcl_backend_error {}.

    The only difference in behavior is that synthetic(<nullstring>) would create the string (null) for <nullstring> being a NULL pointer internally, while set resp.body = <nullstring> creates the empty string "" and set resp.body += <nullstring> is a NOOP. (4503)

  • A new resp.storage VCL variable available from vcl_synth{} was added to select which storage the synth response body gets created on. (4358)

VMODs

vmod_std

  • Fixed a bug causing std.fileread() to panic when pointed at a 0-length file. (4557)

  • The argument to std.rollback() is now obsolete and ignored, the appropriate headers to be rolled back are now inferred from the call site. This also fixes a panic when resp or beresp was passed. (4566)

  • std.collect_all() has been added to combine all multiple headers of req, resp, bereq or beresp according to the HTTP RFCs: Set-Cookie is not combined, Cookie is combined with "; " and all other headers with ", ".

  • Header combining by std.collect() is now visible in the log.

  • std.strftime() now errors out it given a NULL format string. (4551)

  • Fixed a potential buffer over-read when parsing HTTP dates. (4554)

  • std.getenv() gained an optional fallback argument which is returned if the environment variable is not set. (4527)

vmod_math

  • math.strfromd(): format strings cannot contain extra data after the formatter. (4547)

vmod_blob

  • blob.transcode() now limits its stack usage by decoding large inputs piecemeal, avoiding a potential stack overflow.

  • blob.sub() now properly errors out if given a negative offset or size. (4549)

varnishlog & varnishstat

  • HttpGarbage log records now contain the offending data rather than just the request method.
  • HTTP/1 messages rejected for invalid body framing now get a BogoHeader log record naming the offending field.
  • Malformed lines in the VSM _.index file are now reported with a meaningful diagnostic instead of a bare assertion failure in VSM readers like varnishstat and varnishlog. (4569)
  • Counters for backend connection closes have been added: MAIN.backend_closed, MAIN.backend_closed_err and the MAIN.bc_* close reason counters that are a subset of sc_* session counters, as well as the equivalent per-backend VBE.*.closed, VBE.*.closed_err and close reason counters. (4337)
  • varnish{log,ncsa,hist,top} all gained the -0 dry-run argument that allows validating command line arguments before running them for real. (4493)

varnishadm

  • varnishadm now only uses libedit if both stdin and stdout are terminals.

  • The -x workdir option has been added to varnishadm to print the default work directory and exit. This is useful for tools that need to discover the VSM location in most setups. (4494)

  • tls.cert.list -j no longer returns an empty body with a 200 status when the child process is not running; it now returns an empty JSON array ([]).

varnishtest & vtest

  • varnishtest gained the VTEST_VARNISH_VCL_PREPEND environment variable to inject VCL code into all VCL loaded by varnish instances.

  • Varnish can now be built without the vtest2 git submodule and instead with an externally provided vtest program, as installed by running DESTDIR=/prefix make install in the Vtest2 repository https://code.vinyl-cache.org/vtest/VTest2 (#4398)

    The Varnish specific test commands varnish, logexpect and vsm have been moved to a vtest extension.

    For a build with the submodule, both a varnishtest program and vtest symlink continue to be built and installed as monolithic binaries which always include the extension.

    For a build without the submodule (with an external vtest program), a varnishtest wrapper is built, which sets up the right command line arguments and calls vtest.

    This is done to hopefully achieve a smooth transition, until we plan to eventually remove varnishtest and wholly replace it with vtest -E libvtest_ext_varnish.so (or the equivalent for automake), which is what the varnishtest wrapper already calls.

  • The following vtest feature tests have been moved to vcache_builtwith in the Varnish Cache VTest extension: 64bit, persistent_storage, coverage, asan, msan, tsan, ubsan, sanitizer, workspace_emulator and witness.

  • In the Varnish Cache VTest extension, the log output of SLT_F_UNSAFE log records has been changed to escape unprintable characters as \xFF, FF being the hexadecimal representation of the respective character.

  • A simple perl script tools/vtclog2logexp.sh has been added to help create logexp commands for vtest from its output.

Changes for developers and VMOD authors

  • We added infrastructure to easily build VMODs for multiple Varnish Cache based projects. Besides changing how VMOD builds discover such projects and configure themselves appropriately, we also added the vcache command to the Varnish Cache VTest extension. (#4537)

    With the same goal, cache/cache_vinyld.h has been renamed to cache/cache_int.h.

    See Supporting multiple Varnish Cache based projects for details on how to migrate.

    We also fixed the maxmimum version check in the VCACHE_REQUIRE macro from inclusive to exclusive, matching VARNISH_PREREQ's original documented behavior. So VCACHE_REQUIRE([varnish], [9.0.0], [9.1.0]) no longer implements "9.0.x OR 9.1.0" but rather "9.0.x".

  • The varnish-legacy.m4 macro collection for VMOD builds has been removed. VMODs should migrate to using the macros from varnish.m4.

  • The LBODY_SET and LBODY_ADD compatibility defines and the struct VCL_conf and struct VSC_main declarations have been removed from vrt.h. struct vmod_data has moved to vmod_abi.h.

    The debug storage engine lost all parameters except dinit and dopen, as these are replaced by the above now.

    Likewise, the debug.fragfetch helper parameter has been removed, vtc.storage_frag() fills its place.

  • VTIM_format() no longer uses gmtime_r(), which improves performance.

  • The Tstrcmp() macro has been removed from vdef.h, Tstreq() is to be used for equality checks.

  • The functions VRT_synth_strands(), VRT_synth_blob(), VRT_synth_page() and VRT_Stv() have been removed from the runtime.

  • STV_BanExport() no longer holds the ban_mtx (3853)