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

REST PUT request only passes fields to update #379

Open
hangll opened this issue May 5, 2017 · 21 comments
Open

REST PUT request only passes fields to update #379

hangll opened this issue May 5, 2017 · 21 comments

Comments

@hangll
Copy link

hangll commented May 5, 2017

I'm trying to export REST APIs and the problem is that in my PUT request, client usually tries to pass only fields to update, but the generated proto will set all the other fields to its default value. I have no way to tell which fields to update.

Of course I can restrict client to always pass the full object, but is there better way to do this?

@tamalsaha
Copy link
Collaborator

@hangll , on your server side, you could check for fields that have values set (aka, non-default value) and then only update those. That is what we do for our service.

@hangll
Copy link
Author

hangll commented May 5, 2017

@tamalsaha that is hard. How can you tell if a bool value is updated to false or is not set?

@tamalsaha
Copy link
Collaborator

@hangll you could define your boolean variables in a way that settings true will require update. Or, you could use a tr-state variable.

@evolsnow
Copy link

FieldMask may be helpful, and it would be wonderful if grpc-gateway could generate the mask from REST API.

@achew22
Copy link
Collaborator

achew22 commented Jan 10, 2018

The semantics for PUT are that you will include the entire contents of the file. If this were going to be supported it is would have to be under the verb PATCH

@adematte
Copy link

Hello, we have our own implementation to map REST -> GRPC in nodejs and are evaluating if we could use/support this project instead. One of the things we are doing is populating the fieldMask automatically based on the json request. Using a fieldmask is the de facto GRPC approach for "patching" and I can see real value in it being handled by the api gateway and not having it being generated by the REST clients.

Is this something that would make sense for this projet core features, or is this something that should be handled via a custom middleware of some kind?

@achew22
Copy link
Collaborator

achew22 commented Jan 31, 2018

@adematte I think that is the way to go. An auto populated fieldMask is, I think, the way to do this. That said, I'm not sure what the best way to go about doing that would be. Do you have a magically named fieldmask? Is there a part of the spec that allows for that that I've missed?

@wora
Copy link
Contributor

wora commented Jan 31, 2018

I worked on proto3, gRPC, and Google API Design Guide. This is a well known feature request. I would recommend gRPC Gateway implement this feature.

When you perform a partial update against a Google API, you can explicitly pass the field mask as HTTP header X-Goog-FieldMask, see https://cloud.google.com/apis/docs/system-parameters. gRPC Gateway can auto generate this header if the request method is PATCH and this header is absent, based on the presence of JSON fields. I think the semantics is very easy to understand and also easy to use.

@adematte
Copy link

adematte commented Jan 31, 2018

@achew22 currently what we are doing is this:

  • look for a PATCH http route
  • look for a property of type google.protobuf.FieldMask in the request message
  • autopopulate it based on the json request (we only use the body for this)

As a reminder, FieldMasks can also be used for partial responses but we don't handle those in any particular way. We just handle the partial update (patch) scenarios.

@adematte
Copy link

adematte commented Jan 31, 2018

@wora if I am not mistaken the document you are pointing to, refers to fieldmasks used for response filtering. I don't think it would be a good idea to hijack the X-Goog-FieldMask http header when using PATCH requests don't you agree?

@wora
Copy link
Contributor

wora commented Jan 31, 2018 via email

@adematte
Copy link

do we even need to pass this through an http header though instead of just using the json body? The only rational I see regarding the http header is that this way we do not affect the json request payload. Any other advantages to the use of a header?

@achew22
Copy link
Collaborator

achew22 commented Feb 16, 2018

I see a few advantages to putting it in a header

  1. it will work even if the request proto doesn't have a FieldMask field embedded in it
  2. what do you do if there are multiple FieldMasks?
  3. It doesn't pollute the exposed API to swagger. If you add a FieldMask, now your public API has an extra field that you have to explain to people doesn't do anything because it is overwritten by a proxy server.

@wora
Copy link
Contributor

wora commented Feb 16, 2018

@adematte I think you are correct. Google API Design Guide recommends every PATCH method has an update_mask in the request message. We can auto populate it. The request message should have at most one FieldMask field at the top level. Otherwise, the proxy should do nothing.

@dmacthedestroyer
Copy link
Contributor

Hi all, I'm looking to rehydrate the PATCH debate -- is there still an appetite for this? If so, I think I can provide development effort for it. This is the current design I see:

HTTP PATCH request comes in
if the gRPC request message has exactly 1 FieldMask field:
set the request FieldMask field based on HTTP request JSON body

Areas that still need discussing:

  • What to do about the generated Swagger file? Should it be modified to exclude FieldMask?

@achew22
Copy link
Collaborator

achew22 commented Jun 1, 2018 via email

@adematte
Copy link

adematte commented Jun 7, 2018 via email

@kibertoad
Copy link

@dmacthedestroyer What about GET requests with optional parameters? This could be useful for a search.

@dmacthedestroyer
Copy link
Contributor

That's a good question, and one we've battled with in our organization. I'm inclined to leave that as a separate conversation so as to not make this issue too ambitious :)

How's that sound? Maybe open a seperate issue to discuss that? I think it'd require a deeper look into what gRPC recommends for List commands and abiding by that first and foremost.

@kibertoad
Copy link

@dmacthedestroyer Sure, created #698

This was referenced Nov 13, 2018
@ivucica
Copy link
Collaborator

ivucica commented Jan 20, 2019

One way of handling this is probably switching to syntax proto2; and checking whether a struct field is nil before dereferencing it.

If the field is nil, then the proto field was not set, and it was not passed to grpc-gateway.

If the field is not nil, then the value was set.

I'm using this to skip updating fields that the user has not passed in the proto message and in JSON. This is good enough for me, even if using FieldMasks (see
#812) might have advantages. (I can't think of any right now, though I'm sure there are some!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants