Skip to content

AEP-0134 Linter Rules

Update methods- HTTP body

This rule enforces that all Update RPCs set the HTTP body to the resource, as mandated in AEP-134.

This rule looks at any method whose name begins with Update, and complains if the HTTP body field is not set to the resource being created.

Incorrect code for this rule:

// Incorrect.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "*" // This should be "book".
};
}

Correct code for this rule:

// Correct.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
}

If you need to violate this rule, use a leading comment above the method. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::http-body=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "*"
};
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- PATCH HTTP verb

This rule enforces that all Update RPCs use the PATCH HTTP verb, as mandated in AEP-134.

This rule looks at any message matching beginning with Update, and complains if the HTTP verb is anything other than PATCH. It does check additional bindings if they are present.

Incorrect code for this rule:

// Incorrect.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
put: "/v1/{book.name=publishers/*/books/*}" // Should be `patch:`.
body: "book"
};
}

Correct code for this rule:

// Correct.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
}

If you need to violate this rule, use a leading comment above the method. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::http-method=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
put: "/v1/{book.name=publishers/*/books/*}" // Should be `patch:`.
body: "book"
};
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- HTTP URI path field

This rule enforces that all Update RPCs map the path field from the resource object to the HTTP URI, as mandated in AEP-134.

This rule looks at any message matching beginning with Update, and complains if the path variable from the resource (not the request message) is not included in the URI. It does check additional bindings if they are present.

Additionally, if the resource uses multiple words, it ensures that word separation uses snake_case.

Incorrect code for this rule:

// Incorrect.
rpc UpdateBookRequest(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{book.path=publishers/*/books/*}" // Should be `path`
body: "book"
};
}

Correct code for this rule:

// Correct.
rpc UpdateBookRequest(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{path=publishers/*/books/*}"
body: "book"
};
}

If you need to violate this rule, use a leading comment above the method. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::http-uri-path=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
rpc UpdateBookRequest(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{book.path=publishers/*/books/*}"
body: "book"
};
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Method signature

This rule enforces that all Update standard methods have a google.api.method_signature annotation with an appropriate value, as mandated in AEP-134.

This rule looks at any method beginning with Update, and complains if the google.api.method_signature annotation is missing, or if it is set to an value other than "{resource},update_mask. Additional method signatures, if present, are ignored.

Incorrect code for this rule:

// Incorrect.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
// A google.api.method_signature annotation should be present.
}
// Incorrect.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
// Should be "book,update_mask".
option (google.api.method_signature) = "book";
}

Correct code for this rule:

// Correct.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.method_signature) = "book,update_mask";
}

If you need to violate this rule, use a leading comment above the method. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::method-signature=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.method_signature) = "book";
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Allow missing

This rule enforces that all Update standard methods for declarative-friendly resources ([AEP-128][]) have a bool allow_missing field, as mandated in AEP-134.

This rule looks at any message matching Update*Request and complains if the bool allow_missing field is not found.

Important: This rule is only active if the corresponding resource is designated as declarative-friendly.

Incorrect code for this rule:

// Incorrect.
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
// Needs `bool allow_missing`
}

Correct code for this rule:

// Correct.
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
bool allow_missing = 3;
}

If you need to violate this rule, use a leading comment above the field. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::request-allow-missing-field=disabled
// aep.dev/not-precedent: We really need this field because reasons. --)
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
}

Note: Violations of declarative-friendly rules should be rare, as tools are likely to expect strong consistency.

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Mask field

This rule enforces that all Update standard methods have a field in the request message for the field mask, as mandated in AEP-134.

This rule looks at any message matching Update*Request and complains if the update_mask field has any type other than google.protobuf.FieldMask.

Incorrect code for this rule:

// Incorrect.
message UpdateBookRequest {
Book book = 1;
// Field type should be `google.protobuf.FieldMask`.
string update_mask = 2;
}

Correct code for this rule:

// Correct.
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
}

If you need to violate this rule, use a leading comment above the message (if the resource field is missing) or above the field (if it is improperly named). Remember to also include an aep.dev/not-precedent comment explaining why.

message UpdateBookRequest {
Book book = 1;
// (-- api-linter: core::0134::request-mask-field=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
string update_mask = 2;
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Mask field

This rule enforces that all Update standard methods have a field in the request message for the field mask, as mandated in AEP-134.

This rule looks at any message matching Update*Request and complains if it can not find a field named update_mask.

Incorrect code for this rule:

// Incorrect.
// `google.protobuf.FieldMask update_mask` is missing.
message UpdateBookRequest {
Book book = 1;
}

Correct code for this rule:

// Correct.
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
}

If you need to violate this rule, use a leading comment above the message. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::request-mask-required=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
message UpdateBookRequest {
Book book = 1;
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Request message

This rule enforces that all Update RPCs have a request message name of Update*Request, as mandated in AEP-134.

This rule looks at any message matching beginning with Update, and complains if the name of the corresponding input message does not match the name of the RPC with the suffix Request appended.

Incorrect code for this rule:

// Incorrect.
rpc UpdateBook(Book) returns (Book) { // Should be `UpdateBookRequest`.
option (google.api.http) = {
patch: "/v1/{name=publishers/*/books/*}"
body: "*"
};
}

Correct code for this rule:

// Correct.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
}

If you need to violate this rule, use a leading comment above the method. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::request-message-name=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
rpc UpdateBook(Book) returns (Book) { // Should be `UpdateBookRequest`.
option (google.api.http) = {
patch: "/v1/{name=publishers/*/books/*}"
body: "*"
};
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Name field

This rule enforces that all Update standard methods have a string path field in the request message, as mandated in AEP-134.

This rule looks at any message matching Update*Request and complains if the path field is missing.

Incorrect code for this rule:

// Incorrect.
message UpdateBookRequest {
// Field path should be `path`.
string book = 1;
}

Correct code for this rule:

// Correct.
message UpdateBookRequest {
string path = 1;
}

If you need to violate this rule, use a leading comment above the message. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::request-path-required=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
message UpdateBookRequest {
string book = 1;
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Required fields

This rule enforces that all Update standard methods do not have unexpected required fields, as mandated in AEP-134.

This rule looks at any message matching Update*Request and complains if it comes across any required fields other than:

Incorrect code for this rule:

// Incorrect.
message UpdateBookRequest {
Book book = 1 [(google.api.field_behavior) = REQUIRED];
// Non-standard required field.
bool allow_missing = 2 [(google.api.field_behavior) = REQUIRED];
}

Correct code for this rule:

// Correct.
message UpdateBookRequest {
string path = 1 [(google.api.field_behavior) = REQUIRED];
Book book = 2 [(google.api.field_behavior) = REQUIRED];
bool allow_missing = 3 [(google.api.field_behavior) = OPTIONAL];
}

If you need to violate this rule, use a leading comment above the field. Remember to also include an aep.dev/not-precedent comment explaining why.

message UpdateBookRequest {
Book book = 1 [(google.api.field_behavior) = REQUIRED];
// (-- api-linter: core::0134::request-required-fields=disabled
// aep.dev/not-precedent: We really need this field to be required because
// reasons. --)
bool allow_missing = 2 [(google.api.field_behavior) = REQUIRED];
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Resource field

This rule enforces that all Update standard methods have a field in the request message for the resource itself, as mandated in AEP-134.

This rule looks at any message matching Update*Request and complains if the field of the resource’s type is not named properly.

Incorrect code for this rule:

// Incorrect.
message UpdateBookRequest {
// Field name should be `book`.
Book payload = 1;
google.protobuf.FieldMask update_mask = 2;
}

Correct code for this rule:

// Correct.
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
}

If you need to violate this rule, use a leading comment above the field. Remember to also include an aep.dev/not-precedent comment explaining why.

message UpdateBookRequest {
// (-- api-linter: core::0134::request-resource-field=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
Book payload = 1;
google.protobuf.FieldMask update_mask = 2;
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Resource field

This rule enforces that all Update standard methods have a field in the request message for the resource itself, as mandated in AEP-134.

This rule looks at any message matching Update*Request and complains if there is no field of the resource’s type with the expected field name.

Incorrect code for this rule:

// Incorrect.
// `Book book` is missing.
message UpdateBookRequest {
google.protobuf.FieldMask update_mask = 2;
}

Correct code for this rule:

// Correct.
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
}

If you need to violate this rule, use a leading comment above the message. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::request-resource-required=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
message UpdateBookRequest {
google.protobuf.FieldMask update_mask = 2;
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Unknown fields

This rule enforces that all Update standard methods do not have unexpected fields, as mandated in AEP-134.

This rule looks at any message matching Update*Request and complains if it comes across any fields other than:

Incorrect code for this rule:

// Incorrect.
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
string library_id = 3; // Non-standard field.
}

Correct code for this rule:

// Correct.
message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
}

If you need to violate this rule, use a leading comment above the field. Remember to also include an aep.dev/not-precedent comment explaining why.

message UpdateBookRequest {
Book book = 1;
google.protobuf.FieldMask update_mask = 2;
// (-- api-linter: core::0134::request-unknown-fields=disabled
// aep.dev/not-precedent: We really need this field because reasons. --)
string library_id = 3; // Non-standard field.
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Long-running Update

This rule enforces that declarative-friendly update methods use long-running operations, as mandated in AEP-134.

This rule looks at any Update method connected to a resource with a google.api.resource annotation that includes style: DECLARATIVE_FRIENDLY, and complains if it does not use long-running operations.

Incorrect code for this rule:

// Incorrect.
// Assuming that Book is styled declarative-friendly, UpdateBook should
// return a long-running operation.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
}

Correct code for this rule:

// Correct.
// Assuming that Book is styled declarative-friendly...
rpc UpdateBook(UpdateBookRequest) returns (google.longrunning.Operation) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
option (google.longrunning.operation_info) = {
response_type: "Book"
metadata_type: "OperationMetadata"
};
}

If you need to violate this rule, use a leading comment above the message. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::response-lro=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
}

Note: Violations of declarative-friendly rules should be rare, as tools are likely to expect strong consistency.

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Resource response message

This rule enforces that all Update RPCs have a response message of the resource, as mandated in AEP-134.

This rule looks at any message matching beginning with Update, and complains if the name of the corresponding output message does not match the name of the RPC with the prefix Update removed.

It also permits a response of google.longrunning.Operation; in this case, it checks the response_type in the google.longrunning.operation_info annotation and ensures that it corresponds to the name of the RPC with the prefix Update removed.

Incorrect code for this rule:

// Incorrect.
// Should be `Book`.
rpc UpdateBook(UpdateBookRequest) returns (UpdateBookResponse) {
option (google.api.http) = {
patch: "/v1/{book.path=publishers/*/books/*}"
body: "book"
};
}

Correct code for this rule:

// Correct.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.path=publishers/*/books/*}"
body: "book"
};
}

Incorrect code for this rule:

// Incorrect.
rpc UpdateBook(UpdateBookRequest) returns (google.longrunning.Operation) {
option (google.api.http) = {
patch: "/v1/{book.path=publishers/*/books/*}"
body: "book"
};
option (google.longrunning.operation_info) = {
response_type: "UpdateBookResponse" // Should be "Book".
metadata_type: "UpdateBookMetadata"
};
}

Correct code for this rule:

// Correct.
rpc UpdateBook(UpdateBookRequest) returns (google.longrunning.Operation) {
option (google.api.http) = {
patch: "/v1/{book.path=publishers/*/books/*}"
body: "book"
};
option (google.longrunning.operation_info) = {
response_type: "Book"
metadata_type: "UpdateBookMetadata"
};
}

If you need to violate this rule, use a leading comment above the method. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::response-message-name=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
rpc UpdateBook(UpdateBookRequest) returns (UpdateBookResponse) {
option (google.api.http) = {
patch: "/v1/{book.path=publishers/*/books/*}"
body: "book"
};
}

If you need to violate this rule for an entire file, place the comment at the top of the file.

Update methods- Synonym check

This rule enforces that single-resource creation methods have names beginning with Update, as mandated in AEP-134.

This rule looks at any message with names similar to Update, and suggests using Update instead. It complains if it sees the following synonyms:

  • Patch
  • Put
  • Set

Incorrect code for this rule:

// Incorrect.
rpc PatchBook(PatchBookRequest) returns (Book) { // Should be `UpdateBook`.
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
}

Correct code for this rule:

// Correct.
rpc UpdateBook(UpdateBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
}

If you need to violate this rule, use a leading comment above the method. Remember to also include an aep.dev/not-precedent comment explaining why.

// (-- api-linter: core::0134::synonyms=disabled
// aep.dev/not-precedent: We need to do this because reasons. --)
rpc PatchBook(PatchBookRequest) returns (Book) {
option (google.api.http) = {
patch: "/v1/{book.name=publishers/*/books/*}"
body: "book"
};
}

If you need to violate this rule for an entire file, place the comment at the top of the file.