Automatically forward subpath to port on localhost

1. Caddy version (caddy version):

v2.4.6 h1:HGkGICFGvyrodcqOOclHKfvJC0qTU7vny/7FhYp9hNw=

2. How I run Caddy:

for now, just running locally with caddy start or caddy run depending on how i’m feeling.

a. System environment:

macOS 11.6.7
Homebrew 3.5.5-21-g0b2a4c4
Homebrew/homebrew-core (git revision aa463d5651f; last commit 2022-07-20)
Homebrew/homebrew-cask (git revision 2df013e9fb; last commit 2022-07-21)

b. Command:

caddy run

c. Service/unit/compose file:

n/a

d. My complete Caddyfile or JSON config:

{
	admin localhost:4444
	debug
	log
}
:8000/* {
	@portLocalhost path_regexp port ^([0-9]+)/
	handle @portLocalhost {
		reverse_proxy localhost:{re.port.1}
	}

	handle {
		respond "Bad hostname" 400
	}
}

3. The problem I’m having:

I’m basically trying to do this but with a subpath instead of a subdomain.

I’m running an application on localhost: and I want to reverse proxy to that so that I can access it via localhost:8000/8080/ide/*

4. Error messages and/or full log output:

n/a

5. What I already tried:

I’ve tried using the path_regexp but I can’t get it to match for some reason. Maybe bad regex?

:8000/*/ide/* {
        uri strip_prefix @portLocalhost {re.port.1}/ide
        @portLocalhost path_regexp port ^([0-9]+)\/ide
        handle @portLocalhost {
                reverse_proxy localhost:{re.port.1}
        }

        handle {
                respond "Bad hostname" 400
        }
}

6. Links to relevant resources:

1 Like
{
	admin    localhost:4444
}
:8000/*/ide/* {
        handle {
                respond "hello world" 200
        }

}

Doesn’t work with http://localhost:8000/8080/ide/hi so something I’m doing is wrong

Hi :wave:

Please update to v2.5.2, your version is outdated.

Your regex is missing the leading / in the path.
Instead of ^([0-9]+)/ you must write ^/([0-9]+)/.
That should fix your problem and allow you to actually use your matcher the way you intended :slight_smile:

Though, it should be noted, that the upstream will receive the vhosts’ Host: header.
A quick curl localhost:8000/3000/ with a dummy netcat tcp running in the background yields:

❯ nc -vl 3000
Listening on 0.0.0.0 3000
Connection received on localhost 52880
GET /3000/ HTTP/1.1
Host: localhost:8000
User-Agent: curl/7.84.0
Accept: */*
X-Forwarded-For: 127.0.0.1
X-Forwarded-Host: localhost:8000
X-Forwarded-Proto: http
Accept-Encoding: gzip

If your upstream somehow depends on Host: header containing localhost:3000 if connecting from localhost:8000/3000/, consider extending your reverse_proxy directive as described in the docs somewhat far down regarding reverse_proxy with https upstreams:

reverse_proxy localhost:{re.port.1} {
	header_up Host {upstream_hostport}
}

Also, drop that /* in :8000/* {. That is not necessary in your case and got deprecated with v2.5.0.
Exerpt from the v2.5.0 release notes:

The linked PR explains why and shows and example how to rewrite multiple path vhosts to a single vhosts:

3 Likes

Wow! Why are you so helpful? This was the best response I could have asked for. Thank you so much :smiley:

Full Caddyfile with changes:

{
	admin    localhost:4444
}
:8000 {
	@portLocalhost path_regexp port ^/([0-9]+)\/ide
        handle @portLocalhost {
		uri strip_prefix {re.port.1}/ide
                reverse_proxy localhost:{re.port.1}
        }

	handle {
                respond "Bad hostname" 400
        }

}
3 Likes

@IndeedNotJames is indeed awesome if not James, right??

Thank you for filling out the help template. It makes things much faster.

4 Likes