Skip to content
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 a bug when gRPC transcoding is used with parameterized paths #5679

Merged
merged 10 commits into from
Jun 4, 2024

Conversation

jrhee17
Copy link
Contributor

@jrhee17 jrhee17 commented May 16, 2024

Motivation:

This bug was found while analyzing the code for #5676.

Our gRPC-transcoding path parser contains logic which uses the parameter name when constructing the mapped path.
While doing so, we use an arbitrary name prefixed with a 'p' if we are unable to determine a suitable parameter name.

This can be problematic since a path may be constructed in a different way from what the user expected.

e.g. Assume we use the following path pattern:

  • path: /v1/conflict/{id=hello/*}/{p0}/test

The above path will currently be mapped to:

  • /v1/conflict/hello/:p0/:p0/test.

However, there is no guarantee that id and p0 should be equal, and hence should be built to the following path:

  • /v1/conflict/hello/:p0/:p1/test.

I propose that we prepend a '@' to the generated fields. The reasoning for this is:

As long as the above is satisfied, I think any character is fine.
I actually believe any sub-delims character can be used, so let me know if any character should be preferred more.

sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="

Modifications:

  • Modified to prepend a '@' character in front of generated fields.

Result:

  • There is no longer a bug when a user uses field p{\d} for gRPC transcoding.

@jrhee17 jrhee17 added the defect label May 16, 2024
@jrhee17 jrhee17 added this to the 1.29.0 milestone May 16, 2024
@minwoox
Copy link
Member

minwoox commented May 16, 2024

@@ -501,7 +501,8 @@ private HttpJsonTranscodingService(GrpcService delegate,
}

@Override
public HttpEndpointSpecification httpEndpointSpecification(Route route) {
public HttpEndpointSpecification
httpEndpointSpecification(Route route) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert?

@@ -174,7 +175,7 @@ public void updateMessageV1(UpdateMessageRequestV1 request, StreamObserver<Messa
@Override
public void updateMessageV2(Message request, StreamObserver<Message> responseObserver) {
final ServiceRequestContext ctx = ServiceRequestContext.current();
final String messageId = Optional.ofNullable(ctx.pathParam("message_id")).orElse("no_id");
final String messageId = Optional.ofNullable(ctx.pathParam("p0")).orElse("no_id");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like a breaking behavior.
What do you think of other approaches? e.g. prohibiting p0...pn as a parameter name or using different parameter names that a user wouldn't use(Still need a validation though).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I've updated so that we prepend a '@' in front of generated path parameters. Let me know if this doesn't make sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea. I like it. 👍

Copy link
Member

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, @jrhee17 👍 👍 👍

Copy link
Member

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, @jrhee17 👍 👍 👍

Copy link
Contributor

@ikhoon ikhoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@minwoox minwoox merged commit baa6829 into line:main Jun 4, 2024
15 checks passed
@minwoox
Copy link
Member

minwoox commented Jun 4, 2024

@jrhee17 👍 👍 👍

ikhoon added a commit to ikhoon/armeria that referenced this pull request Jun 5, 2024
minwoox pushed a commit that referenced this pull request Jun 5, 2024
…rancoding (#5729)

Motivation:

PR #5679 allows groups name in a regex path pattern to start with `@`. However, group names of a regular expression must start with a letter. https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#groupname

Modifications:

- Use `p\d` as a group name for `PathMappingType.REGEX`
  - `@p\d` will stay unchanged for `PathMappingType.PARAMETERIZED`

Result:

Fix a regression caused by #5679
Dogacel pushed a commit to Dogacel/armeria that referenced this pull request Jun 8, 2024
…e#5679)

Motivation:

This bug was found while analyzing the code for line#5676.

Our gRPC-transcoding path parser contains logic which uses the parameter name when constructing the mapped path.
While doing so, we use an arbitrary name prefixed with a 'p' if we are unable to determine a suitable parameter name.

https://github.com/line/armeria/blob/1737482b82255d2ff4728927bdf91631bf1b23e9/grpc/src/main/java/com/linecorp/armeria/server/grpc/HttpJsonTranscodingPathParser.java#L385

This can be problematic since a path may be constructed in a different way from what the user expected.

e.g. Assume we use the following path pattern:
- path: `/v1/conflict/{id=hello/*}/{p0}/test`

The above path will currently be mapped to:
- `/v1/conflict/hello/:p0/:p0/test`.

However, there is no guarantee that `id` and `p0` should be equal, and hence should be built to the following path:
- `/v1/conflict/hello/:p0/:p1/test`.

I propose that we prepend a '@' to the generated fields. The reasoning for this is:
- Protobuf doesn't allow field names other than letters, digits, underscores in identifiers.
  - https://protobuf.dev/reference/protobuf/proto3-spec/#identifiers
  - https://protobuf.dev/reference/protobuf/proto2-spec/#identifiers
- '@' is a valid character in a path segment, so it stays the same after `RequestTarget#forServer` is called. This is useful when displaying the paths in `DocService` (called by `MethodInfo`).
  - https://datatracker.ietf.org/doc/html/rfc3986#section-3.3

As long as the above is satisfied, I think any character is fine.
I actually believe any `sub-delims` character can be used, so let me know if any character should be preferred more.

>  sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
                  / "*" / "+" / "," / ";" / "="

Modifications:

- Modified to prepend a '@' character in front of generated fields.

Result:

- There is no longer a bug when a user uses field `p{\d}` for gRPC transcoding.

<!--
Visit this URL to learn more about how to write a pull request description:
https://armeria.dev/community/developer-guide#how-to-write-pull-request-description
-->
Dogacel pushed a commit to Dogacel/armeria that referenced this pull request Jun 8, 2024
…rancoding (line#5729)

Motivation:

PR line#5679 allows groups name in a regex path pattern to start with `@`. However, group names of a regular expression must start with a letter. https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#groupname

Modifications:

- Use `p\d` as a group name for `PathMappingType.REGEX`
  - `@p\d` will stay unchanged for `PathMappingType.PARAMETERIZED`

Result:

Fix a regression caused by line#5679
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants