Replies: 1 comment
-
|
@shenqidebaozi @demoManito could you help to take a look? |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Background
I've added a failing test case in
@transport/http/binding/encode_test.gothat highlights an issue with our current URL encoding implementation.As I haven't committed it yet, here is the test case for context:
The root cause is that transport/http/binding/encode.go:EncodeURL uses encoding/form/proto_encode.go:EncodeValues to prepare the values for both path parameters and query parameters. However,
EncodeValuesuses thejson_nameof a protobuf field to create the key-value map, which is correct for query parameters according to protobuf's JSON mapping specification.The problem arises when a URL path template uses the protobuf field's text name (the actual field name in the
.protofile, which is typicallysnake_case), but the key generated byEncodeValuesis thecamelCasejson_name.In the example above, the path template expects a variable named
{user_id}. However,EncodeValuesprocesses theUpdateUserRequestand generates a keyuserIdfor theuser_idfield. WhenEncodeURLattempts to substitute{user_id}, it can't find a matching key in the parameter map, causing the substitution to fail and resulting in a malformed URL.A key constraint is that we cannot simply change
EncodeValuesto use text names, as it's correctly implemented for query parameters. Furthermore, the latter half of theEncodeURLfunction relies on thisjson_name-based map to correctly drop path parameters and formulate the final query string.Proposed Solutions
I have two potential solutions in mind, each with its own trade-offs. I'd like to get the community's input on the best approach.
Option 1: Runtime Mapping in
EncodeURLWe could implement logic within
EncodeURLitself (or a helper function) that performs a similar operation toencodeByFieldfromproto_encode.go. This new logic would iterate over the fields of the protobuf message, creating a mapping from the text name (e.g.,"name") to the JSON name (e.g.,"naming").When
EncodeURLprocesses a path variable like{sub.name}, it would use this map to look up the correct key ("sub.naming") in thequeryParamsmap generated byEncodeValues.protoc-gen-go-httpplugin.EncodeURLcall that has path parameters.proto_encode.go.Option 2: Pre-computation in
protoc-gen-go-httpAnother approach is to modify the
protoc-gen-go-httpplugin. The plugin could analyze the protobuf definitions and pre-generate the necessary text-name-to-json-name mappings. This map could then be passed as an argument toEncodeURLfrom the generated code.Request for Feedback
Which of these two options seems more viable? Or, is there a third, better solution we haven't considered? I'm looking forward to hearing everyone's thoughts on how to best resolve this issue while considering performance and backward compatibility.
A crucial point to clarify is what the official stance should be: Should HTTP path variables use
text_nameorjson_name? The current tests in@transport/http/binding/encode_test.gofor cases like{sub.naming}imply thatjson_nameis expected. However, the common convention for API path parameters is to use thesnake_casefield name (text_name).Furthermore, even if we were to decide that
json_nameis the correct approach for path variables, theprotoc-gen-go-httpplugin currently does not support generating this. This reveals a fundamental inconsistency between the framework's behavior and the code generation tooling. We need to align these.Related Issues and PRs
This problem has been discussed in several other issues and pull requests:
Beta Was this translation helpful? Give feedback.
All reactions