lucaslorentz / caddy-docker-proxy

Caddy as a reverse proxy for Docker
MIT License
2.61k stars 163 forks source link

Changing HTTP status code rewrite - is that possible using labels? #629

Open Kenya-West opened 3 weeks ago

Kenya-West commented 3 weeks ago

I try to implement such logic to rewrite HTTP 307 response from some backend to a HTTP 200 one.

Equivalent in Caddyfile would be:

{$DOMAIN} {
    reverse_proxy http://service:80 {
        handle_response {
            @redirect307 {
                expression `{http.response.status} == 307`
            }
            handle @redirect307 {
                response_template = "{{.RespHeader.Get \"Location\"}}"
                respond `{"redirect_url": "{{.RespHeader.Get \"Location\"}}"}` 200 {
                    header Content-Type application/json
                }
            }
        }
    }

How could I implement this code block in Caddy Docker Proxy?

Approach №1

Something like:

---
version: "3.8"

services:
  xui:
    image: ${DOCKERIMAGE}
    container_name: ${CONTAINERNAME}
    hostname: ${HOSTNAME}
    env_file:
      - .env
    restart: unless-stopped
    networks:
      - caddy
    ports:
      - "${PORT}:80"
    labels:
      caddy: "${DOMAIN}"
      # some are skipped
      caddy.2_reverse_proxy: "{{upstreams ${DASHBOARD_PORT}}"
      caddy.3_handle_path: "/${DASHBOARD_PATH}"
      caddy.3_handle_path.reverse_proxy: "{{upstreams ${DASHBOARD_PORT}}}"
      caddy.3_handle_path.reverse_proxy.handle_response: "handle_307"
      caddy.3_handle_response.handle_307: "response_template"
      caddy.3_handle_response.response_template: |
        {
          respond `{\"redirect_url\": \"{{.RespHeader.Get \"Location\"}}\"}` 200 {
            header Content-Type application/json
          }
        }

networks:
  caddy:
    external: true

But Caddy always fails to parse such multiline config regardless of is there backslashes or not, is there either | or > before multiline value or not... There are always errors like caddy | [2024-06-07 19:00:25] ERROR: Failed to get Container Caddyfile [logger=docker-proxy] template: :1: unexpected "\\\\" in operand or caddy | [2024-06-07 18:58:28] ERROR: Failed to get Container Caddyfile [logger=docker-proxy] template: :1: unexpected "\}" in operand. It's the parsing problem.

Approach №2

Caddyfile:

(handle_redirects) {
    @redirect307 {
        status 307
    }
    handle_response @redirect307 {
        respond `{"redirect_url": "{{.RespHeader.Get \"Location\"}}"}` 200 {
            header Content-Type application/json
        }
    }
}

using it:

# ...
    labels:
      caddy: "${DOMAIN}"
      # ...
      caddy.2_reverse_proxy: "{{upstreams ${DASHBOARD_PORT}}"
      caddy.3_handle_path: "/${DASHBOARD_PATH}"
      caddy.3_handle_path.reverse_proxy: "{{upstreams ${DASHBOARD_PORT}}}"
      caddy.4_handle_response: "/${DASHBOARD_PATH}/*"
      caddy.4_handle_response.status: "307"
      caddy.4_handle_response.handle_307: "handle_redirects"
# ...

yet it produces the same errors as above.

How could I put multiline JSON block in YAML label value?

francislavoie commented 3 weeks ago

Where are you getting response_template from? That doesn't exist in Caddy.

Everything that's possible with a Caddyfile is possible with Docker labels. But sometimes it can be tricky to translate.