Using string concatenation in path expression

1. The problem I’m having:

I’m trying to use expression matching to deny access to certain sub directories. The expression matching work as expected, however I’d like to add the variable http.request.host to a path but this value needs concatenating to make the complete path.

The hardcoded version is shown here:

@block {
 expression `path("/client/*") && ! path("/client/THESITE.COM/*")`
}
respond @block 404

I’d like the replace the parts in CAPS above using the following pseudo code:

@block {
 expression `path("/client/*") && ! path("/client/{http.request.host}/*")`
}
respond @block 404

So that with multiple sites I don’t have to edit this value manually.
I can’t seem to find any documentation about how to achieve this. The variable http.request.host is correct, but I’m not sure about the syntax for the 2nd path

2. Error messages and/or full log output:

Not really relevant as I don’t know the syntax

3. Caddy version:

V2.6.4

4. How I installed and ran Caddy:

Installed on Linux via apt install caddy running under systemd

a. System environment:

Ubuntu 22.04

b. Command:

c. Service/unit/compose file:

d. My complete Caddy config:

# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace ":80" below with your
# domain name.
{
http_port 80
https_port 443
}

# Pull out to make each site as simple as possbile
(websockets) {
@websockets {
	header Connection Upgrade
	header Upgrade websocket
}
}

eyeronic.duckdns.org:443 {
	root * /mnt/c/source/eyeronic_iss/trunk/www
	
	import websockets
	route /socket {
		reverse_proxy @websockets 127.0.0.1:8089
	}

	@block {
	expression `path("/client/*") && ! path("/{{http.request.host}}/*")`
	}
	respond @block {http.request.host} 

	file_server
	tls internal
	php_fastcgi unix//var/run/php/php8.1-fpm.sock
}

5. Links to relevant resources:

This might be relevant but not sure:

Placeholders in CEL expressions are essentially “functions” that pull out the value, so you need to treat them like they’re function calls syntactically. Try something like this:

path("/client/" + {http.request.host} + "/*")

You don’t need the @websockets matcher by the way. You only need the matcher if you need to split up websocket traffic from HTTP traffic on the same URLs. In your case you’re using /socket for websockets so you can just do reverse_proxy /socket 127.0.0.1:8089 to simplify it.

1 Like

Thank you!
That works perfectly and means I don’t have to build a generator, really fantastic!

About the websockets I had to do it like this, initially I had just the reverse proxy but was getting really strange random dropped connections. I found a post somewhere on the forums using the route which completely fixed the problem (I know my server side and client code were correct). This was with an earlier version of Caddy but doing the route instead of directly doing the proxy made it rock solid.

Edit: If you want me to get logs from this error (if they still exist) I can try and recreate the problem and post logs (I’m far from a Caddy expert so might need to some to look at logging/debugging etc.)

I guarantee that neither route or the @websockets matcher do anything for you.

1 Like

I shall test and if there are any changes I will reply or do a new post.
Again thank you for your time and help!

1 Like

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