-
Notifications
You must be signed in to change notification settings - Fork 169
Description
https://google.aip.dev/124#multiple-many-to-one-associations explains a resource can have multiple parents, but one parent must be the canonical one. I take this to mean that if we have a resource Book canonically at /publishers/{publisher}/books/{book}, it is permissable to have a ListGenreBooks at GET /genres/{genre}/books which returns Books.
Full example in protobuf
syntax = "proto3";
package foo;
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
// My Service
service TestThing {
// List Books
rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {
option (google.api.http) = {get: "/{parent=publishers/*}/books"};
option (google.api.method_signature) = "parent";
}
// List Books by genre
rpc ListGenreBooks(ListGenreBooksRequest) returns (ListGenreBooksResponse) {
option (google.api.http) = {get: "/{parent=genre/*}/books"};
option (google.api.method_signature) = "parent";
}
}
// Book
message Book {
option (google.api.resource) = {
type: "library.googleapis.com/Book"
pattern: "publishers/{publisher}/books/{book}"
singular: "book"
plural: "books"
};
// Name
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
}
// List books
message ListBooksRequest {
// Format: publishers/{publisher}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {child_type: "library.googleapis.com/Book"}
];
// Page size
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Page token
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
// List books
message ListBooksResponse {
//books
repeated Book books = 1;
// next page token
string next_page_token = 2;
}
// List genre books
message ListGenreBooksRequest {
// Format: genre/{genre}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {child_type: "library.googleapis.com/Book"}
];
// Page size
int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
// Page token
string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}
// List books
message ListGenreBooksResponse {
// Books
repeated Book books = 1;
// next page token
string next_page_token = 2;
}The linter fails this with
List responses should only contain fields explicitly described in AIPs. https://linter.aip.dev/132/response-unknown-fields (buf-plugin-google-api)
on the ListGenreBooksResponse repeated Book books = 1; line. I considered maybe the field should be called genre_books, but that fails with another error
Paginated resource response field name should be the snake_case form of the resource type plural defined in the `(google.api.resource)` annotation. https://linter.aip.dev/158/response-plural-first-field (buf-plugin-google-api)
So my query is, do I understand the guidance around multi-parent resources correctly? And if so, what is the idiomatic field name for the repeated resource in ListGenreBooksResponse message? And ultimately, is the linter wrong in this case? (I tried to find an example of this in the googleapis repo, but couldn't figure out a good way to search for this situation).