Reusing reverse_proxy block for separate routes?

1. The problem I’m having:

I want to use reverse_proxy, but require a static Authorization header for a route,
e.g. /abc should require Authorization: 123
e.g. /def should require Authorization: 456
and be forwarded upstream
otherwise status 401

like

@abc {
	header Authorization 123
}
@def {
	header Authorization 456
}
reverse_proxy @abc localhost:9000
reverse_proxy @def localhost:9000
respond 401

but I want to configure reverse_proxy, and I dont want to repeat this following block for every route. Is there a way to basically name an upstream block (reverse_proxy) and then reuse it?
I was thinking about listening locally :4000 and then use localhost:4000 as a shared target. But it adds unnecessary overhead.

reverse_proxy {
  to server1:3000 server2:3000
  lb_policy random
  health_port 3000
  health_interval 1s
  health_passes 1
  health_fails 10
  health_timeout 5s
  lb_retries 3
  lb_try_duration 10s
  header_down -X-Powered-By
  # tls
  # tls_client_auth
  # ...
}

2. Error messages and/or full log output:


3. Caddy version:

4. How I installed and ran Caddy:

a. System environment:

b. Command:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

c. Service/unit/compose file:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

d. My complete Caddy config:

PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.

5. Links to relevant resources:

1 Like

Welcome!

There are two options for this, depending on what you want to do.

Snippets

(upstream) {
    reverse_proxy {
    to server1:3000 server2:3000
    lb_policy random
    health_port 3000
    health_interval 1s
    health_passes 1
    health_fails 10
    health_timeout 5s
    lb_retries 3
    lb_try_duration 10s
    header_down -X-Powered-By
    # tls
    # tls_client_auth
    # ...
    }
}

www.mysite.com {
    import upstream
}

When the Caddyfile is loaded, the “import upstream” string is converted to your defined snippet…

Alternatively, there is an experimental feature I use a lot:

Named Routes:

&(upstream) {
    reverse_proxy {
    to server1:3000 server2:3000
    lb_policy random
    health_port 3000
    health_interval 1s
    health_passes 1
    health_fails 10
    health_timeout 5s
    lb_retries 3
    lb_try_duration 10s
    header_down -X-Powered-By
    # tls
    # tls_client_auth
    # ...
    }
}

www.mysite.com {
    invoke upstream
}

Using named routes should save on memory usage when you’re invoking the same route on lots of sites.

2 Likes

I agree named routes is the way to go.

Alternatively you could just have one big expression matcher if they have the same outcomes:

@shouldProxy <<CEL
	(header({'Authorization': ['123']}) && path('/abc*')) ||
	(header({'Authorization': ['456']}) && path('/def*'))
	CEL
reverse_proxy @shouldProxy localhost:9000
5 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.