Templating headers

1. The problem I’m having:

I’m trying to set a request header when using reverse_proxy, based on a different request header. I thought that a good approach would be to create a new Caddy module which implements a new template function to hand the complexity of transforming the headers.

Unfortunately, I can’t seem to be able to use templates when setting up new headers. I know that I can use {{.RespHeader.Set ...}} to set headers while using a template, for example when performing a static_request, but that’s not what I want to do, I want to do it on a reverse_proxy.

2. Error messages and/or full log output:

Here’s an example of a test configuration file:

{
  "apps": {
    "http": {
      "servers": {
        "test": {
          "listen": [
            ":8080"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "templates"
                },
                {
                  "handler": "vars",
                  "string_one": "{{randAlpha 4}}"
                },
                {
                  "handler": "headers",
                  "response": {
                    "set": {
                      "string_one": ["{http.vars.string_one}"],
                      "string_two": ["{{randAlpha 4}}"] 
                    }
                  }
                },
                {
                  "handler": "static_response",
                  "body": "{{randAlpha 4}} {http.vars.string_one}\n"
                }
              ]
            }
          ]
        }
      }
    }
  }
}

This is the result:

# curl -v localhost:8080
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.88.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Length: 7
< Content-Type: text/plain; charset=utf-8
< Server: Caddy
< String_one: }
< String_two: {{randAlpha 4}}
< Date: Wed, 23 Aug 2023 16:20:19 GMT
< 
YLOq }
* Connection #0 to host localhost left intact

Interesting things:

  • Templating works fine inside the static_response
  • Templating doesn’t work at all inside the headers
  • Templating is super weird inside vars, cutting the string. Maybe it things it’s supposed to be a placeholder?

So I’m concluding that templating is not at all universal and only works under selected handlers. Is there a way to template a header when using reverse_proxy?

I’ve also tried setting up headers inside reverse_proxy, with the same result.

Thank you

3. Caddy version:

v2.7.4

4. How I installed and ran Caddy:

a. System environment:

Downloaded Caddy from the website, under Linux.

b. Command:

./caddy run -c caddy.json

When you enable the templates handler, it does nothing immediately. What it does is set up the response body to be intercepted as a stream and then have its contents replaced on the way out. This means it only works on the response body. It also only runs on the way back up the middleware chain, and not on the way down.

You can still use templates with reverse_proxy FYI, you just need to make sure your proxy response includes template text in the body.

That said, this is very much an XY problem kind of question:

What exactly are you trying to achieve? You’re asking the wrong questions.

Hi, thanks for replying.

I’ve described what I’m trying to achieve on my first sentence, but I’ll expand on that.

Basically Caddy is receiving a certain header that is encoded in a certain way. I have no control over this, since it’s coming from a third-party. I need to decode that header, apply some transformations, create a new header based on those transformations, and then send it to a backend service via reverse_proxy. I cannot change the way the backend service consumes the header, so it really needs to come from Caddy.

You haven’t explained what the transformation is. That matters as to what your options are. Please be more specific.

I’m receiving a header that contains a JSON Web Token (JWT). I want to pick up a specific claim of that JWT and add it to the request as a separate header.

I think you’re looking for a plugin like GitHub - ggicci/caddy-jwt: 🆔 Caddy Module JWT Authentication then.

Thanks for the link to that plugin, but unfortunately it doesn’t work for us. We’re using Azure AD and the tokens issued by Microsoft Graph are special and can’t be validated by third parties (Access tokens in the Microsoft identity platform - Microsoft Entra | Microsoft Learn). This means that the JWT Authentication plugin for Caddy will always fail.

Either way, I suggest you implement what you need as a plugin of your own:

Thanks, that’s what I ended up doing. It’s a bit daunting to begin with, but once you’ve got the hang of it it’s not that difficult.

1 Like

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