HTTP REST APIs
URL
Example
The following sections present a few real world examples on how to apply resource-oriented API design to large scale services. You can find more examples in the Google APIs repository.
In these examples, the asterisk indicates one specific resource out of the list.
Gmail API
The Gmail API service implements the Gmail API and exposes most of Gmail functionality. It has the following resource model:
-
API service:
gmail.googleapis.com
- A collection of users:
users/*
. Each user has the following resources.- A collection of messages:
users/*/messages/*
. - A collection of threads:
users/*/threads/*
. - A collection of labels:
users/*/labels/*
. - A collection of change history:
users/*/history/*
. - A resource representing the user profile:
users/*/profile
. - A resource representing user settings:
users/*/settings
.
- A collection of messages:
- A collection of users:
Cloud Pub/Sub API
The pubsub.googleapis.com
service implements the Cloud Pub/Sub API, which defines the following resource model:
-
API service:
pubsub.googleapis.com
- A collection of topics:
projects/*/topics/*
.
- A collection of topics:
-
A collection of subscriptions:
projects/*/subscriptions/*
.
NOTE: Other implementations of the Pub/Sub API may choose different resource naming schemes.
Cloud Spanner API
The spanner.googleapis.com
service implements the Cloud Spanner API, which defines the following resource model:
- API service:
spanner.googleapis.com
- A collection of instances:
projects/*/instances/*
.- A collection of instance operations:
projects/*/instances/*/operations/*
. - A collection of databases:
projects/*/instances/*/databases/*
. - A collection of database operations:
projects/*/instances/*/databases/*/operations/*
. - A collection of database sessions:
projects/*/instances/*/databases/*/sessions/*
.
- A collection of instance operations:
- A collection of instances:
Methods
The following table describes how to map standard methods to HTTP methods:
Standard Method | HTTP Mapping | HTTP Request Body | HTTP Response Body |
---|---|---|---|
List |
GET |
N/A | Resource* list |
Get |
GET |
N/A | Resource* |
Create |
POST |
Resource | Resource* |
Update |
PUT or PATCH |
Resource | Resource* |
Delete |
DELETE |
N/A | google.protobuf.Empty ** |
*The resource returned from List
, Get
, Create
, and Update
methods may contain partial data if the methods support response field masks, which specify a subset of fields to be returned. In some cases, the API platform natively supports field masks for all methods.
List
The List
method takes a collection name and zero or more parameters as input, and returns a list of resources that match the input.
List
is commonly used to search for resources. List
is suited to data from a single collection that is bounded in size and not cached. For broader cases, the custom method Search
should be used.
A batch get (such as a method that takes multiple resource IDs and returns an object for each of those IDs) should be implemented as a custom BatchGet
method, rather than a List
. However, if you have an already-existing List
method that provides the same functionality, you may reuse the List
method for this purpose instead. If you are using a custom BatchGet
method, it should be mapped to HTTP GET
.
HTTP mapping:
- The
List
method must use an HTTPGET
verb. - The request message field(s) receiving the name of the collection whose resources are being listed should map to the URL path. If the collection name maps to the URL path, the last segment of the URL template (the collection ID) must be literal.
- All remaining request message fields shall map to the URL query parameters.
- There is no request body; the API configuration must not declare a
body
clause. - The response body should contain a list of resources along with optional metadata.
Get
The Get
method takes a resource name, zero or more parameters, and returns the specified resource.
HTTP mapping:
- The
Get
method must use an HTTPGET
verb. - The request message field(s) receiving the resource name should map to the URL path.
- All remaining request message fields shall map to the URL query parameters.
- There is no request body; the API configuration must not declare a
body
clause. - The returned resource shall map to the entire response body.
Create
Update
Delete
Custom Methods
Custom methods refer to API methods besides the 5 standard methods. They should only be used for functionality that cannot be easily expressed via standard methods. In general, API designers should choose standard methods over custom methods whenever feasible. Standard Methods have simpler and well-defined semantics that most developers are familiar with, so they are easier to use and less error prone. Another advantage of standard methods is the API platform has better understanding and support for standard methods, such as billing, error handling, logging, monitoring.
A custom method can be associated with a resource, a collection, or a service. It may take an arbitrary request and return an arbitrary response, and also supports streaming request and response.
URL
For custom methods, they should use the following generic HTTP mapping:
https://service.name/v1/some/resource/name:customVerb
The reason to use :
instead of /
to separate the custom verb from the resource name is to support arbitrary paths. For example, undelete a file can map to POST /files/a/long/file/name:undelete
Use Cases
Some additional scenarios where custom methods may be the right choice:
- Reboot a virtual machine. The design alternatives could be “create a reboot resource in collection of reboots” which feels disproportionately complex, or “virtual machine has a mutable state which the client can update from RUNNING to RESTARTING” which would open questions as to which other state transitions are possible. Moreover, reboot is a well-known concept that can translate well to a custom method which intuitively meets developer expectations.
- Send mail. Creating an email message should not necessarily send it (draft). Compared to the design alternative (move a message to an “Outbox” collection) custom method has the advantage of being more discoverable by the API user and models the concept more directly.
- Promote an employee. If implemented as a standard
update
, the client would have to replicate the corporate policies governing the promotion process to ensure the promotion happens to the correct level, within the same career ladder etc.
Standard Fields
This section describes a set of standard message field definitions that should be used when similar concepts are needed. This will ensure the same concept has the same name and semantics across different APIs.
Name | Type | Description |
---|---|---|
name |
string |
The name field should contain the relative resource name. |
parent |
string |
For resource definitions and List/Create requests, the parent field should contain the parent relative resource name. |
create_time |
Timestamp |
The creation timestamp of an entity. |
update_time |
Timestamp |
The last update timestamp of an entity. Note: update_time is updated when create/patch/delete operation is performed. |
delete_time |
Timestamp |
The deletion timestamp of an entity, only if it supports retention. |
expire_time |
Timestamp |
The expiration timestamp of an entity if it happens to expire. |
start_time |
Timestamp |
The timestamp marking the beginning of some time period. |
end_time |
Timestamp |
The timestamp marking the end of some time period or operation (regardless of its success). |
read_time |
Timestamp |
The timestamp at which a particular an entity should be read (if used in a request) or was read (if used in a response). |
time_zone |
string |
The time zone name. It should be an IANA TZ name, such as “America/Los_Angeles”. For more information, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones. |
region_code |
string |
The Unicode country/region code (CLDR) of a location, such as “US” and “419”. For more information, see http://www.unicode.org/reports/tr35/#unicode_region_subtag. |
language_code |
string |
The BCP-47 language code, such as “en-US” or “sr-Latn”. For more information, see http://www.unicode.org/reports/tr35/#Unicode_locale_identifier. |
mime_type |
string |
An IANA published MIME type (also referred to as media type). For more information, see https://www.iana.org/assignments/media-types/media-types.xhtml. |
display_name |
string |
The display name of an entity. |
title |
string |
The official name of an entity, such as company name. It should be treated as the formal version of display_name . |
description |
string |
One or more paragraphs of text description of an entity. |
filter |
string |
The standard filter parameter for List methods. |
query |
string |
The same as filter if being applied to a search method (ie :search ) |
page_token |
string |
The pagination token in the List request. |
page_size |
int32 |
The pagination size in the List request. |
total_size |
int32 |
The total count of items in the list irrespective of pagination. |
next_page_token |
string |
The next pagination token in the List response. It should be used as page_token for the following request. An empty value means no more result. |
order_by |
string |
Specifies the result ordering for List requests. |
request_id |
string |
A unique string id used for detecting duplicated requests. |
resume_token |
string |
An opaque token used for resuming a streaming request. |
labels |
map |
Represents Cloud resource labels. |
deleted |
bool |
If a resource allows undelete behavior, it must have a deleted field indicating the resource is deleted. |
show_deleted |
bool |
If a resource allows undelete behavior, the corresponding List method must have a show_deleted field so client can discover the deleted resources. |
update_mask |
FieldMask |
It is used for Update request message for performing partial update on a resource. This mask is relative to the resource, not to the request message. |
validate_only |
bool |
If true, it indicates that the given request should only be validated, not executed. |
Error
If you are a server developer, you should generate errors with enough information to help client developers understand and address the problem. At the same time, you must be aware of the security and privacy of the user data, and avoid disclosing sensitive information in the error message and error details, since errors are often logged and may be accessible by others. For example, an error message like “Client IP address is not on whitelist 128.0.0.0/8” exposes information about the server-side policy, which may not be accessible to the user.
Error Codes
Google APIs must use the canonical error codes defined by google.rpc.Code
. Individual APIs should avoid defining additional error codes, since developers are very unlikely to write logic to handle a large number of error codes. For reference, handling an average of 3 error codes per API call would mean most application logic would just be for error handling, which would not be a good developer experience.
Discussion
要不要保留 HTTP Method Code,比如 404、500,还是用错误码来表示异常情况(此时,所有 REST APIs 都返回 200 的 status code,而如果处理过程中出现异常,则返回500)。
个人是偏向于 HTTP Method Code,因为HTTP Method Code本身已经被标准化了,其语义更丰富,且通用性更好。
还有一个好处是,如果用response body的error code来表示异常情况,需要解析完整个response body。而如果假如这个body非常大,且执行这个操作与业务无关,比如在gateway端触发circuit breaker,这个解析操作的执行效率非常低(因为解析一个非常大的body,但只会使用到其中的error code)。
Error Messages
The error message should help users understand and resolve the API error easily and quickly. In general, consider the following guidelines when writing error messages:
- Do not assume the user is an expert user of your API. Users could be client developers, operations people, IT staff, or end-users of apps.
- Do not assume the user knows anything about your service implementation or is familiar with the context of the errors (such as log analysis).
- When possible, error messages should be constructed such that a technical user (but not necessarily a developer of your API) can respond to the error and correct it.
- Keep the error message brief. If needed, provide a link where a confused reader can ask questions, give feedback, or get more information that doesn’t cleanly fit in an error message. Otherwise, use the details field to expand.
Naming Convertions
Traditional RPC APIs
Methods
Only GET
and POST
method are allowed. We don’t use PUT
and DELETE
in project.
GET
method is used to retrieve information from server, while POST
requests are generally used to add / update / delete the data on server.
- One notable exception is that, API that pass array to fetch batch data from server could be in
POST
method. This is because it is awkward to pass array of data to server using query string. You can pass array in JSON object inPOST
body. e.g.
# Simple request
POST /api/order/get_list
{"orders":[100001, 100002]}
# Complex request
POST /api/item/get_list
{"items":[{"shopid":1000,"itemid":100001},{"shopid":1000,"itemid":100002}]}