AIP-4210
Client library generators
API guidelines exist in order to promote simple, intuitive, and consistent APIs. Users familiar with APIs that generally adhere to AIP guidance are able to take what they learn in prior APIs and apply it to new ones.
Client libraries provide a mechanism for users to get started with APIs more quickly, by simplifying common concerns (such as auth) and by a language-native way to call API endpoints and receive language-native responses. However, for these libraries to provide the most value, they also must be simple, intuitive, and consistent. Code generators provide a means for producing consistent client libraries at scale.
Code generators following the standards in these AIPs are known as "generated API client generators", or GAPIC generators for short. The resulting libraries are colloquially called GAPICs.
Note: Because this AIP describes guidance and requirements in a
language-neutral way, it uses generic terminology which may be imprecise or
inappropriate in certain languages or environments (for example, the use of the
term class even though languages such as Go do not have classes). This AIP's
particular use of vocabulary is best understood as an explanation of
principles, and precise adherence to exact vocabulary in this AIP is not an
expectation.
Guidance
Protobuf plugins
Code generators must be implemented as plugins to protoc, the protocol
buffer compiler. The plugin system allows plugins to be written in any
language, and plugins should ordinarily be written in the language being
targeted, in order to take advantage of in-language tooling, and to ensure that
experts in the target environment are able to meaningfully contribute.
protocexpects plugins to be an executable in$PATH, and namedprotoc-gen-{plugin_name}, corresponding to the--{plugin_name}_outoption sent to theprotocexecutable.- For a plugin creating client libraries for a specific language, the option
name should follow the convention
--{lang}_gapic_out(meaning the corresponding plugin executable is namedprotoc-gen-{lang}_gapic).
- For a plugin creating client libraries for a specific language, the option
name should follow the convention
- Plugins must accept a serialized
CodeGeneratorRequestobject (defined inplugin.proto) onstdin; the bulk of this is a series ofFileDescriptorProtomessages (defined indescriptor.proto). - Plugins must emit a serialized
CodeGeneratorResponseobject (defined inplugin.proto) onstdout.
CLI options
Code generators should be able to run without any options or flags if at
all possible, and be able to generate a valid library from only the protos. If
options are required, protoc allows them to be passed as
--{plugin_name}_opt, and the string provided here becomes set as the
parameter string on the CodeGeneratorRequest.
Code generators must not rely on environment variables for configuration.
Expected behavior
This section outlines the expected behavioral attributes of the output of the client library generator (in other words: the libraries that the generators write). Client libraries must implement these concepts in order to be considered complete.
Services and methods
Each of the service and rpc directives in the requested protos must be
represented in the client library output, unless the language or transport is
unable to support it.
Note: While how to accomplish this may vary from language to language, in most classical languages it is probably a class for each service, containing methods for each RPC.
- The classes generated for each
servicedirective must honor thegoogle.api.default_hostannotation if it is provided, and use that host as the default hostname. These classes should provide a mechanism for the end user to override the hostname.- If the
google.api.default_hostannotation is not present on theservicedirective, then the generated class should require a hostname when it is instantiated.
- If the
- Additionally, if the classes generated for each service support using OAuth
and service credentials, they must honor the
google.api.oauth_scopesannotation (if it is provided), and use these scopes by default. - Services that have set the
deprecatedprotobuf option totrueshould have an equivalent deprecation tag generated in the generated class. If applicable, this tag may include a comment that specifies when the service will be removed, which is typically the next major version update. Similarly, RPCs with this option set totrueshould have their generated language method(s) marked as deprecated. - Finally, service classes must also accept credentials, which are used appropriately when requests are made. (Accepting a custom gRPC channel satisfies this requirement.)
Long-running operations
An RPC is considered to be a "long-running" RPC if (and only if) the RPC's
return type is google.longrunning.Operation. Any API which has one or
more RPCs returning an Operation is expected to implement the Operations
service.
Because the response and metadata fields in Operation are of the
type google.protobuf.Any, it is necessary to know what message to use to
deserialize them. This is annotated on the RPC using the
google.longrunning.operation_info annotation.
Note: The values in this struct are strings, not message objects; the
code generator uses the string to determine the appropriate message to use.
Strings with no period (.) character refer to a message in the same proto
package.
Code generators should fail with an error if a type is provided in the
operation_info annotation which was not imported, or if no response type
or metadata type is provided. Code generators should fail with an error if
either the response_type or metadata_type keys are omitted.
Client libraries must honor the LRO interface; if an RPC has an
Operation as its return type, the generated method must intercept it
and return an appropriate idiomatic object for resolving the LRO (such as a
Future or Promise bound to the underlying Operation object).
Streaming
Client libraries must implement streaming to the extent that their
supporting transports allow. An RPC is considered to be streaming if the
stream keyword is present on the argument or response type. This is present
in the MethodDescriptorProto message using the client_streaming and
server_streaming keys.
View on GitHub