Routing and rewrites

Route by path

Send API requests to one backend while returning a separate response for other paths.

10 minute lesson

~~~

One proxy usually fronts more than one thing. The classic split: API requests go to an application server, everything else gets the frontend. Request matchers choose which handler receives traffic.

Add a path matcher

Update the Caddyfile:

http://127.0.0.1:8080 {
  handle /api/* {
    reverse_proxy 127.0.0.1:4001
  }

  handle {
    respond "frontend\n"
  }
}

Each handle block is mutually exclusive — the first matching one wins, and Caddy orders them by matcher specificity. The /api/* matcher catches paths under /api/. The bare handle with no matcher is the fallback for everything else.

Reload and test each route:

curl http://127.0.0.1:8080/api/users
# {"port":4001,"path":"/api/users"}

curl http://127.0.0.1:8080/
# frontend

The API request reached the backend, and note what the backend saw: the full path /api/users, unchanged. handle routes the request but doesn’t modify it. The next lesson covers stripping the prefix when the backend expects clean paths.

Test the edges

Now the requests people forget to try:

curl http://127.0.0.1:8080/api
# frontend

curl http://127.0.0.1:8080/api/
# {"port":4001,"path":"/api/"}

/api without a trailing slash does not match /api/* — the pattern requires the slash. It falls through to the frontend handler. Whether that’s a bug or the behavior you want depends on your API contract, but you should decide it, not discover it. If you want both, use two matchers: handle /api /api/*.

Notice that matcher details affect edge paths such as /api without a trailing slash. These boundaries are where routing bugs live.

My advice is to write tests for near matches: the prefix without a slash, a path that shares a prefix like /apiv2, an encoded slash. A broad route can accidentally expose an internal handler, and you find out when someone else does.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →