Error creating http request cookie matcher

1. My Caddy version (caddy version):

v2.0.0-rc.3 h1:z2H/QnaRscip6aZJxwTbghu3zhC88Vo8l/K57WUce4Q=

2. How I run Caddy:

Caddy is kept running on my system via a macOS launchctl .plist file that executes caddy run --config /path/to/Caddyfile as a background job.

a. System environment:

macOS Mojave 10.14.6 (18G4032)

b. Command:

caddy validate --config /path/to/config

d. My complete Caddyfile or JSON config:

localhost {
  root * /Users/noel/Dev/server/projects-active/test

  @request_b {
    expression {http.request.cookie.testcookie} == "myvalue"

  file_server browse {
    root /Users/noel/Dev/server/projects-active/test/siteA

  file_server @request_b browse {
    root /Users/noel/Dev/server/projects-active/test/siteB

3. The problem I’m having:

I’m trying to set up a Caddy configuration where the presence of a cookie with a value will direct all requests to a separate site hosted on the same server. Unsure whether a separate file server directive, or a rewrite is the cleanest way to do this, but in either case, I’m having trouble getting a valid configuration when it comes to creating a named matcher to handle the check for the cookie. The above Caddyfile is a reduced test case that I am able to get the below error to reproduce with.

4. Error messages and/or full log output:

validate: loading http app module: provision http: server srv0: setting up route handlers: route 0: loading handler modules: position 0: loading module 'subroute': provision http.handlers.subroute: setting up subroutes: route 1: loading matcher modules: module name 'expression': provision http.matchers.expression: compiling CEL program: ERROR: <input>:1:64: undeclared reference to 'myvalue' (in container '')
 | caddyPlaceholder(request, "http.request.cookie.testcookie") == myvalue
 | ...............................................................^

5. What I already tried:

Tried scanning the docs to see if there was another way to match a request cookie based on content but it seems like the expression matcher is the way to go on this one. What’s odd to me is even though I’m defining myvalue in this case as a string, I’m the error I’m getting is an undeclared reference, which shouldn’t matter, since I’m looking to match a string, no?

Hi noelforte, welcome around! :wave:

The issue you’re facing is due to the technicality of how parsers work. The quotes around "myvalue" are consumed by the parser of the Caddyfile before it’s passed to the expression parser, which is CEL. By the time CEL receives the expression, myvalue isn’t enclosed in quotes anymore, so CEL tries to understand it as a variable, some predefined value, or an expression, which it is none of them. You should include a second set of escaped quotes around so the Caddyfile will consume the outer set and the CEL parser will receive the value with an inner set of quotes. Long story short, you should replace "myvalue" with "\"myvalue\"" . I’ve tested it and found it to work.

In other good news, there’s a pending PR to add support for literal strings using backticks (i.e. ` ) so the Caddyfile will not consume the quotes for its own and passes the expression as-is to the consumer, which in your case is the expression matcher. Once that PR is merged, you should be able to simply do this:

expression `{http.request.cookie.testcookie} == "myvalue"`

Hey @Mohammed90— also found that enclosing in single quotes as so (expression {http.request.cookie.testcookie} == 'myvalue') works as well, so I’m not sure if those get treated differently by the Caddyfile parser.

Thanks for the tip!

1 Like

Caddy doesn’t parse ' specially, only " and later will parse backticks as @Mohammed90 mentioned, so that’s a good find, i.e. CEL allows ' and ".

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