/assets/caddy.jpg

How to set up a local reverse proxy using Caddy

Motivation

Imagine you’re happily working on a frontend while someone else works on an API you will have to call. He isn’t ready yet so the only choice you have is to mock it yourself and serve it on a different port.

Access to fetch at 'localhost:4000' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Now that’s a bummer, you cannot work like this and start getting angry, because you can’t reach the person responsible for this. To get rid of this error there are multiple ways though. One way is using Caddy as a reverse proxy. This is what I will show you shortly.

Install Caddy

At first you have to install Caddy to use it. The easiest way is to use a binary from its creators.

After installing it you should have caddy ready in your command line. To test this simply call caddy. And you should see some usage information.

Writing a caddy reverse proxy

For this we need a file called “Caddyfile”. This file serves as our server configuration:

json
:4001 {
reverse_proxy {
to localhost:4000
}
}

For a reverse proxy we need an endpoint our application can talk to. In our case this is “:4001”. Which translates to localhost:4001.

Caddy has an option called reverse_proxy. This is, obviously, what we want. In there we can use the keyword “to” to send our traffic to whatever adress we want to. Here we go with localhost:4000, our mocked up API.

This alone doesn’t solve our CORS problem though. To rid ourselves of this error we need to change some headers for our local browser to not block the response. The error message usually tells us what header we’re missing or have wrong. Above we had “Access-Control-Allow-Origin” in our CORS error message. This means that we need to allow this.

For the most part I go with the following caddy reverse proxy configuration to make sure, that whatever I am calling, I will get.

json
:4001 {
reverse_proxy {
to localhost:4000
header_down Access-Control-Allow-Headers *
header_down Access-Control-Expose-Headers *
}
header Access-Control-Allow-Origin *
header Access-Control-Allow-Methods *
}

That’s all there is to it. It’s possible to call external APIs as well. You just need to change the value behind your “to” directive, and you’re ready to go.