Sticking to the Google Cloud API Design Guide, we can distinguish between standard methods and custom methods. Standard methods are:
List
- Fetches a list of resources from a collection.Get
- Fetches a single resource.Create
- Creates a new resource.Update
- Updates an existing resource. Optional, a resource can be partially updated.Delete
- Deletes a resource.
Each of these are mapped to a different operation in each API style.
When implementing a RESTful Web Service, we will be using HTTP as the underlying transfer protocol to manipulate resources. According to REST constraints, the system should be visible. Here this means we should leverage the available methods on HTTP rather than encapsulating our own methods within our request representations (i.e. we should not do tunnelling).
HTTP defines a number of methods along with their description (HTTP/1.1 Request Methods (RFC 7231) and PATCH Method for HTTP (RFC 5789)):
Method | Meaning | Is safe | Is idempotent |
---|---|---|---|
GET | Transfer a current representation of the target resource | yes | yes |
HEAD | Same as GET, but only transfer the status line and header section | yes | yes |
OPTIONS | Describe the communication options for the target resource | yes | yes |
PUT | Replace all current representations of the target resource with the request payload | no | yes |
DELETE | Remove all current representations of the target resource | no | yes |
POST | Perform resource-specific processing on the request payload | no | no |
PATCH | Apply partial modifications (delta) to a resource | no | no |
A method is considered safe as long as it does not have side-effects. And it is idempotent when the side-effects of applying several identical requests is the same as for a single request.
REST specification does not mention much about which HTTP methods should be used for a certain operation. This is because REST is all about the architectural style, while HTTP methods are part of the Web's architecture. When mapping an API operation to an HTTP method we should consider: the semantic of the method; whether the operation is safe or idempotent; how affect caching; etc. But from the client point of view, it is not important which HTTP method maps an operation. There are some consensus, though:
GET
- Used for safe and idempotent data retrieval, either on documents or in collections/stores.HEAD
- Used for data inspection. When only the metadata (header) of a resource is required,HEAD
can be used instead ofGET
.OPTIONS
- Used for data inspection. To discover how we can interact with a resource,OPTIONS
will be used. This will return anAllow
header listing all available methods. Note that, even though a client application can fetch this information at runtime, it increases the network traffic.POST
- This is the most controversial HTTP method. It can be used for a number of things:- To add a new item into a collection. This is like calling to a factory method. A
Slug
(a suggested identifier) can optionally be set, but the identifier will be defined by the server. - To exercise a controller.
- To run safe and idempotent operations that exceed the maximum length for an identifier. For example, when running a complex query whose URI-representation is invalid.
- And to run any other unsafe and non-idempotent operation. For example, an asynchronous task.
- To add a new item into a collection. This is like calling to a factory method. A
PUT
:- Update a mutable resource. Conditional Requests (RFC 7232) are recommended in order to prevent concurrency problems.
- Add a new item into a store, this is, when the client can decide the identifier of the resource.
DELETE
- It is used to remove a resource. This operation is not safe (i.e. it has side effects), but it is idempotent. This is controversial: what should we return when asked to remove a resource that never existed? A404 Not Found
? What should we return when deleting a resource that was previously removed?204 No Content
? Is this secure enough? Should we maintain a list of removed identifiers?PATCH
- Allows to partially update a resource.- Other HTTP methods - It is encouraged not to use other HTTP methods, like those proposed by WebDAV (RFC 4918), and instead use
POST
.
It's fundamental to notice several things. Neither REST nor HTTP are CRUD. Some HTTP methods clearly map CRUD action (i.e. GET
maps Read and DELETE
maps Delete). However:
POST
can run a number of non-idempotent and unsafe operations. One of those operations might be Create. Performing other actions it is also correct. Remember, the entire SOAP protocol is tunnelled throughPOST
.PUT
does not only Update a resource. It can also Create a specific resource.
Reference table of mapping between standard methods and HTTP methods:
Standard Method | HTTP method |
---|---|
List |
GET <collection URL> |
Get |
GET <document URL> |
Create |
POST <collection URL> or PUT <document URL> |
Update |
PUT <document URL> or PATCH <document URL> |
Delete |
DELETE <document URL> |
Both REST and GraphQL run on top of HTTP, but unlike REST, GraphQL does not promotes the visibility of its transport protocol. Instead, it provides a quite simple set of operations available for API designers. The entry point of every GraphQL consists of three different operation types:
Operation Type | Meaning |
---|---|
query |
Allow to get a graph from the remote API |
mutation |
Operation which causes side effects in the remote entity graph |
subscription |
Let an client application create a websocket-based subscription to a topic |
The mapping between this operations types and our standard methods is straightforward:
Standard Method | GraphQL operation type |
---|---|
List |
query |
Get |
query |
Create |
mutation |
Update |
mutation |
Delete |
mutation |
RPC services in general, and gRPC in particular, are very flexible interfaces that allow both resource-oriented and action-oriented API styles. Google, as the creators of Protocol Buffers, encourages developers to follow a resource oriented approach.
Since Protocol Buffers wraps every remote procedure into an rpc
type definition, we just need to create an rpc
named after the method it follows, as in GetArticle
or ListArticles
.