1. The problem I’m having:
I have a (flask) server and was trying to implement basic authentification for some resources using caddy.
For now, I’m just trying to make it work locally.
Im using Caddy-Docker-Proxy to generate the Caddyfile from docker labels.
The route I’m having problems with is /app/test/
It is a POST request that Im trying to send from the frontend (browser). Precising browser because it works from postman, since it doesnt need preflight.
It send a preflight OPTIONS request :
curl "http://localhost:8008/app/test" -X \
OPTIONS -H \
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0" -H \
"Accept: */*" -H \
"Accept-Language: en-CA,en-US;q=0.7,en;q=0.3" -H \
"Accept-Encoding: gzip, deflate, br" -H \
"Access-Control-Request-Method: POST" -H \
"Access-Control-Request-Headers: authorization,content-type" -H \
"Referer: http://localhost:8080/" -H \
"Origin: http://localhost:8080" -H \
"Connection: keep-alive" -H \
"Sec-Fetch-Dest: empty" -H \
"Sec-Fetch-Mode: cors" -H \
"Sec-Fetch-Site: same-site"
then this POST request :
curl "http://localhost:8008/app/test" -X \
POST -H \
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0" -H \
"Accept: application/json, text/plain, */*" -H \
"Accept-Language: en-CA,en-US;q=0.7,en;q=0.3" -H \
"Accept-Encoding: gzip, deflate, br" -H \
"Content-Type: application/json;charset=utf-8" -H \
"Authorization: Basic YWRtaW46aGFzaA==" -H \
"Content-Length: 6237" -H \
"Origin: http://localhost:8080" -H \
"Connection: keep-alive" -H \
"Referer: http://localhost:8080/" -H \
"Sec-Fetch-Dest: empty" -H \
"Sec-Fetch-Mode: cors" -H \
"Sec-Fetch-Site: same-site"
I tried running it using cors-anywhere while running my server through ngrok and was able to make it work.
curl "https://cors-anywhere.herokuapp.com/http://<ngrok-sub-domain>.ngrok-free.app/app/test" -X \
OPTIONS -H \
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/112.0" -H \
"Accept: */*" -H \
"Accept-Language: en-CA,en-US;q=0.7,en;q=0.3" -H \
"Accept-Encoding: gzip, deflate, br" -H \
"Access-Control-Request-Method: POST" -H \
"Access-Control-Request-Headers: authorization,content-type" -H \
"Referer: http://localhost:8080/" -H \
"Origin: http://localhost:8080" -H \
"Connection: keep-alive" -H \
"Sec-Fetch-Dest: empty" -H \
"Sec-Fetch-Mode: cors" -H \
"Sec-Fetch-Site: cross-site"
My question is can I set up Caddy to accept my resquest and how?
2. Error messages and/or full log output:
response headers from the OPTIONS request :
HTTP/1.1 401 Unauthorized
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: authorization,content-type
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: access-control-allow-origin,access-control-allow-methods,access-control-allow-headers
Connection: keep-alive
Server: Caddy
Www-Authenticate: Basic realm="restricted"
Date: Thu, 27 Apr 2023 20:04:48 GMT
Content-Length: 0
and from the OPTIONS request using cors-anywhere, which worked:
HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: authorization,content-type
Access-Control-Expose-Headers: access-control-allow-origin,access-control-allow-methods,access-control-allow-headers
Date: Thu, 27 Apr 2023 19:09:54 GMT
Transfer-Encoding: chunked
Via: 1.1 vegur
I see that the Access-Control-Allow-Methods
Header doesnt appear in the Unauthorized version. But i added it in my caddy config.
3. Caddy version:
v2.6.4
4. How I installed and ran Caddy:
a. System environment:
Docker
b. Command:
docker compose -f docker-compose.yaml up
c. Service/unit/compose file:
docker-compose.yaml :
version: '3.9'
services:
caddy:
image: lucaslorentz/caddy-docker-proxy:ci-alpine
ports:
- 80:80
- 443:443
- 8008:8008
environment:
- CADDY_INGRESS_NETWORKS=caddy #listen to caddy network
networks:
- caddy
volumes:
- /var/run/docker.sock:/var/run/docker.sock #access docker daemon
- caddy_data:/data #store caddy data
restart: unless-stopped
server:
container_name: dev-server
build:
context: .
dockerfile: Dockerfile
volumes:
- ./data:/data/
- .:/app/
networks:
- caddy
env_file:
- .env
entrypoint: ["gunicorn", "--reload", "main:app", "-c", "gunicorn.conf.py"]
environment:
- PORT=8008
labels:
caddy: :8008
caddy.route_0: /app/*
caddy.route_0.reverse_proxy: server:8008
caddy.route_1: /app/test
caddy.route_1.basicauth.admin: hash
caddy.header: /app/test
caddy.header.Access-Control-Allow-Origin: "*"
caddy.header.Access-Control-Allow-Methods: 'GET, POST, PUT, DELETE, OPTIONS'
caddy.header.Access-Control-Allow-Headers: 'authorization,content-type'
caddy.header.Access-Control-Expose-Headers: 'access-control-allow-origin,access-control-allow-methods,access-control-allow-headers'
caddy.header.Access-Control-Allow-Credentials: true
caddy.header.Connection: keep-alive
volumes:
caddy_data: {}
networks:
caddy:
external: true
d. My complete Caddy config:
The caddyfile is generated from labels in docker-compose file but here’s what the logs give me (once formatted) :
:8008 {
header /app/test {
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers authorization,content-type
Access-Control-Allow-Methods GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin *
Access-Control-Expose-Headers access-control-allow-origin,access-control-allow-methods,access-control-allow-headers
Connection keep-alive
}
route /app/* {
reverse_proxy server:8008
}
route /app/test {
basicauth {
admin hash
}
}
}
as you can see, I added response header to my protected route; they all appear, except for Access-Control-Allow-Methods.
5. Links to relevant resources:
Caddy Docker Proxy
cors-anywhere