I'm testing a local Icecast server on Ubuntu, using Traefik 1.7 in Docker containers.
When manually going to a page on a subdomain, all CORS headers are set:
But accessing the page from another local domain always gives 502 errors on OPTIONS.
I've managed to get some debug info from the Traefik container, but I'm stuck as to how to solve this.
everse-proxy | time="2022-11-11T21:08:01Z" level=debug msg="vulcand/oxy/forward/http: begin ServeHttp on request" Request="{\"Method\":\"OPTIONS\",\"URL\":{\"Scheme\":\"http\",\"Opaque\":\"\",\"User\":null,\"Host\":\"10.10.1.8:8000\",\"Path\":\"\",\"RawPath\":\"\",\"ForceQuery\":false,\"RawQuery\":\"\",\"Fragment\":\"\",\"RawFragment\":\"\"},\"Proto\":\"HTTP/2.0\",\"ProtoMajor\":2,\"ProtoMinor\":0,\"Header\":{\"Accept\":[\"*/*\"],\"Accept-Encoding\":[\"gzip, deflate, br\"],\"Accept-Language\":[\"en-US,en;q=0.9,nl;q=0.8\"],\"Access-Control-Request-Headers\":[\"icy-metadata\"],\"Access-Control-Request-Method\":[\"GET\"],\"Cache-Control\":[\"no-cache\"],\"Origin\":[\"https://gsr.localhost.traefik.me\"],\"Pragma\":[\"no-cache\"],\"Referer\":[\"https://gsr.localhost.traefik.me/\"],\"Sec-Fetch-Dest\":[\"empty\"],\"Sec-Fetch-Mode\":[\"cors\"],\"Sec-Fetch-Site\":[\"same-site\"],\"User-Agent\":[\"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36\"]},\"ContentLength\":0,\"TransferEncoding\":null,\"Host\":\"radio.localhost.traefik.me\",\"Form\":null,\"PostForm\":null,\"MultipartForm\":null,\"Trailer\":null,\"RemoteAddr\":\"127.0.0.1:53784\",\"RequestURI\":\"/radio\",\"TLS\":null}"
reverse-proxy | time="2022-11-11T21:08:01Z" level=debug msg="Upstream ResponseWriter of type *pipelining.writerWithoutCloseNotify does not implement http.CloseNotifier. Returning dummy channel."
reverse-proxy | time="2022-11-11T21:08:01Z" level=debug msg="'502 Bad Gateway' caused by: EOF"
reverse-proxy | time="2022-11-11T21:08:01Z" level=debug msg="vulcand/oxy/forward/http: Round trip: http://10.10.1.8:8000, code: 502, Length: 11, duration: 5.960359ms tls:version: 303, tls:resume:true, tls:csuite:c02f, tls:server:radio.localhost.traefik.me"
The docker-compose.yml
:
version: "3.1"
networks:
db_default:
external: true
services:
reverse-proxy:
container_name: reverse-proxy
image: traefik:v1.7-alpine # The official Traefik docker image
network_mode: "host"
command: --api --docker # Enables the web UI and tells Tr fik to listen to docker
volumes:
- ./docker:/certs:ro
- ./docker/traefik.toml:/etc/traefik/traefik.toml
- /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
gsr2:
container_name: gsrdev2
build: docker
volumes:
- .bash_history:/root/.bash_history
- ./:/var/www
- ./log:/tmp/audit
environment:
#PHP_IDE_CONFIG: "serverName=gsr2.localhost.xip.io"
XDEBUG_CONFIG: "start_with_request=yes"
labels:
- traefik.enable=true
- "traefik.frontend.rule=Host:gsr.localhost.traefik.me"
networks:
- db_default
icecast2:
image: pltnk/icecast2
container_name: icecast2
expose:
- 8000
volumes:
- ./icecast.xml:/etc/icecast2/icecast.xml
- ./log:/var/log/icecast2
- ./docker/bundle.pem:/etc/icecast2/bundle.pem
labels:
- traefik.enable=true
- "traefik.frontend.rule=Host:radio.localhost.traefik.me"
networks:
- db_default
The traefik.toml
:
defaultEntryPoints = ["http","https"]
loglevel="DEBUG"
[api]
dashboard = false
[entryPoints]
[entryPoints.http]
address = ":80"
#[entryPoints.http.redirect]
# regex = "^http://(www.)*(.*)"
# replacement = "https://$2"
# permanent = true
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "/certs/cert.pem"
keyFile = "/certs/key.pem"
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "localhost.traefik.me"
watch = true
exposedbydefault = false
network = "proxy"
Header config in Icecast server:
<http-headers>
<header name="Access-Control-Allow-Origin" value="*" />
<header name="Vary" value="Origin" />
<header name="Access-Control-Allow-Methods" value="GET, OPTIONS, PUT, POST" />
<header name="Access-Control-Allow-Headers" value="Content-Type, Icy-Metadata" />
<header name="Access-Control-Expose-Headers" value="Icy-MetaInt, Icy-Br, Icy-Description, Icy-Genre, Icy-Name, Ice-Audio-Info, Icy-Url, Icy-Sr, Icy-Vbr, Icy-Pub" />
</http-headers>
I fixed it! First I migrated to Traefik 2. Then, according to the Traefik docs, I can just include some middleware to set the headers for CORS directly on my container, like this:
icecast2:
image: pltnk/icecast2
container_name: icecast2
expose:
- 8000
volumes:
- ./icecast.xml:/etc/icecast2/icecast.xml
- ./log:/var/log/icecast2
labels:
- "traefik.http.middlewares.testheader.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
- "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=*"
- "traefik.http.middlewares.testheader.headers.accessControlAllowHeaders=Content-Type, Icy-Metadata"
- "traefik.http.middlewares.testheader.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.testheader.headers.addvaryheader=true"
- traefik.enable=true
- traefik.http.routers.icecast2.middlewares=testheader
- "traefik.http.routers.icecast2.entrypoints=http,https"
- "traefik.http.routers.icecast2.tls=true"
- traefik.http.routers.icecast2.rule=Host(`radio.localhost.traefik.me`)