Chris Collins

Tools · network

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.

  1. Pick an example from the list, or paste your own nginx.conf (an http { } block, or just the server { } blocks) or Caddyfile. Auto tells them apart; the switch beside it forces one.

  2. List the files on disk that matter — try_files, index, -f tests and static files look them up. A path ending in / is a directory. With an empty list every path counts as a file.

  3. Type the request: method, full URL (the Host header comes from it), extra headers, and the client address if allow/deny matter.

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.

Privacy

Everything runs in your browser. Configs, file lists and requests are kept in this browser’s local storage so they are there next time; nothing is sent anywhere. Share link puts the config and requests into the link itself.

Runs entirely in your browser; nothing you type leaves this page.