Reverse_proxy to backend over range of ports?

1. The problem I’m having:

Trying to reverse_proxy to many backends over a range of ports.

Is there any way to do this without manually typing out each port by hand? Is there a shorthand pattern feature I’m not aware of? Is there any possibility of this feature being added in the future?

Does not currently exist in the manual: reverse_proxy (Caddyfile directive) — Caddy Documentation

This works, but is error prone and repetitive.

:80 {
	reverse_proxy 127.0.0.1:5000  127.0.0.1:5001 127.0.0.1:5002 127.0.0.1:5003 127.0.0.1:5004 127.0.0.1:5005 127.0.0.1:5006 127.0.0.1:5007 127.0.0.1:5008 ...... {
		# ...
	}
}

What would be helpful:

:80 {
	reverse_proxy 127.0.0.1:5000-5100 {
		# ...
	}
}

Sample use case using compose.yml (services that run as a large collection of single workers).

services:
  app:
    ports:
      - "127.0.0.1:5000-5100:5000"
    deploy:
      replicas: 100

2. Error messages and/or full log output:

ERROR http.log.error making dial info: upstream 127.0.0.1:5000-5100: dial address must represent precisely one socket: 127.0.0.1:5000-5100 represents 101

3. Caddy version:

v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=

4. How I installed and ran Caddy:

a. System environment:

Ubuntu 22.04

Technically we have code in place to support port ranges, but we have a condition in place which rejects upstreams which use a port range:

	if numPorts := addr.PortRangeSize(); numPorts != 1 {
		return DialInfo{}, fmt.Errorf("upstream %s: dial address must represent precisely one socket: %s represents %d",
			u.Dial, dial, numPorts)
	}

I think the reason we did this is that it would require modifying in-place the config the user provided, so if you were to read back the config from the admin API, you would get a different config than what you gave it.

Like for example you’d run a config with ["localhost:5000-5001"] then run curl localhost:2019/config/ to get the config back from the admin API and you’d see in the config ["localhost:5000", "localhost:5001"].

The runtime code references the actual config, and uses it as reference for which upstreams to maintain state for (health status, failed request count, etc).

All that said, I don’t see any problem with making upstream ranges work in the Caddyfile (by expanding the range to multiple upstream addresses in the adapted JSON config), but it probably couldn’t work directly in JSON configs because of the above.

WDYT @matt ?

1 Like

I don’t know how that would work with the API though; we’re supposed to return a DialInfo, so if it’s multiple sockets, which DialInfo do we return?

Edit: Oh, I think I missed the meaning of the request.

Yeah, I suppose that’d be fine. Kinda weird that it’s Caddyfile-only, but makes sense technically speaking.

1 Like

Alright, implemented in this PR:

2 Likes

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