nginx and Caddy request router
Paste an nginx config or a Caddyfile and a request, and step through what the server does with it — which server block and location win and why, rewrites, try_files, if, alias vs root, the proxy_pass trailing-slash rules, add_header inheritance — ending in the file served, the upstream URL or the redirect. Plus a table of requests checked against expected outcomes.
Added
How to use it
Most nginx surprises come down to one question: for this request, which block runs, and what
does it do with the URI? This tool answers it without a server. Paste a config, type a request, and
it walks the request through the same steps nginx takes — choosing the server block, searching the
locations, running rewrites and if, checking files for try_files and index, and handing the
request to a file, a FastCGI server or an upstream — showing each decision and the line of the
config that made it. Caddyfiles work too.
It simulates; it doesn’t build or lint. To write a config from a form, or have every line of one explained and checked, use the server config builders.
How to use it
Trace a request has the config on one side and the request on the other.
-
Pick an example from the list, or paste your own
nginx.conf(anhttp { }block, or just theserver { }blocks) or Caddyfile. Auto tells them apart; the switch beside it forces one. -
List the files on disk that matter —
try_files,index,-ftests and static files look them up. A path ending in/is a directory. With an empty list every path counts as a file. -
Type the request: method, full URL (the Host header comes from it), extra headers, and the client address if
allow/denymatter.
The outcome appears at once: the status, and the file served, the upstream URL with the headers
nginx sends it, the FastCGI SCRIPT_FILENAME, or the redirect target; then the response headers
that add_header adds. Below it is every step. Step through goes one step at a time and lights up
the config lines that step used; for the location search it lists every location that was
considered and why each lost. Tap any step to jump to it.
Test table runs many requests at once against expected outcomes — one per line,
GET https://app.example.com/api/users | proxy http://api_backend/users. An expectation is one or
more facts separated by ;: a status (404), file /srv/site/about.html,
proxy http://up/path, 301 https://example.com/, location /api/, script /var/www/index.php,
body ok, or header X-Frame-Options: DENY. Each row shows what actually happens and whether it
matches; tap a request to trace it. It is a quick regression check before you change a location.
The rules summarises nginx’s and Caddy’s matching order, the proxy_pass slash table and the
inheritance rules.
The examples: a single-page app with an API proxy, PHP-FPM with a front controller, a static site with caching and an alias, multi-tenant wildcard hosts with a map, the location example from the nginx documentation, a page of classic gotchas, and the same jobs in a Caddyfile. Each comes with a test table.
What it models
nginx, following its documentation and source: server selection by port, then server_name
(exact, longest leading wildcard, longest trailing wildcard, first regex, default_server); URI
normalisation; server-level rewrites; the location search (=, longest prefix, ^~, nested
locations, regexes in order, the automatic 301 for /api → /api/); rewrite with last,
break, redirect and permanent and how arguments are kept or dropped; return; set; map;
if with every condition type, and the way a matching if replaces the location’s configuration
("If is Evil"); allow/deny; internal; try_files; index; root and alias (including the
off-by-slash traversal); autoindex; error_page; proxy_pass with and without a URI part, with
variables, after rewrite … break, with upstream blocks and proxy_set_header; fastcgi_pass
with fastcgi_param and fastcgi_split_path_info; add_header and expires. include of the
stock files (fastcgi_params, fastcgi.conf, snippets/fastcgi-php.conf, proxy_params) works;
other includes need their contents pasted in.
Caddy: site selection and automatic HTTPS redirects, snippets and import, named and inline
matchers (path, path_regexp, host, method, header, query, remote_ip, not, file),
the directive order and same-directive sorting, handle, handle_path, route, rewrite, uri,
try_files, redir, respond, error, basic_auth, header, reverse_proxy, php_fastcgi,
file_server and handle_errors.
Not modelled: the IP address part of listen, TLS and SNI, what an upstream answers (a proxied
request is assumed to get 200), caching, rate limits (the server config builders simulate
limit_req), sub_filter, Lua and other third-party modules, and Caddy’s CEL expression matchers.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.