Rob
(Rob)
March 19, 2020, 3:49am
1
Hi, is it possible to rewrite a request from GET to POST, sort of like described here ? The last comment said something about it working in Caddy 2.0.
My use-case is a GraphQL query to Hasura which currently only supports POST requests. I’d like to enable GET requests so I can cache using a CDN. Thanks!
Hi @Rob , welcome to the Caddy community!
Just to note, the forum post you linked describes Caddy’s own upstream health checking, and changing which method it uses for that.
It’s a little bit different from what I would call translating a client’s request to a different method before proxying it upstream.
Of note - Caddy 2 currently does neither, but it’s still in development, so maybe you can mention this thread (possibly also the one you linked) when you submit a v2 feature request on the Github repository at GitHub - caddyserver/caddy: Fast, multi-platform web server with automatic HTTPS ?
Rob
(Rob)
March 19, 2020, 12:05pm
3
Ah, thanks for that clarification @Whitestrake ! I’ll consider opening an issue if I can’t find another way to do what I want.
matt
(Matt Holt)
March 19, 2020, 3:05pm
4
That’s not quite right The rewrite
handler can change the request method: JSON Config Structure - Caddy Documentation
2 Likes
There I go again, basing my assertions off the Caddyfile instead of the actual capabilities under the hood!
One day I’ll learn… Thanks for the clarification.
1 Like
Can we add a subdirective to rewrite
for this before the RCs? Something like:
rewrite * /foo.html {
method POST
}
Maybe you can think of a better way.
matt
(Matt Holt)
March 19, 2020, 9:31pm
7
Maybe just a new directive? method /foo.html POST
1 Like
What does this do in non-reverse-proxy situations?
matt
(Matt Holt)
March 20, 2020, 2:02am
10
Still changes the method. For if any future handlers later in the middleware chain care about the method, I guess.
1 Like
Rob
(Rob)
March 20, 2020, 2:46am
11
Thanks @matt . I have one more question. As far as I can tell from the docs, it is not possible to set the body of the request. Is that correct?
In my case I want to use the query arguments from a GET request to set the body of a new POST request. Thanks!
matt
(Matt Holt)
March 20, 2020, 2:48am
12
You want the server to set/change the request body for any later handlers (like reverse proxy for example)?
Not currently implemented but easy to add to the request_body handler: JSON Config Structure - Caddy Documentation
Rob
(Rob)
March 20, 2020, 3:07am
13
Yes, I think so. Are you offering to make a change? If so, sounds great! Maybe I should give complete background to my motivation:
Someone made this suggestion to me as a solution to caching POST requests via CDN.
My current Caddyfile looks like:
api.revddit.com {
proxy /q/ 172.17.0.1:9090 {
websocket
without /q
}
proxy / graphql-engine:8080 {
websocket
}
}
And I have a docker-compose.yaml with the following:
caddy:
image: abiosoft/caddy:0.11.0
depends_on:
- "graphql-engine"
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/Caddyfile
- caddy_certs:/root/.caddy
I would need to update the above to Caddy 2. This setup comes from a Digital Ocean droplet image provided by Hasura, which is a GraphQL engine.
Should be pretty simple to do the same as what you already have in v2:
api.revddit.com {
route /q/* {
uri strip_prefix q/
reverse_proxy 172.17.0.1:9090
}
reverse_proxy graphql-engine:8080
}
Rob
(Rob)
March 20, 2020, 4:04am
15
Thanks for showing what my config should look like in v2.
My goal here is to transform GET requests to POST requests by setting the body which I think requires an update within Caddy itself and additional configuration within my Caddyfile. I’m also checking with Hasura devs to see if I can use the caddy/caddy docker image instead of abiosoft/caddy.
matt
(Matt Holt)
March 20, 2020, 4:43pm
16
So you would need something like:
api.revddit.com {
route /q/* {
method POST
uri strip_prefix q/
request_body {http.request.uri.query.param}
reverse_proxy 172.17.0.1:9090
}
reverse_proxy graphql-engine:8080
}
But right now the method
and request_body
lines don’t exist. (They’re extremely easy to implement, I think. PRs welcomed.)
Rob
(Rob)
March 21, 2020, 1:01am
17
Hi @matt , do I need to change existing code or add a module?
I’m unfamiliar with Go and the Caddy code-base, so I would not say it’s easy for me. I can give it a try.
matt
(Matt Holt)
March 21, 2020, 2:54am
18
It’d be new Caddyfile directives for existing modules, that’s all.
You don’t have to do it yourself, but it would probably be faster, since I myself don’t plan on adding new features until after the 2.0 release.
The method
directive would come from the rewrite
handler, in here: https://github.com/caddyserver/caddy/blob/v2/modules/caddyhttp/rewrite/caddyfile.go
And the request_body
handler does not yet have a directive: https://github.com/caddyserver/caddy/tree/v2/modules/caddyhttp/requestbody
Here’s some godoc: httpcaddyfile package - github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile - pkg.go.dev
Again, don’t feel obligated to, it’s just a matter of time at this point. (Anyone could do this, as well.)
Rob
(Rob)
March 21, 2020, 3:02am
19
Great, thank you for these details! I’ll give it a shot after I read a bit more about docker.
Rob
(Rob)
March 21, 2020, 3:42am
20
I think uri is also missing as a handler for route because it shows this error when I tried to upgrade my existing config,
caddy_1 | run: adapting config using caddyfile: parsing caddyfile tokens for 'route': /etc/caddy/Caddyfile:3 - Error during parsing: unrecognized directive: uri
I used,
api.revddit.com {
route /q/* {
uri strip_prefix q/
reverse_proxy 172.17.0.1:9090
}
reverse_proxy graphql-engine:8080
}
I’ll try to learn some Go now. The config I hope to get working is,
api.revddit.com {
route /q/* {
uri strip_prefix q/
reverse_proxy 172.17.0.1:9090
}
route /v1/graphql {
request_body {http.request.uri.query.param}
method POST
}
reverse_proxy graphql-engine:8080
}
1 Like