I’d like to make a custom plugin that does something kind of like this contrived example:
- Examines the
POST
body
- Does some sort of dynamic lookup based on the POST body
- Uses the value of the lookup to determine the URL to write to.
Here’s a very contrived example:
- Requests come in as
POST
to /foo
w/ JSON payload {"destination": 42, ...other json.. }
- Plugin intercepts this as lookups up destination 42 in it’s backend
- In this case let’s say looking up destination 42 returns
/bar
- Request is rewritten to
/bar
keeping everything else about the request intact.
I think the route I want to look at is writing a custom middleware that acts like http.handlers.rewrite
but before I dig too much deeper figured I’d post here and see if anyone knows of any examples that do something kind of similar.
Thanks!
You can just define a variable in your module (see the var
handler for how that works, and read its source code), then you can just use Caddy’s existing rewrite
handler like this:
rewrite * {vars.your_destination}
Awesome thanks I’ll take a look!
Ok cool, I also came across caddy-ext/requestbodyvar at master · RussellLuo/caddy-ext · GitHub which shows how and where to call Replacer.Map
to load the placeholder value. Thanks! That combined w/ your rewrite suggestion should work!
This seems to be working perfectly, thanks!
For anyone else trying something similar here’s what my Caddyfile looks like:
route /foo* {
# register my module that creates the request_body_destination variable
request_body_destination_var
rewrite /foo {request_body_destination}
reverse_proxy /foo/bar { ... }
}
My request_body_destination_var
module looks very much like caddy-ext/requestbodyvar at master · RussellLuo/caddy-ext · GitHub here’s the gist of the ServeHTTP
:
func (v *RequestBodyDestinationVar) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
// TODO: actually parse the payload and construct a dynamic route
route := "/foo/bar"
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
repl.Set("request_body_destination", route)
// set a response header just so I know this is working
w.Header().Set("X-Debug-Destination", route)
return next.ServeHTTP(w, r)
}
1 Like