Skip to content

Commit

Permalink
grpc-json: preserve request method in x-envoy-original-method header (#…
Browse files Browse the repository at this point in the history
…11126)

Commit Message: grpc-json: preserve http request method in `x-envoy-original-method` header so that applications have access to it.
Additional Description: The grpc-json transcoder currently forwards HTTP path to applications via "x-envoy-original-path" header. We would find it useful if it also forwarded the HTTP method.
Risk Level: Low
Testing: Updated grpc-json-transcoder unit tests
Docs Changes: Added docs
Release Notes: Added release notes

Signed-off-by: Phillip Huang <[email protected]>
  • Loading branch information
JavaScriptBach authored Jun 2, 2020
1 parent b9aff55 commit 6a69cc5
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ can be send by the gRPC server in the server streaming case.
In this case, HTTP response header `Content-Type` will use the `content-type` from the first
`google.api.HttpBody <https://github.com/googleapis/googleapis/blob/master/google/api/httpbody.proto>`.

Headers
--------

gRPC-JSON forwards the following headers to the gRPC server:

* `x-envoy-original-path`, containing the value of the original path of HTTP request
* `x-envoy-original-method`, containing the value of the original method of HTTP request


Sample Envoy configuration
--------------------------

Expand Down
1 change: 1 addition & 0 deletions docs/root/version_history/current.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ New Features
* grpc: added support for Google gRPC :ref:`custom channel arguments <envoy_v3_api_field_config.core.v3.GrpcService.GoogleGrpc.channel_args>`.
* grpc-json: added support for streaming response using
`google.api.HttpBody <https://github.com/googleapis/googleapis/blob/master/google/api/httpbody.proto>`_.
* grpc-json: send a `x-envoy-original-method` header to grpc services.
* gzip filter: added option to set zlib's next output buffer size.
* health checks: allow configuring health check transport sockets by specifying :ref:`transport socket match criteria <envoy_v3_api_field_config.core.v3.HealthCheck.transport_socket_match_criteria>`.
* http: added :ref:`local_reply config <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.local_reply_config>` to http_connection_manager to customize :ref:`local reply <config_http_conn_man_local_reply>`.
Expand Down
1 change: 1 addition & 0 deletions source/common/http/headers.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class HeaderValues {
const LowerCaseString EnvoyMaxRetries{absl::StrCat(prefix(), "-max-retries")};
const LowerCaseString EnvoyNotForwarded{absl::StrCat(prefix(), "-not-forwarded")};
const LowerCaseString EnvoyOriginalDstHost{absl::StrCat(prefix(), "-original-dst-host")};
const LowerCaseString EnvoyOriginalMethod{absl::StrCat(prefix(), "-original-method")};
const LowerCaseString EnvoyOriginalPath{absl::StrCat(prefix(), "-original-path")};
const LowerCaseString EnvoyOverloaded{absl::StrCat(prefix(), "-overloaded")};
const LowerCaseString EnvoyRateLimited{absl::StrCat(prefix(), "-ratelimited")};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ Http::FilterHeadersStatus JsonTranscoderFilter::decodeHeaders(Http::RequestHeade
headers.removeContentLength();
headers.setReferenceContentType(Http::Headers::get().ContentTypeValues.Grpc);
headers.setEnvoyOriginalPath(headers.getPathValue());
headers.addReferenceKey(Http::Headers::get().EnvoyOriginalMethod, headers.getMethodValue());
headers.setPath("/" + method_->descriptor_->service()->full_name() + "/" +
method_->descriptor_->name());
headers.setReferenceMethod(Http::Headers::get().MethodValues.Post);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ TEST_F(GrpcJsonTranscoderFilterTest, TranscodingUnaryPost) {
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false));
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/shelf", request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("POST", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/CreateShelf", request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));

Expand Down Expand Up @@ -454,6 +455,7 @@ TEST_F(GrpcJsonTranscoderFilterTest, TranscodingUnaryPostWithPackageServiceMetho
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/bookstore.Bookstore/CreateShelfWithPackageServiceAndMethod",
request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("POST", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/CreateShelfWithPackageServiceAndMethod",
request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));
Expand Down Expand Up @@ -597,6 +599,7 @@ TEST_F(GrpcJsonTranscoderFilterSkipRecalculatingTest, TranscodingUnaryPostSkipRe

EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/shelf", request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("POST", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/CreateShelf", request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));

Expand Down Expand Up @@ -674,6 +677,7 @@ TEST_F(GrpcJsonTranscoderFilterTest, TranscodingUnaryWithHttpBodyAsOutput) {
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false));
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/index", request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("GET", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/GetIndex", request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));

Expand Down Expand Up @@ -708,6 +712,7 @@ TEST_F(GrpcJsonTranscoderFilterTest, TranscodingUnaryWithHttpBodyAsOutputAndSpli
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false));
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/index", request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("GET", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/GetIndex", request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));

Expand Down Expand Up @@ -753,6 +758,7 @@ TEST_F(GrpcJsonTranscoderFilterTest, TranscodingUnaryPostWithHttpBody) {
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false));
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/postBody?arg=hi", request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("POST", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/PostBody", request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));

Expand Down Expand Up @@ -800,6 +806,7 @@ TEST_F(GrpcJsonTranscoderFilterTest, TranscodingStreamPostWithHttpBody) {
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false));
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/streamBody?arg=hi", request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("POST", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/StreamBody", request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));

Expand Down Expand Up @@ -855,6 +862,7 @@ TEST_F(GrpcJsonTranscoderFilterTest, TranscodingStreamWithHttpBodyAsOutput) {
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false));
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/indexStream", request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("GET", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/GetIndexStream", request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));

Expand Down Expand Up @@ -907,6 +915,7 @@ TEST_F(GrpcJsonTranscoderFilterTest, TranscodingStreamWithFragmentedHttpBody) {
EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false));
EXPECT_EQ("application/grpc", request_headers.get_("content-type"));
EXPECT_EQ("/indexStream", request_headers.get_("x-envoy-original-path"));
EXPECT_EQ("GET", request_headers.get_("x-envoy-original-method"));
EXPECT_EQ("/bookstore.Bookstore/GetIndexStream", request_headers.get_(":path"));
EXPECT_EQ("trailers", request_headers.get_("te"));

Expand Down

0 comments on commit 6a69cc5

Please sign in to comment.