4

TL,DR; How should HTTP PATCH communicate the removal of resource attributes when using a FieldMask?

Google's API Design Guide for implementing standard methods states that a partial update should be achieved using a FieldMask. Below is my own contrived example to update a Test resource:

The API of the service defines a Test resource and an HTTP PATCH method (UpdateTest) for partial updates.

// A test resource.
message Test {
  string name = 1;
  google.protobuf.StringValue description = 2;
}

// Request message for update method.
message UpdateTestRequest {
  // The resource name of the test to be updated. 
  string name = 1;
  // Wrap the actual data in a data field.
  Test test = 2;
  // Field mask to support partial updates.
  google.protobuf.FieldMask update_mask = 3;
}

// Partially update a Test resource.
rpc UpdateTest(UpdateTestRequest) returns (google.protobuf.Empty) {
  option (google.api.http) = {
     patch: "v1/{name=tests/*}"
     body: "*"
   };
}

An equally contrived server implementation uses the FieldMask to merge the resources (proto messages):

updated_test = v1_test_pb2.Test(name = 'Updated')
original_test = v1_test_pb2.Test(
  name = 'Original',
  description = google.protobuf.wrappers_pb2.StringValue(
    value = 'I am Original!')
)

mask = google.protobuf.field_mask_pb2.FieldMask(
  paths = ['name', 'description']
)

# from, to
mask.MergeMessage(updated_test, original_test)
print(updated_test)

The end result is a patch Test resource:

name: "Updated"
description {
  value: "I am Original!"
}

Clearing the description field removes the property altogether:

updated_test = v1_test_pb2.Test(name = 'Updated')
updated_test.ClearField('description')

original_test = v1_test_pb2.Test(
  name = 'Original',
  description = google.protobuf.wrappers_pb2.StringValue(
    value = 'I am Original!')
)

# from, to
mask.MergeMessage(updated_test, original_test)
print(updated_test)

...the final patched Test resource would be:

name: "Updated"

Great. But how would this be encoded in the HTTP PATCH request?

The only "solution" I can think of is that, if the FieldMask contains description but the updated Test resource doesn't provide a value, it should be removed using ClearField.

This would require manually visiting each field either in the mask, or the Test messaage (or both) to determine whether the it should be removed. This seems crazy, especially if a resource has many fields.

Jack
  • 10,313
  • 15
  • 75
  • 118

0 Answers0