router: add support for direct (non-proxied) http responses.#2335
router: add support for direct (non-proxied) http responses.#2335mattklein123 merged 8 commits intoenvoyproxy:masterfrom brian-pane:direct-response/2315
Conversation
Signed-off-by: Brian Pane <bpane@pinterest.com>
Signed-off-by: Brian Pane <bpane@pinterest.com>
alyssawilk
left a comment
There was a problem hiding this comment.
Cool, this will be a super useful feature to have!
a couple of drive by comments below
include/envoy/router/router.h
Outdated
| }; | ||
|
|
||
| /** | ||
| * A routing primitive that specifies a direct (non-proxied) HTTP response . |
| typedef std::unique_ptr<const Decorator> DecoratorConstPtr; | ||
|
|
||
| /** | ||
| * An interface that holds a RedirectEntry or a RouteEntry for a request. |
There was a problem hiding this comment.
I'd prefer this replace RedirectEntry rather than be a slightly duplicate thing.
newPath could be optional, and expected for redirect responses. I'm neutral if it should be done here or in a follow-up but maybe add a TODO?
There was a problem hiding this comment.
Thanks for the suggestion; combining RedirectEntry and DirectResponseEntry sounds good to me. The combined code will have to deal with some incompatibilities between the two -- e.g., under the current data plane API, redirects aren't allowed to send the response_headers_to_add, whereas direct responses are required to -- but it will probably still be cleaner than the current diff.
I'll merge the implementations post an update to this PR later today.
There was a problem hiding this comment.
cool. hopefully if we do some sanity checks with an IsRedirectReturnCode() in the right places we'll guard against bad configs/code
There was a problem hiding this comment.
I don't see any reason redirects cannot also populate response_headers_to_add. That seems pretty useful to me. Thoughts?
There was a problem hiding this comment.
Adding response_headers_to_add to redirects would change the behavior of existing configs. If we were designing the config schema from scratch, I’d advocate for sending the headers with redirects. But at this point it would impact backward compatibility. Unless we added a “send_headers_with_redirects” flag that defaults to false, I suppose :(
There was a problem hiding this comment.
Yeah, fair enough. I kind of think we could "just do it" and document it in this case as a change. But that's me. Fine to block/TODO for now if you think that would be best.
| virtual const RedirectEntry* redirectEntry() const PURE; | ||
|
|
||
| /** | ||
| * @return the direct response entry or nullptr if there is no direct response for the request. |
| const DirectResponseEntry* RouteEntryImplBase::directResponseEntry() const { | ||
| // A route for a request can exclusively be a route entry, a direct response entry, | ||
| // or a redirect entry. | ||
| if (isDirectResponse()) { |
There was a problem hiding this comment.
Yeah, I think this is confusing, since a redirect entry is a direct response too
test/config/utility.h
Outdated
|
|
||
| // Add an additional route with a direct (non-proxied) response. | ||
| void addDirectResponse(const std::string& domains, const std::string& prefix, | ||
| Http::Code responseCode, const std::string& body); |
There was a problem hiding this comment.
Do you think this will be used widely? If not I'd just suggest doing this as with void addConfigModifier(HttpModifierFunction function); in testRouterDirectResponse
mattklein123
left a comment
There was a problem hiding this comment.
2 drive by comments. Thanks for working on this. I'm +1 on combining redirect and direct response somehow. I think it will make the code simpler.
source/common/config/rds_json.cc
Outdated
| throw EnvoyException("Redirect route entries must not have WebSockets set"); | ||
| } | ||
| } | ||
| bool has_direct_response = false; |
There was a problem hiding this comment.
All the v1 code can be dropped, right?
| validateAndAppendKey(ret, datasource.inline_bytes()); | ||
| break; | ||
| } | ||
| case envoy::api::v2::DataSource::kInlineString: { |
There was a problem hiding this comment.
Can we remove from this PR?
There was a problem hiding this comment.
I’ll move this to a separate PR
Signed-off-by: Brian Pane <bpane@pinterest.com>
Signed-off-by: Brian Pane <bpane@pinterest.com>
|
I'll add another commit later to address a couple of open review comments:
|
alyssawilk
left a comment
There was a problem hiding this comment.
This is looking great - thanks for taking the time to extend/rename the redirect entry
| if (route_->directResponseEntry()) { | ||
| auto response_code = route_->directResponseEntry()->responseCode(); | ||
| if (response_code >= Http::Code::MultipleChoices && response_code < Http::Code::BadRequest) { | ||
| config_.stats_.rq_redirect_.inc(); |
There was a problem hiding this comment.
I think we probably want a direct response stat which supplements (and hopefully eventually replaces) the redirect stat.
There was a problem hiding this comment.
I added a counter of direct responses. Is there a precedent in Envoy for also having counters per response status or per response code family (2xx, 3xx, etc)?
There was a problem hiding this comment.
We already have split out codes for all downstream responses. IMO that's probably sufficient.
source/common/router/router.cc
Outdated
| response_code); | ||
| return Http::FilterHeadersStatus::StopIteration; | ||
| } | ||
| Http::Utility::sendLocalReply( |
There was a problem hiding this comment.
Take a look at callers of sendLocalReply - I think you can simplify the arguments a bit (and if I'm incorrect please educate me! :-P)
There was a problem hiding this comment.
Oh, I see, this method is in the same class that provides a friendly wrapper around sendLocalReply. I'll switch to that.
Signed-off-by: Brian Pane <bpane@pinterest.com>
Signed-off-by: Brian Pane <bpane@pinterest.com>
mattklein123
left a comment
There was a problem hiding this comment.
looks solid, thanks. Few small comments.
source/common/json/config_schemas.cc
Outdated
| "weighted_clusters": {"$ref" : "#/definitions/weighted_clusters"}, | ||
| "host_redirect" : {"type" : "string"}, | ||
| "path_redirect" : {"type" : "string"}, | ||
| "status": {"type": "integer"}, |
source/common/router/config_impl.h
Outdated
|
|
||
| const DecoratorConstPtr decorator_; | ||
| const Http::Code redirect_response_code_; | ||
| const Http::Code direct_response_code_; |
There was a problem hiding this comment.
nit: I might consider making this Optional<Http::Code>. I think it would be slightly clearer in all the places you set and consume it.
| response_code); | ||
| return Http::FilterHeadersStatus::StopIteration; | ||
| } | ||
| config_.stats_.rq_direct_response_.inc(); |
There was a problem hiding this comment.
please add an expectation in one of the tests that checks this stat gets incremented.
There was a problem hiding this comment.
Oh, and I almost forgot - we should update docs for this. Please add an envoy-API pull updating router_filter.rst and note it in your PR description
There was a problem hiding this comment.
@brian-pane you plan on finishing up docs in a follow up, right?
There was a problem hiding this comment.
Yes, I was planning to make a followup PR that adds the remainder of this feature (adding optional response headers and body), with the docs linked to that new PR.
There was a problem hiding this comment.
OK that works. Will merge this.
Signed-off-by: Brian Pane <bpane@pinterest.com>
mattklein123
left a comment
There was a problem hiding this comment.
LGTM, thank you. Will defer to @alyssawilk for final review/merge. (She is out Fridays so probably Tuesday).
|
Could you please add YAML tests? |
|
I'll add SAML tests and post an updated diff tomorrow |
alyssawilk
left a comment
There was a problem hiding this comment.
LGTM, Looks great to me :-)
Merge pending Piotr's sign off on tests.
Signed-off-by: Brian Pane <bpane@pinterest.com>
e309720
|
@PiotrSikora I added some YAML tests. Let me know if they look okay. |
And include in GitHub release artifacts Updates rules_swift to pull in bazelbuild/rules_swift#838 When users open the archive, they'll have rich docs they can explore using Xcode's documentation navigator. When we update to Xcode 13.4, we'll be able to generate HTML docs with this approach and publish to the documentation website. Here's a demo of what that static site looks like: https://envoy-mobile-docc-demo.netlify.app/documentation/envoy/ https://user-images.githubusercontent.com/474794/171704142-993072a3-fbc2-4db6-9c70-65e9e1a47aac.mp4 Risk Level: Low Testing: Local, CI Docs Changes: Added Release Notes: Added Signed-off-by: JP Simard <jp@jpsim.com>
And include in GitHub release artifacts Updates rules_swift to pull in bazelbuild/rules_swift#838 When users open the archive, they'll have rich docs they can explore using Xcode's documentation navigator. When we update to Xcode 13.4, we'll be able to generate HTML docs with this approach and publish to the documentation website. Here's a demo of what that static site looks like: https://envoy-mobile-docc-demo.netlify.app/documentation/envoy/ https://user-images.githubusercontent.com/474794/171704142-993072a3-fbc2-4db6-9c70-65e9e1a47aac.mp4 Risk Level: Low Testing: Local, CI Docs Changes: Added Release Notes: Added Signed-off-by: JP Simard <jp@jpsim.com>
Description:
This PR implements support for returning an HTTP response with a configured
status code without proxying to an upstream.
Risk Level: Medium
Limitations:
There are two features in the corresponding data-plane-api PR that are not implemented in this PR:
I plan to put those feature in a separate PR, in order to keep this PR manageably small.
There are TODO comments for them in this PR.
Testing: Updated unit and integration tests included
Docs Changes: N/A
Release Notes:
N/A (I'll add this feature to the release notes once I've added support for sending
a configured response body and headers.)
Fixes: #2315
API Changes:
envoyproxy/data-plane-api#393
Signed-off-by: Brian Pane bpane@pinterest.com