I’d really like for Caddy to have an option for request mirroring, and I read the conversation on Github issues #4211 and #6706. The other day, I decided to start playing with the idea.
I have a simple but limited POC that actually works for my needs. An example Caddyfile looks like:
http://localhost:8080 {
route /some/path {
shadow {
compare_body
primary {
respond Hunter1
}
shadow {
respond Hunter2
}
}
}
}
The idea is to essentially make primary
and shadow
subdirectives work similarly to the route
directive; to define a set of directives for a chain of MiddlewareHandlers. My handler multiplexes the request to both of those handlers (Although my POC only loads a single handler for shadow and single handler for primary right now).
But I’m struggling as I try to expand it to be more broadly useful. The biggest challenge right now: So far the best way I’ve found to unmarshal caddyfile config into child modules is to use the caddy.GetModule
function. But that means I’m only able to get handler modules where the following are true, at least for Caddyfile support.
- The module can be loaded just from the directive string
- For cases like
http.handlers.reverse_proxy
this is easy enough, since I can just concathttp.handlers.
with the directive. - For cases like
respond
I need to add special handling to usenew(caddyhttp.StaticResponse)
explicitly.
- For cases like
- The module must implement
caddyfile.Unmarshaler
, or just not need to (unmarshal any values from the caddyfile).
That works well enough for my simple example above, but if I want to mirror a request to a different path…
route /v1/my/api {
shadow {
compare_body
primary {
reverse_proxy https://my-host.com
}
shadow {
uri replace /v1/my/api /v2/my/api # This doesn't work :(
reverse_proxy https://my-host.com
}
}
}
I can’t unmarshal uri
which is registered with a somewhat specialized parser function and is just a directive for loading http.handlers.rewrite
which has lots of different behavior behind different directives, and doesn’t implement caddyfile.Unmarshaler
.
It would be awesome if there was a hypothetical httpcaddyfile.GetRegisteredHandlerUnmarshaler(directive string)
function, so I could just parse this handler directive easily. One thing I want to try doing is forking Caddy so I can play around with the idea. But it feels like there are reasons why the registered directives/parsers aren’t exported in any consumable way.
Before I go off the deep end, I was wondering if anyone had thoughts or feedback on my approach.