Reverse proxy doesn't work with query parameters

1. Output of caddy version:

v2.5.2 h1:eCJdLyEyAGzuQTa5Mh3gETnYWDClo1LjtQm2q9RNZrs=

2. How I run Caddy:

a. System environment:

Ubuntu 22.04 LTS (GNU/Linux 5.15.0-1019-aws x86_64

b. Command:

sudo caddy start

c. Service/unit/compose file:

Paste full file contents here.
Make sure backticks stay on their own lines,
and the post looks nice in the preview pane. -->

d. My complete Caddy config:

example.com {
        handle /api/* {
                reverse_proxy localhost:3000
        }

        handle /auth/* {
                reverse_proxy localhost:3000
        }

        handle {
                root * /home/ubuntu/source/liverepo/dist/production-chart-front-end
                try_files {path} {path}/ /index.html
                file_server
        }
}

3. The problem I’m having:

This is an Angular application with a node backend. The issue I face is when I attempt to navigate to the reverse proxy for the back in, the path isn’t matched when there are query parameters. If I go to https://example.com/auth/code?response_type=code&… caddy directs to the Angular application, but if I go to https://example.com/auth/code the backend application receives the request.

I know I’m not supposed to redact the domain, but it isn’t mine to choose to disclose. There are also 6 query parameters that are passed to this route in case that matters.

This issue only occurs in production, in local dev the requests also use a proxy and they work.

4. Error messages and/or full log output:

Sep 19 13:16:52 ip-172-31-41-174 systemd[1]: Starting Caddy...
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: caddy.HomeDir=/var/lib/caddy
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: caddy.AppDataDir=/var/lib/caddy/.local/share/caddy
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: caddy.AppConfigDir=/var/lib/caddy/.config/caddy
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: caddy.ConfigAutosavePath=/var/lib/caddy/.config/caddy/autosave.json
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: caddy.Version=v2.5.2 h1:eCJdLyEyAGzuQTa5Mh3gETnYWDClo1LjtQm2q9RNZrs=
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: runtime.GOOS=linux
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: runtime.GOARCH=amd64
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: runtime.Compiler=gc
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: runtime.NumCPU=1
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: runtime.GOMAXPROCS=1
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: runtime.Version=go1.18.3
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: os.Getwd=/
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: LANG=C.UTF-8
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: NOTIFY_SOCKET=/run/systemd/notify
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: HOME=/var/lib/caddy
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: LOGNAME=caddy
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: USER=caddy
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: INVOCATION_ID=eea81cf308264aa9ac423b1713f6bc72
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: JOURNAL_STREAM=8:17097
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: SYSTEMD_EXEC_PID=438
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: {"level":"info","ts":1663593413.1497974,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":""}
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: {"level":"info","ts":1663593413.1950748,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["//127.0.0.1:2019","//localhost:2019","//[::1]:2019"]}
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: {"level":"warn","ts":1663593413.1958282,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server","server_name":"srv0","http_port":80}
Sep 19 13:16:53 ip-172-31-41-174 caddy[438]: {"level":"info","ts":1663593413.2093222,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0001acd90"}

5. What I already tried:

At first I thought this was an Angular issue, and tried some things that I don’t believe are relevant. Then I realized that the problem had to be with the url specifically being requested. So I tried changing the Caddyfile in a number of different ways as it seems you can do the same thing in multiple fashions. Only when I tried navigating to the url without the parameters did I realize that was the root of the issue, and I don’t see anything in the docs that looks to speak to this issue.

6. Links to relevant resources:

With the config you posted, that should be impossible.

How do you know which one is responding? Make a request with curl -v with and without a query, and show us what it looks like.

You can turn on the debug global option which will show more details in your logs, which should reveal what’s happening for each request. Add this at the top of your Caddyfile:

{
	debug
}

I erased everything in the caddy file and just started with having everything go through the reverse proxy then added the handles one by one and it is working now. I’m not sure what I could have possibly done wrong. I had also cleared cache in browser prior to adjusting the caddy file this time, so it may have been a browser issue. Which is probably why you all prefer to use curl and take the browser out of the equation.

2 Likes