caddy icon indicating copy to clipboard operation
caddy copied to clipboard

Backticks do not correctly escape brackets

Open bayardar opened this issue 7 months ago • 5 comments

Context

When trying to use the health_request_body directive, the use of backticks for a json body does not work. Ex :

  • health_request_body {"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]} --> This works
Host:               192.168.XXX.XXX:XXXX
User-Agent:         Go-http-client/1.1
Content-Length:     63
Accept-Encoding:    gzip
Content-Type:       application/json
Via:                1.1 Caddy
X-Forwarded-For:    192.168.XXX.XXX
X-Forwarded-Host:   blablabla.xyz
X-Forwarded-Proto:  http
JSON
{
    "id": 1,
    "jsonrpc": "2.0",
    "method": "eth_blockNumber",
    "params": []
}
  • health_request_body `{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}` --> This does not works it send an empty body
Host:               192.168.XXX.XXX:XXXX
User-Agent:         Go-http-client/1.1
Content-Length:     0
Accept-Encoding:    gzip
Content-Type:       application/json
Via:                1.1 Caddy
X-Forwarded-For:   192.168.XXX.XXX
X-Forwarded-Host:   blablabla.xyz
X-Forwarded-Proto:  http
No request content

Might be interesting to write that in the doc or even adapt the code to take it into account properly! This is not working as expected here https://caddyserver.com/docs/caddyfile/concepts#tokens-and-quotes in the backticks section!

How to repoduce

  • OS : debian 12
sudo apt install mitmproxy
mitmproxy --mode reverse:http://<SERVER1_URL>>:<SERVER1_PORT> -p 8080

And here is a sample Caddyfile

http://<YOUR_DESTINATION_URL>:<YOUR_DESTINATION_PORT> {
        log
        reverse_proxy http://<SERVER1_URL>:<SERVER1_PORT> {
                lb_policy first
                health_status 2xx
                health_uri /
                health_method POST
                health_headers {
                        Content-Type application/json
                }
                health_request_body "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_blockNumber\",\"params\":[]}"

                header_up Host {upstream_hostport}
        }
}

http:/<SERVER1_URL>:<SERVER1_PORT> {
        log
        reverse_proxy http://localhost:8080 {
                header_up Host {upstream_hostport}
                header_down X-Acting-Upstream "primary"
        }
}

Now you will see the request handled by mitmproxy, you can inspect the request content.

bayardar avatar May 13 '25 13:05 bayardar

Did you try escaping the opening { so Caddy doesn't read it as a placeholder?

`\{"jsonrpc":...

francislavoie avatar May 13 '25 19:05 francislavoie

This indeed works, I think it's more of a documentation issue, as it wasn't obvious that health_request_body was using placeholders. This will be an issue for anyone trying to send JSON requests.

I also think there should be a WARN log in caddy when trying to use unknown/invalid placeholders, such as {"json": ; WDYT?

ngotchac avatar May 13 '25 19:05 ngotchac

We could probably switch to replacing only known placeholders.

mholt avatar May 13 '25 19:05 mholt

@francislavoie Yep escaping { works but as @ngotchac said it is not clear with what is written in the doc since we have an example like that

directive `{"foo": "bar"}`

@mholt sounds like a great idea!

bayardar avatar May 14 '25 07:05 bayardar

It's dependent on each directive's code. Some do ReplaceAll and some do ReplaceKnown, which is the difference in this case.

francislavoie avatar May 14 '25 07:05 francislavoie