-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Generating Multiple Path Bindings for Single gRPC Call #720
Comments
@ch3rub1m that doesn't even compile with the latest version of protoc. the |
@jon-whit How about this:
|
@ch3rub1m sorry man, I feel like we're clashing on this one... The problem with your example above is it doesn't adhere to my needs as stated above. I need parent to match |
@jon-whit I understood. I just propose a compromise between current features and what you want. |
Is there anyone else that can speak to this? I guess I'm not fundamentally understanding why
doesn't get transformed to something like
Could someone help me understand why this design choice was made? |
I'm afraid that information may be hard to come by, perhaps @achew22 will know? |
@johanbrandhorst thanks for looping in here. I've been trying to figure out a solution to this issue for a while now, so any assistance is much appreciated :). Thanks! |
@achew22 Any ideas here? |
@jon-whit unfortunately I don't have any specific ideas here. Step one is going to be create a failing test case. Do you think you could send in a PR that demonstrates this reliably? |
@achew22 maybe I misunderstand.. The example above would be one such case..? What do you mean? |
Does the following solve the issue? grpc-gateway/examples/internal/proto/examplepb/a_bit_of_everything.proto Lines 500 to 511 in 1dd92c9
|
This follows the design of the Google gRPC guidelines that they use for their own APIs. https://cloud.google.com/apis/design The path parameters are described in http.proto and in RFC 6570 By using a "name" based syntax that qualifies all identifiers, it allows fields that reference more than one potential type of entity to specify that. For example, if you take Google "Resource Manager" API, it has a top level element called Organization, a branch structure called Folder, and a leaf called Project. Project and Folder both have a "parent" field that is the "name" of the Organization or Folder that is the parent for the given resource. If they had used IDs everywhere, they would have had a "parent_organization_id" and a "parent_folder_id" fields with some constraint around them. Not a great alternative Unfortunately the group that manages the OpenAPI specification has not yet agreed to support RFC 6570 so currently they could not support this type of syntax. See (and related issues): That means that if we would like to support this style of syntax, |
Thanks for all of that context, that makes a lot of sense! In particular the last part is very useful for anyone who wants to tackle this issue - it sounds like it should be totally possible, though we'll need to figure out how to parse these variables in the openapi generator. We obviously do the parsing already in the grpc-gateway generator but I'm not sure if it's there in the openapi one today. |
So I've been reading the source and debugging a lot more recently and reading old issues. It appears that Issue #702 made a change that doesn't strip the "=organizations/*" from the path parameter if its called "name" or "parent". Specifically line 820 in protoc-gen-openapiv1/internal/genopenapi/template.go, the "isResourceName" function. The original issue was raised because if you have two endpoints that share the stripped name, they couldn't be represented in OpenAPI as the path and method is the unique identifier for the endpoint. For example if you had two GET endpoints defined as: Those would both resolve to So @rcgoodfellow when he implemented the fix, just said "when the path parameter is called 'name' or 'parent', then don't strip the qualifier". I feel like this solution was actually not an appropriate one as it technically is what caused #407 (i.e. we now have an invalid swagger specification because it has path parameters specified using a syntax that OpenAPI does not support (i.e. Unfortunately I can't really think of a way that it could be fixed that isn't some other hack. We could rename the path parameter to a different name (maybe add a _1 suffix) when another endpoint is found with the same stripped name. This would only really be a change to the protoc-gen-openapiv2. However we still have the problem of tools sending the escaped "/" (i.e. "$2F") based on the swagger specification (as all path parameters have to be escaped before they're replaced). Right now we have the newly added Unescaping configuration however it currently doesn't unescape path segments before it attempts to divide them (Line 268 in runtime/mux.go) so we'd have to do additional work there as well. |
@yinzara I believe I've been mistagged here, my contributions to this repository to not appear to be related to the issues you are referencing. |
Totally apologize @rcgoodfellow , it was @ch3rub1m that changed the lines I was looking at (yours were later in the file). I've got a PR now #2461 Love some feedback! |
I've read this and related issues with great interest, as we also have gRPC APIs that follows the Google gRPC API guidelines with the resource name syntax (e.g. ( First, I've found what looks like a bug I'm happy to report in a separate issue: If I have multiple services in the same API with similar prefixes (e.g. Second, I'd like to to get input to some thoughts on the original problem described in this issue. I would really like to have a OpenAPI file that lists the different paths (using OPs example):
I see two immediate problems with generating this:
To solve this, would it make sense to allow specifying the OpenAPI friendly paths and path parameters in the
As a path may contain multiple |
Thanks for your thoughtful input! I noticed you raised #2489 for the first issue, thanks for that! As for the proposal, I worry about having another source of truth for the template path and parameters, with obvious maintenance issues. I don't think this would be the first such case but we really should exhaust other possibilities before compromising there. I'm confused by the problem statement too, in the example |
Thanks for the feedback! My idea is not in ideal, it's merely a workaround the lack of support for this in the standards (OpenAPI and gRPC HTTP mapping). I get your idea with using different gRPC fields for the alternative paths. That will require a change to any gRPC message to use in this way, as OPs example would have to be changed to (possibly put the alternative parent ids in a
This puts an extra burden on the gRPC service implementation that I think should be possible to solve with parameter mapping. Also, if you do the above, the path is very short to ignore the Google API guidelines completely:
However, this doesn't solve the problem on how to generate OpenAPI specification when following the Google API guidelines for resource names. Another possibility is to extend |
I see the problem. I'm hesitant to adopt something like this without a clear need from the community - it would be a pretty dangerous change to make and I want to know that there's enough benefit to take on the cost, if it means having to add this alternative path specification option. Let me know if you can think of some other way to solve this though! |
I have implemented a simpler suggestion in PR #2562 |
I seem to have missed a concept in the Google AIPs that can be used to generate paths based on resource names - the Examples are provided in AIP 122. Note that there are two variants that must be supported, depending on when the resource type is used in request message, and when the request only contains a reference (by resource name) to the actual resource (option It is still not possible to convey type information, description, or examples of the individual path segments though. Would it make sense to add a runtime option to |
Would we need to add an option? Is it something we could just turn on? Do you think it would risk breaking users? |
I have a feeling nobody are using |
@yinzara I'd be very happy to get your input on the idea to generate path parameters from |
Yeah and I think this is an unrelated issue to this issue. If we want to support `google.api.resource` annotations instead of using `google.api.http` then we should have a separate defect opened.
From: Øyvind Matheson Wergeland ***@***.***>
Date: Monday, March 28, 2022 at 8:00 AM
To: grpc-ecosystem/grpc-gateway ***@***.***>
Cc: Matthew Vance ***@***.***>, Comment ***@***.***>
Subject: Re: [grpc-ecosystem/grpc-gateway] Generating Multiple Path Bindings for Single gRPC Call (#720)
Would we need to add an option? Is it something we could just turn on? Do you think it would risk breaking users?
I have a feeling nobody are using protoc-gen-openapiv2 with google.api.resource annotations, since nobody suggested to use that previously. It wouldn't break our flow at least, that's for sure!
—
Reply to this email directly, view it on GitHub<#720 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AWEFJMX3XESEGOHQZEOY27DVCHCO7ANCNFSM4FOT23AQ>.
You are receiving this because you commented.Message ID: ***@***.***>
|
The way I understand this is that See https://github.com/googleapis/googleapis/blob/f59df18148fd44d2ead03109c391a742a9c99e48/google/api/resource.proto#L75-L83 for an example on how to apply multiple resource paths for a resource. OPs example would need to be expanded to something like this (note that I'm not sure how to support an empty parent):
This should generate the following paths in the OAS file:
An implementation will have to handle several cases, e.g. for supporting multiple parent resources, each alternative path must be matched with the binding, and for parent references using multiple parent types, the path matching must be on the pattern prefix of the alternative patterns for the Expanding OPs example with
This should generate the following paths in the OAS file:
(EDIT: corrected typo |
So that makes no sense to me. That would mean that you'd have to have translate the GetRoleRequest message into 3 separate OpenAPI resources: one for each API endpoint that could be supported by it as you would no longer have a That also breaks the whole abstraction as "tenant" and "role" really don't exist. They're just a name for a placeholder in the URL/resource name. You aren't supposed to deconstruct resource names into their parts. They are a name and not an id for a reason. There is no way to have |
@yinzara thank you for your input! I think there would still only be one resource (
So from a REST consumer point of view, I think it is preferable to rather expand the path than work with these patterns, and |
I disagree. I think you're making assumptions about the consumer of your API. When you use resource names in an API, you expect to be passing those resource names around and for fields of entities to use those resource names when referring to other entities. You shouldn't be parsing those names into those parts and then passing those parts to your APIs as you don't have enough information to know if your parsing is actual valid.
If I have a RoleBinding message that has a https://cloud.google.com/apis/design/resource_names#resource_name_as_string |
When testing tools used to render documentation from OAS files(readme.com and Swagger UI), we noticed that path parameters containing OpenAPI 2 doesn't include Allowing This implies that the current approach in My conclusion so far is that we'll most likely do some post processing on the generated OAS file to replace path parameters with |
Thanks for the research there, do you think we need to make a behavioral change in the generator? |
Yes I do think that, but that takes us some steps back to previous discussions - we need to introduce annotations to specify the extra path parameters per http binding, including description and type information. I think this is a fairly large extension of the generator. |
Introducing more annotations is leaving a bad taste in my mouth, it's already complex as it is. Right now my main concern is that we generate valid OAS documents. Should we revert the previous changes to behavior? |
Sorry, let me rephrase; the OAS file isn't syntactically invalid, but when used on path parameters that contains As I understand it, there are no previous version of the generator that supports path parameters with One possibility is to log a warning in these cases, but that doesn't solve the problem on how to generate a valid and usable OAS file based on a proto file when following the Google AIPs. As outlined above, it looks like it may be possible to get the path parameter names from We're currently working around this by providing a custom mapping file and post-processing the generated OAS files with a script that replaces the path parameters. This way, we avoid hand coding the bulk of the OAS files, so the generator is still usable in our pipeline. |
I see, thanks for the clarification. So the attempts to fix the handling of parameters containing
What do you think? |
I'm leaning towards calling it a day. I would be very happy if the openapiv2 generator could produce an OAS that's directly usable, but for us it's currently not worth the effort. I'd rather spend some time fixing other bugs within the current behaviour. Also, |
I agree. Would you be interested in adding a warning log for these cases, so that a user that runs into this issue can understand why it may not work as expected? |
Done in PR #2697 |
OpenAPI 3.1 explicitly forbids
|
I have a field in a protobuf message called "parent". It looks like this:
And a gRPC method that looks like this:
The parent can take the form
organizations/<org_id>
ortenants/<tenant_id>
or it can be empty. I'd like the generated swagger definitions to match all three. For example:GET /auth/iam/roles
GET /auth/iam/organizations/<org_id>/roles
GET /auth/iam/tenants/<tenant_id>/roles
The swagger generator currently only generates two paths:
GET /auth/iam/roles
GET /auth/iam/{parent}/roles
{parent}
only matches a single path parameter, and since the parent can include a slash you can't get a match.What's the correct way of doing this?
The text was updated successfully, but these errors were encountered: