Skip to content

About

A Varnish VMOD that allows modification of a URL's query parameters.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

libvmod-querymodifier

This is a simple Varnish VMOD that allows modification of a URL's query parameters by including or excluding specified parameters and their values.

Usage

Inclusion

List the parameters that you would like to have remain in the URL. All other query parameters and their values will be removed.

import querymodifier;

set req.url = querymodifier.modifyparams(url=req.url, params="search,id", exclude_params=false);
# Or use the convenience function, `includeparams`.
set req.url = querymodifier.includeparams(url=req.url, params="search,id");

# Original URL: example.com/?search=name&ts=123456789&id=987654321
# Modified URL: example.com/?search=name&id=987654321

Opt-in parameter ordering

sortparams sorts all query parameters without filtering. includeparams_sorted keeps only the named parameters and sorts those. Both sort by raw, case-sensitive name. It preserves the order of repeated names (for example, tag=first&tag=second). It does not decode names or values, sort values, or change the existing includeparams behavior.

set req.url = querymodifier.sortparams(req.url);
# Original: /feed/?tag=first&page=2&format=json&tag=second
# Result:   /feed/?format=json&page=2&tag=first&tag=second

set req.url = querymodifier.includeparams_sorted(req.url, "page,format,tag");

# Original: /feed/?tag=first&page=2&format=json&tag=second&ts=123
# Result:   /feed/?format=json&page=2&tag=first&tag=second

Cache safety: enable this only for routes whose origin treats reordered parameters identically. A backend may interpret distinct parameters in order, or treat repeated names specially. The VMOD changes the forwarded URL as well as the cache key when used on req.url in vcl_recv.

Exclusion

List the parameters that you would like to have removed from the URL. All other query parameters and their values will remain.

import querymodifier;

set req.url = querymodifier.modifyparams(url=req.url, params="ts,v", exclude_params=true);
# Or use the convenience function, `excludeparams`.
set req.url = querymodifier.excludeparams(url=req.url, params="ts,v");

# Original URL: example.com/?search=name&ts=123456789&v=123456789&id=987654321
# Modified URL: example.com/?search=name&id=987654321

Remove all valid query parameters

Remove all query parameters by passing in an empty string.

import querymodifier;
set req.url = querymodifier.modifyparams(url=req.url, params="", exclude_params=true);
# Or use the convenience function, `excludeallparams`.
# set req.url = querymodifier.excludeallparams(url=req.url);

# Original URL: example.com/?search=name&ts=123456789&v=123456789&id=987654321
# Modified URL: example.com/

Remove all query string

Remove all of the query string, i.e. everything after, and including the ? regardless of if the are valid name=value query string parameters.

import querymodifier;
set req.url = querymodifier.removeallquerystring(url=req.url);

# Original URL: example.com/?123456
# Modified URL: example.com/

Additional

See the tests for more parameter edge cases.

Building

The VTC suite and generated differential tests run against Varnish 7.5–8.0 on Alpine and Varnish 9.1 on Debian in CI.

./bootstrap
make
make check # optionally run tests, recommended.
sudo make install

# Or build and test against Varnish 8.0.2 with Docker:
docker compose build
docker compose run --rm test

# Build and test against Varnish 9.1 (Debian image):
docker build -f Dockerfile.debian -t querymodifier-test:9.1 .
docker run --rm --entrypoint /bin/sh querymodifier-test:9.1 \
  -c 'make check && python3 test_querymodifier_generated.py --seed 2026 --cases 200'

Contributing

Fork, code, and PR! See build instructions above.

I'm happy to review any PRs. Any bug reports are also welcome.

Generated differential tests

After ./bootstrap && ./configure && make, run:

python3 test_querymodifier_generated.py --seed 2026 --cases 200

This generates deterministic requests and compares the built VMOD's forwarded URL against an independent Python model through varnishtest. It exercises all filtering modes and both sorting functions, with duplicate names, empty values, encoded names, and extra separators. Change --seed to explore other cases; failures save a reproducible querymodifier-failure-<seed>-<batch>.vtc. This is generated testing, not a replay of production traffic or a proof that sorting is safe for a particular origin's parameter semantics.

Debugging

ASan

The module can also be built with AddressSanitizer support.

It is recommended that when developing on the module, you build with AddressSanitizer support enabled in order to help identify any memory issues with the VMOD.

In order to build the module with this enabled, run the bootstrap script with --enable-asan.

./bootstrap --enable-asan

There are also some scripts in the debug directory to assist. Navigate to the debug directory and run docker compose up --build in order to build the module with ASan support as well as with a backend nginx to field example requests.

Note: Do not use the module built with ASan support in production. This is meant for development purposes only.

gdb

gdb is also included in the debug Dockerfile for your convenience.

  • After you've brought up Docker Compose, exec into the Varnish container.
docker compose exec varnish
  • Attach gdb to the Varnish child process. You can either get the PID with ps or Varnish will print the child PID to the console like varnish-1 | Debug: Child (31) Started.
(gdb) attach 31
  • Set a breakpoint, for example on the vmod_modifyparams function. A .gdbinit file is included in the Docker container to instruct gdb where to find the VMOD shared libraries.
(gdb) b vmod_modifyparams
Breakpoint 1 at 0xffff7e0b14cc: file vmod_querymodifier.c, line 219.
  • Send a request to http://localhost:8080 that exercises the VMOD.

  • Continue the debugger and then use gdb as you normally would.

(gdb) c
Continuing.
[Switching to Thread 0xffff855cf140 (LWP 372)]

Thread 101 "cache-worker" hit Breakpoint 1, vmod_modifyparams (ctx=0xffff855cd9b8, uri=0xffff79a3d8ac "/?blah=1&ts=1", params_in=0xffff7e0e7610 "ts,v,cacheFix,date",
    exclude_params=1) at vmod_querymodifier.c:219
219         CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);

Acknowledgements

Alternatives

Some alternatives to this VMOD are:

License

Apache 2.0

About

A Varnish VMOD that allows modification of a URL's query parameters.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages