-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
reverseproxy: Add handle_response
blocks to reverse_proxy
(#3710)
#3712
reverseproxy: Add handle_response
blocks to reverse_proxy
(#3710)
#3712
Conversation
f47fbf4
to
62eb124
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on a PR!
I just did a quick high-level pass for starters. We shouldn't have to change the dispenser or remove the CaddyfileUnmarshaler interface...
I also noticed that with this approach -- and maybe I'm wrong, feel free to correct me -- only filters on a single status code or header value. That seems like a severe limitation; I think adding more status codes is easily doable but giving proper control over headers is going to need more consideration.
@@ -743,6 +789,5 @@ func (h *HTTPTransport) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { | |||
|
|||
// Interface guards | |||
var ( | |||
_ caddyfile.Unmarshaler = (*Handler)(nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this no longer a caddyfile Unmarshaler? It needs to be if it is to be used to unmarshal the Caddyfile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree it's not exactly right (because reverse_proxy
still need to be a caddyfile.Unmarshaler), but this was done because with those changes, httpcaddyfile.Helper
is needed to do the parse chaining.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @francislavoie, you are right.
@mholt if you tell me how to cope with the absence of httpcaddyfile.Helper
in (*Handler).UnmarshalCaddyfile()
(as I need this httpcaddyfile.Helper
instance to call httpcaddyfile.ParseSegmentAsSubroute()
as suggested by @francislavoie in #3707), I will be happy to change this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a bit more digging in the source, and actually, I think it's okay for reverse_proxy
to not be a caddyfile.Unmarshaler
.
This is because it's never used as a guest module to something else. Regular directives don't strictly need to be Unmarshalers because their parsing is handled by callbacks registered with RegisterHandlerDirective
or RegisterDirective
, and those are passed Helper
.
Most directives that do implement caddyfile.Unmarshaler
only do so for the registered callbacks to call UnmarshalCaddyfile
, but that's not actually necessary.
It is necessary for guest modules (like proxy transports, log encoders, log filters, matchers, etc.) to be Unmarshaler
because they are invoked by the parent module (i.e. actual directive parsers).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good practice / conventional to implement that, so you can unmarshal it where necessary. But true, all a directive needs is an unmarshaling function, not necessarily to implement an interface. I strongly encourage keeping to that convention, especially for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand @mholt but in this case I don't think it's possible since we actually need to use Helper
all the way down the callchain for handle_response
to work. Consider how handle
and route
work, this is the same kind of situation (except that it's nested within another directive this time, i.e. reverse_proxy
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any news on that topic?
// WithDispenser returns a new instance based on d. All others Helper | ||
// fields are copied, so typically maps are shared with this new instance. | ||
func (h Helper) WithDispenser(d *caddyfile.Dispenser) Helper { | ||
h.Dispenser = d | ||
return h | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely clear on why this is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is httpcaddyfile.ParseSegmentAsSubroute
takes a Helper
rather than a Dispenser
, which makes it necessary to chain parsing for other directives. Here, we only want to pass a dispenser that only has the contents of the handle_response
block so that it doesn't overrun its parsing. That's why the dispenser is being replaced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again @francislavoie, yes this simple method is to simplify code in such cases.
I pushed a change in But perhaps you want to be able to combine several headers/statuses for one handle_response? I applied the format you proposed in the original issue #3707 but maybe I misunderstood your proposition. Do you want a handle_response block be like:
? Meaning both Feel free to provide me a complete spec of what you want so we can go further. |
6ef80a9
to
f4eace2
Compare
Just a heads up, #3740 may change the way the parsing of |
Aren't the args consumed by |
f4eace2
to
165dcf7
Compare
165dcf7
to
5b5b63c
Compare
5b5b63c
to
4a48c44
Compare
Sorry to come back so late on this.
@maxatome So I had a bit of a think 🤔 and I believe what we should do to make this more natural is to reuse the matcher syntax that we already have for this, so like:
This would be done by storing the named matchers in a map which is then referenced when parsing the I think we could keep the existing approach where if you just need one matcher, you can put it inline, but for anything more complex you'd use a named matcher. One annoyance is that since response matchers aren't the same as request matchers, we can't quite share that parsing code. |
Also - if you don't have the time to finish this off, let me know and I'd be glad to take it over (you'll still get author credit) |
Hi @francislavoie thanks for your reply. |
No description provided.