Maps, type of variables and expression

1. Caddy version (caddy version):

v2.4.5

2. How I run Caddy:

a. System environment:

Desktop, Darwin

b. Command:

$ curl -I "https://localhost/demo/?foo"

d. My complete Caddyfile or JSON config:

localhost {
	map {query} {testvariable_number} {
		foo 1
		bar 2
		default 3
	}

	header x-testvariable-number {testvariable_number}
	header x-query {query}

	@typetest expression `{testvariable_number} > 0`
	header @typetest x-typetest YES

	respond "Look at the headers" 200
}

3. The problem I’m having:

I want to use the destination variable that is created during a mapping with expression and need it to be interpreted as a number/int.

4. Error messages and/or full log output:

$ curl -I "https://localhost/demo/?foo"
HTTP/2 200
server: Caddy
x-query: foo
x-testvariable-number: 1
content-length: 19

I expected the @typetest matcher to be triggered.

5. What I already tried:

To verify the matcher and expression work at all:

	@typetest expression `{testvariable_number} == "1"`
	header @typetest x-typetest YES

results in

HTTP/2 200
server: Caddy
x-query: foo
x-testvariable-number: 1
x-typetest: YES
content-length: 19

6. Links to relevant resources:

I expected to being able to work with the result like in the handle_errors example:

	@4xx expression `{http.error.status_code} >= 400 && {http.error.status_code} < 500`
	respond @4xx "It's a 4xx error!"

All map placeholders in Caddy will output strings, not integers. CEL doesn’t have a (string, int) -> bool defined for comparison operators like >. The solution is to cast the placeholder to an int before comparing. So for example:

expression `int({testvariable_number}) > 0`

This will then do (int, int) -> bool for the comparison, which is defined.

See the CEL docs where it talks about numeric values, and the standard definitions that exist for the various types and operators.

The reason your == comparison worked is because you used "1", comparing string to string, which is defined.

Some placeholders that Caddy itself generates will give integers though, like you noticed with the error status code. That’s because the status code is an integer in http.Request in Go, so the placeholder replacer keeps the same type.

1 Like

Hello Francis. I tried casting the placeholder before opening this topic. I can’t remember why I thought casting won’t work inside the expression. Maybe I casted to INT but still compared against a string and I misinterpreted the “no matching overload” error message.

When I’m doing it now it works like a charm. Thanks for the quick response.

2 Likes

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