Skip to content

Caddy as a CORS proxy

CORS is a common issue when you are developing a web application. It is a security mechanism that restricts the resources you can access from another domain.

The usual solution is to contact the API provider and ask them to add your domain to the CORS whitelist. However, this is not always possible. For example, if you are using a third-party API, you may not be able to contact the API provider.

In this article, I will show you how to use Caddy as a (local) CORS proxy to bypass CORS issue.

Quick start

Install Caddy

You can install Caddy in many ways, see the official documentation for more details.

On macOS, you can simply run:

Terminal window
brew install caddy

Create a config file (Caddyfile)

Let’s assume that remote API host is https://robwu.nl, and local proxy we named cors.local. The Caddyfile should look like this:

(cors) {
header {
Access-Control-Allow-Origin "{http.request.header.Origin}"
Access-Control-Allow-Credentials true
Access-Control-Allow-Methods *
Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
}
@options {
method OPTIONS
}
@not-options {
not method OPTIONS
}
}
cors.local {
log {
output file ./caddy-access.log
level ERROR
}
respond @options 204
reverse_proxy @not-options https://cors.local https://robwu.nl {
header_up Host {upstream_hostport}
header_up -X-Forwarded-Host
header_up -X-forwarded-For
header_up -X-forwarded-Proto
header_down -Access-Control-Allow-Origin
}
import cors
}

Don’t forget to replace robwu.nl with the actual domain name.

Configure DNS & TLS

In order to be able to use a local custom domain name and HTTPS, you need to configure DNS and TLS.

Add the following line to /etc/hosts:

Usually you need to use sudo to edit this file.

Terminal window
127.0.0.1 cors.local

You also need to trust the local CA in order to use HTTPS, run the following command:

Terminal window
caddy trust

Run Caddy

Run Caddy in foreground:

Terminal window
caddy run

or, run Caddy in background:

Terminal window
caddy start
caddy stop

Now you can access the proxied API with CORS headers.

Terminal window
curl -v -H "Origin: http://127.0.0.1:3000" https://cors.local/dump.php

Known issues

  1. Sometimes, the response from the proxied API has duplicate CORS headers.