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
Add support for alternative protobuf content types #4364
Add support for alternative protobuf content types #4364
Conversation
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.
PR is not yet ready, but I wanted some help along the way
if (grpcMediaType.is(GrpcSerializationFormats.PROTO.mediaType())) { | ||
unframedHeaders.contentType(MediaType.PROTOBUF); | ||
} else if (grpcMediaType.is(GrpcSerializationFormats.JSON.mediaType())) { | ||
unframedHeaders.contentType(MediaType.JSON_UTF_8); | ||
} | ||
unframedHeaders.contentType(originalContentType); |
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.
for requests that use x-protobuf or x-google-protobuf, my guess is that they would expect the server to respond with the same content type. Would using the passed down originalContentType be safe? Also, should accept header be checked for the response protobuf content type?
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.
Also, should there be an else clause here? (for when grpcMediaType is null)
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.
Would using the passed down originalContentType be safe? Also, should accept header be checked for the response protobuf content type?
If a suitable accept-header
is specified, it makes sense to respect the value over content-type
.
Also, should there be an else clause here? (for when grpcMediaType is null)
It looks like defensive code.
A normal response including an OK
status should be returned with a proper content-type
.
armeria/grpc/src/main/java/com/linecorp/armeria/server/grpc/FramedGrpcService.java
Lines 181 to 187 in 49054ad
defaultHeaders = supportedSerializationFormats | |
.stream() | |
.map(format -> { | |
final ResponseHeadersBuilder builder = | |
ResponseHeaders | |
.builder(HttpStatus.OK) | |
.contentType(format.mediaType()) |
@@ -1052,6 +1054,20 @@ public boolean isJson() { | |||
return is(JSON) || subtype().endsWith("+json"); | |||
} | |||
|
|||
/** | |||
* Returns {@code true} when the subtype is in [{@link MediaType#PROTOBUF}, {@link MediaType#X_PROTOBUF}, {@link MediaType#X_GOOGLE_PROTOBUF}]. |
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.
We prefer to list elements using and
or or
.
* Returns {@code true} when the subtype is in [{@link MediaType#PROTOBUF}, {@link MediaType#X_PROTOBUF}, {@link MediaType#X_GOOGLE_PROTOBUF}]. | |
* Returns {@code true} when the subtype is one of {@link MediaType#PROTOBUF}, {@link MediaType#X_PROTOBUF}, and {@link MediaType#X_GOOGLE_PROTOBUF}. |
Some fixes are made based on review & test breaks |
Codecov Report
@@ Coverage Diff @@
## master #4364 +/- ##
============================================
- Coverage 73.84% 73.83% -0.02%
- Complexity 17702 17721 +19
============================================
Files 1505 1509 +4
Lines 66105 66201 +96
Branches 8309 8311 +2
============================================
+ Hits 48816 48880 +64
- Misses 13289 13320 +31
- Partials 4000 4001 +1
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
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.
Changes look good to me so far 👍
If the fix looks ok, I'll start on writing tests someday soon.
Please do so 🙏
@@ -210,14 +212,15 @@ static void deframeAndRespond(ServiceRequestContext ctx, | |||
} | |||
|
|||
final MediaType grpcMediaType = grpcResponse.contentType(); | |||
requireNonNull(grpcMediaType); |
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.
We shouldn't throw exceptions in this method since the exception isn't propagated to the response.
res.completeExceptionally(new NullPointerException("MediaType is undefined"));
return;
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.
done fixing in addition to closing pooled object before the return
frameAndServe(unwrap(), ctx, grpcHeaders.build(), | ||
clientRequest.content(), responseFuture, null); | ||
frameAndServe(unwrap(), ctx, grpcHeaders.build(), clientRequest.content(), | ||
responseFuture, null, responseContentType); |
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.
Incorrect indentation - can you check that your IDE is correctly formatted?
https://armeria.dev/community/developer-guide#setting-up-your-ide
…m:j-min5u/armeria into support-additional-protobuf-content-types
8f9b775
to
239f63e
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, @j-min5u! 😀
Left minor comments for testing.
grpc/src/main/java/com/linecorp/armeria/server/grpc/UnframedGrpcService.java
Outdated
Show resolved
Hide resolved
...src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcServiceResponseMediaTypeTest.java
Outdated
Show resolved
Hide resolved
...src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcServiceResponseMediaTypeTest.java
Outdated
Show resolved
Hide resolved
...src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcServiceResponseMediaTypeTest.java
Outdated
Show resolved
Hide resolved
...src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcServiceResponseMediaTypeTest.java
Outdated
Show resolved
Hide resolved
grpc/src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcServiceTest.java
Outdated
Show resolved
Hide resolved
grpc/src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcServiceTest.java
Outdated
Show resolved
Hide resolved
…m:j-min5u/armeria into support-additional-protobuf-content-types
some fixes were added based on review.
should I do it? I'd have to pass the request acceptheaders to deframeAndRespond, then set response contentType to that included in acceptHeader if the request contentType isn't in it. Seems like a pretty extreme case though 🤔 |
...src/test/java/com/linecorp/armeria/server/grpc/UnframedGrpcServiceResponseMediaTypeTest.java
Outdated
Show resolved
Hide resolved
Here's what I thought:
So, we could remove these lines completely and just pass the |
I actually forgot about writing these lines 😅 removed them in commit a498c67 |
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.
Sorry for the late review. Left minor comments. 😉
grpc/src/main/java/com/linecorp/armeria/server/grpc/AbstractUnframedGrpcService.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/AbstractUnframedGrpcService.java
Outdated
Show resolved
Hide resolved
grpc/src/main/java/com/linecorp/armeria/server/grpc/AbstractUnframedGrpcService.java
Outdated
Show resolved
Hide resolved
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 a lot for fixing this bug, @j-min5u! 😄
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.
Looks good to me! Thanks @j-min5u ! 🙇 👍 🙇
Our new hero, @j-min5u! 😆 |
@minwoox |
Please, don't worry. 😄 Take care of yourself and see you later. 😄 |
Motivation: Armeria `UnframedGrpcService` doesn't support alternative protobuf content types Modifications: - add `application/x-protobuf` and `application/x-google-protobuf` to MediaType - add isProtobuf() function - identify Protobuf contentType in UnframedGrpcService using isProtobuf() - respond with request-given protobuf content type for deframed response Result: - Closes line#4355 - Armeria `UnframedGrpcService` now supports `application/x-protobuf` and `application/x-google-protobuf` media types.
Motivation: Wrong response contenttype served for http json transcoding endpoints as result of #4364 Modifications: - since AbstractUnframedGrpcService$frameAndServe uses the provided responseContentType parameter directly as the resulting http contenttype, application/json should be provided in HttpJsonTranscodingService instead of application/grpc+json - alternative would be to respond with the request contenttype ex) JSON -> JSON / JSON_UTF_8 -> JSON_UTF_8 Result: - Closes #4473
Motivation:
Armeria
UnframedGrpcService
doesn't support alternative protobuf content typesModifications:
application/x-protobuf
andapplication/x-google-protobuf
to MediaTypeResult:
UnframedGrpcService
now supportsapplication/x-protobuf
andapplication/x-google-protobuf
media types.