-
Notifications
You must be signed in to change notification settings - Fork 17
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
Fix empty GET request codec translation #122
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.
Thanks for looking into this! Would you be able to create a testcase in the file vanguard_restxrpc_test.go
. You'll have to update the proto files under internal/proto/vanguard
to cover the case. As this was an oversight in the testing, and isn't currently covered. To keep with the theme maybe in library.proto
:
// Lists shelves.
rpc ListShelves(ListShelvesRequest) returns (ListShelvesResponse) {
// List method maps to HTTP GET.
option (google.api.http) = {
get: "/v1/shelves"
};
}
And the testcase something like:
}, {
name: "ListShelves-GetNilRequest",
input: input{
method: http.MethodGet,
path: "/v1/shelves",
body: nil,
},
stream: testStream{
method: testv1connect.LibraryServiceListShelvesProcedure,
msgs: []testMsg{
{in: &testMsgIn{
msg: &testv1.ListShelvesRequest{},
}},
{out: &testMsgOut{
msg: &testv1.ListShelvesResponse{},
}},
},
},
output: output{
code: http.StatusOK,
body: &testv1.ListShelvesResponse{},
},
protocol_rest.go
Outdated
} | ||
|
||
func restHTTPBodyRequestIsEmpty(op *operation) bool { | ||
return op.request.ContentLength < 0 |
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.
This is checking for an unknown ContentLength
as -1
is valid for a non empty body where the content-length can't be deduced up front.
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 added some unit tests and took another stab at it using the restTarget values.
I'm open to other fixes.
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 believe the issue is here:
Line 2087 in 7aae240
case m.isRequest && op.clientReqNeedsPrep: |
We need to not fallthrough to the default case as an empty body is not a valid JSON request. We must always use the
prepareUnmarshalRequest
for decoding the message if needed. We also must always emit a request message when we hit EOF here:Lines 952 to 953 in 7aae240
if !r.consumedFirst && errors.Is(err, io.EOF) && r.rw.op.clientReqNeedsPrep { | |
r.msg.markReady() |
I think for now the simplest fix is for any GET request to return true on requestNeedsPrep
. So this would add a simple op.request.Method == http.MethodGET
to the logic . The prepareUnmarshaledRequest
is close to a no-op so shouldn't add much overhead. And almost all GET
requests will require preparation of the request message.
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 don't really understand this change.
For one, why does the request need preparation if the body is empty but all of those other conditions are false? That doesn't seem intuitive. The "request preparation" is to adjust the request -- based on other aspects of the request (like URI path, query string, etc) or to transform the request data when using google.api.HttpBody
.
Also, the helper function looks wrong. If the ContentLength
field of an *http.Request
is less than zero, it means that the length of the body is not known -- i.e. you must actually read the body. This is common for HTTP/2 and HTTP 1.1 chunked requests.
d94a2f2
to
1031e75
Compare
1031e75
to
a8aad48
Compare
Co-authored-by: Edward McFarlane <[email protected]>
Small addition to make the request look more like a real list request. This proto file acts as documentation for building a REST style API. Co-authored-by: Edward McFarlane <[email protected]>
Co-authored-by: Edward McFarlane <[email protected]>
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, thanks!
Co-authored-by: Edward McFarlane <[email protected]>
Requiring request prep for all requests except for
body: "*"