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

support one-ofs in body #570

Conversation

jhump
Copy link
Contributor

@jhump jhump commented Mar 9, 2018

I was curious if this was something that might be accepted as a patch, and (if so) if I'm on the right track.

I must admit, I don't really understand how the FieldPath stuff really works. I mean, I think I see how it's supposed to work. But it looks like actually using nested elements (e.g. foo.bar.baz) would always result in nil dereference panic since the actual request's fields have zero values. So, in this example, field protoReq.Foo, presumably a pointer to message struct, would be nil, and thus unmarshaling code would traverse a nil pointer trying to compute &protoReq.Foo.Bar.Baz (even if it were just one level of nesting: &protoReq.Foo.Bar).

So, in this patch, I didn't really bother examining the entire path for oneofs and only look at the first field. Does that seem sane?

BTW, the whole reason I was exploring this patch is to support an API idiom like so:

message IndividualId {
  oneof id {
    string uid = 1;
    int64 user_id = 2;
  }
}

service Users {
  rpc QueryIndividual (IndividualId) returns (IndividualDetails) {
    option (google.api.http) = {
      get: "/users/v1/individual/{uid}"
      additional_bindings {
        get: "/users/v1/user/{user_id}"
      }
    };
  }
}

@achew22
Copy link
Collaborator

achew22 commented Apr 9, 2018

Hey @jhump, sorry for the very slow response on this. Let me give you an update on the state of affairs around here. I have a PR that I'm going to be submitting soon that is the beginning of the breaking change window for a 2.0 release. As such I've been focusing on getting that done and not really tending to the PR queue. Sorry about that.

This looks like a really good PR to have included and I don't mind at all that it doesn't completely solve the recursive form of the problem -- the perfect is the enemy of the good after all. One thing I noticed is that you've hit a bug in our CI system. I am curious. Do you think you could rebase this PR after that commit and see if the CI system blows up?

I would have expected this to fail since you changed the template which should make the examples directory (which is a dir of goldens) not match. To fix this, you can run make examples to update the goldens and then the PR should pass CI.

Thanks so much for your hard work!

@achew22
Copy link
Collaborator

achew22 commented Apr 26, 2018

Friendliest of pings

@jhump jhump force-pushed the jh/support-oneof-in-body-and-path-param branch 2 times, most recently from a0a10b5 to 2bed8fd Compare April 30, 2018 20:54
@jhump
Copy link
Contributor Author

jhump commented Apr 30, 2018

Looks like this has already been fixed for path params but is still broken for the body. The current code produces Go code that can't compile if a oneof is specified as the body. I think I see how to address that.

@jhump jhump force-pushed the jh/support-oneof-in-body-and-path-param branch from 2bed8fd to f2d5146 Compare April 30, 2018 21:56
@@ -207,6 +207,7 @@ var (
var protoReq {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
var metadata runtime.ServerMetadata
{{if .Body}}
{{.Body.AssignableExprPrep "protoReq"}}
if err := marshaler.NewDecoder(req.Body).Decode(&{{.Body.AssignableExpr "protoReq"}}); err != nil && err != io.EOF {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is what generated bad code. The AssignableExpr would have emitted the prep statements, which would get incorrectly inlined in the call to Decode. By splitting out the prep statements, it now generates working code.

// AssignableExprPrep returns preparation statements for an assignable expression to assign a value
// to the target field. The go expression of the method request object is "msgExpr". This is only
// needed for field paths that contain oneofs. Otherwise, an empty string is returned.
func (p FieldPath) AssignableExprPrep(msgExpr string) string {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I essentially forked AssignableExpr, with this method preserving just the preparations and the other only emitting the last line, the actual field ref.

@jhump jhump changed the title support one-ofs in body and path params support one-ofs in body Apr 30, 2018
@jhump
Copy link
Contributor Author

jhump commented Apr 30, 2018

@achew22, PTAL

@jhump
Copy link
Contributor Author

jhump commented May 1, 2018

The build breakage was bad timing - I pushed just after protobuf merged their dev branch to master. I will rebase this PR after #636 lands, to see if I can get the tests to go green.

@achew22
Copy link
Collaborator

achew22 commented May 1, 2018

@yugui Have you seen this?

@jhump jhump force-pushed the jh/support-oneof-in-body-and-path-param branch from f2d5146 to 578d2a7 Compare May 1, 2018 12:24
@jhump jhump force-pushed the jh/support-oneof-in-body-and-path-param branch from 6740b64 to 26d004c Compare May 1, 2018 20:00
@codecov-io
Copy link

Codecov Report

Merging #570 into master will decrease coverage by 0.43%.
The diff coverage is 36.84%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #570      +/-   ##
==========================================
- Coverage   58.88%   58.44%   -0.44%     
==========================================
  Files          30       30              
  Lines        2853     2871      +18     
==========================================
- Hits         1680     1678       -2     
- Misses       1010     1030      +20     
  Partials      163      163
Impacted Files Coverage Δ
protoc-gen-grpc-gateway/gengateway/template.go 54.9% <ø> (ø) ⬆️
protoc-gen-grpc-gateway/descriptor/types.go 40.47% <36.84%> (-8.6%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c2b051d...26d004c. Read the comment docs.

@jhump
Copy link
Contributor Author

jhump commented May 21, 2018

@achew22 or @yugui: ping?

@tmc
Copy link
Collaborator

tmc commented Jun 19, 2018

Code looks LGTM. My only comment is that I'd like a test case that demonstrates oneof population from body.

@apeletz512
Copy link

@jhump @achew22 @yugui @tmc Any progress here?

@johanbrandhorst
Copy link
Collaborator

Bump, need a rebase and a test case please.

@jhump
Copy link
Contributor Author

jhump commented Sep 20, 2018

@johanbrandhorst, sorry, I've been busy, and we've since re-formulated our proto to not actually need this feature. So, if this seems like a valuable contribution, someone else will have to take it over.

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.

7 participants