REST API and Web Services
REST API and Web Services
Topics
What is REST API
JSON
gRPC, GraphQL
What's an API?
An API, or Application Programming Interface, is a set of definitions and
protocols that allow one application to communicate with another application
which are any kind of object, data, or service that can be accessed by
the client
https://example.com/orders/1
Main Design Principles of RESTful APIs
Clients interact with a service by exchanging representations of resources
For example, a GET request to the URI listed in the previous slide might
return this JSON response body:
{
"orderId":1,
"orderValue":99.90,
"productId":1,
"quantity":1
}
Main Design Principles of RESTful APIs
REST APIs use a uniform interface, which helps to decouple the client and
service implementations
For REST APIs built on HTTP, the uniform interface includes using
standard HTTP verbs to perform operations on resources
The most common operations are GET, POST, PUT, PATCH, and DELETE
Main Design Principles of RESTful APIs
REST APIs use a stateless request model
It contains links to get or update the customer associated with the order
{
"orderID":3,
"productID":2,
"quantity":4,
"orderValue":16.60,
"links": [
{"rel":"product","href":"https://example.com/customers/3",
"action":"GET" },
{"rel":"product","href":"https://example.com/customers/3",
"action":"PUT" }
]
}
Maturity Model for Web APIs
In 2008, Leonard Richardson proposed the following maturity model for web
APIs:
Level 0: Define one URI, and all operations are POST requests to this URI
the HTTP response indicates whether the order was placed successfully
or not
https://example.com/orders // Good
https://example.com/create-order // Avoid
Organize the API design around resources
A resource doesn't have to be based on a single physical data item
A collection is a separate resource from the item within the collection, and
should have its own URI
for example, the following URI might represent the collection of orders:
https://example.com/orders
Organize the API design around resources
Sending an HTTP GET request to a collection URI retrieves a list of items in
the collection
each item in the collection also has its own unique URI
an HTTP GET request to the item's URI returns the details of that item
Organize the API design around resources
Adopt a consistent naming convention in URIs
it's a good practice to organize URIs for collections and items into a
hierarchy. For example,
you could also go in the other direction, and represent the association
from an order back to a customer with a URI such as
/orders/99/customer
Organize the API design around resources
Avoid requiring resource URIs more complex than
collection/item/collection
/customers/1/orders/99/products
Organize the API design around resources
All web requests impose a load on the web server, the more requests, the
bigger the load
therefore, try to avoid "chatty" web APIs that expose a large number of
small resources
Combine related information into bigger resources that can be retrieved with
a single request
for example, if your data is stored in a relational database, the web API
doesn't need to expose each table as a collection of resources
You can handle such non-resource scenarios through HTTP requests that
invoke a function and return the results as an HTTP response message
for example, a web API that implements simple calculator operations such
as add and subtract could provide URIs that expose these operations as
pseudo resources and use the query string to specify the parameters
required
Define API operations in terms of HTTP methods
HTTP GET Method retrieves a representation of the resource at the
specified URI
the body of the response message contains the details of the requested
resource
the body of the request message provides the details of the new
resource
note that POST can also be used to trigger operations that don't actually
create resources
Define API operations in terms of HTTP methods
HTTP PUT Method either creates or replaces the resource at the specified
URI
the request body specifies the set of changes to apply to the resource
The server assigns a URI for the new resource, and returns that URI to the
client
A POST request can also be used to submit data for processing to an existing
resource, without any new resource being created
The differences between POST, PUT, and PATCH
A PUT request creates a resource or updates an existing resource
PUT requests are most frequently applied to resources that are individual
items, such as a specific customer, rather than collections
The differences between POST, PUT, and PATCH
A PATCH request performs a partial update to an existing resource
This can be more efficient than using PUT, because the client only sends the
changes, not the entire representation of the resource
The differences between POST, PUT, and PATCH
PUT requests must be idempotent
if a client submits the same PUT request multiple times, the results should
always be the same (the same resource will be modified with the same
values)
https://www.rfc-editor.org/rfc/rfc6902
Conform to HTTP Semantics
Media Types
In the HTTP protocol, formats are specified through the use of media
types, also called MIME types
{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}
If the server doesn't support the media type, it should return HTTP
status code 415 (Unsupported Media Type)
Conform to HTTP Semantics
Media Types
{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}
If the server cannot match any of the media type(s) listed, it should
return HTTP status code 406 (Not Acceptable)
Conform to HTTP Semantics
GET Methods
A successful GET method typically returns HTTP status code 200 (OK)
If the resource cannot be found, the method should return 404 (Not
Found)
Should be idempotent, the same GET request repeated over the same
resource should result in the same state
Conform to HTTP Semantics
POST Methods
if the method does some processing but does not create a new
resource, the method can return HTTP status code 200 (Ok) and include
the result of the operation in the response body
if the client puts invalid data into the request, the server should return
HTTP status code 400 (Bad Request)
the response body can contain additional information about the error or
a link to a URI that provides more details
Conform to HTTP Semantics
PUT Methods
if a PUT method creates a new resource, it returns HTTP status code 201
(Created), as with a POST method
Consider implementing bulk HTTP PUT operations that can batch updates
to multiple resources in a collection
the PUT request should specify the URI of the collection, and the
request body should specify the details of the resources to be
modified
the patch document doesn't describe the whole resource, only a set of
changes to apply
Conform to HTTP Semantics
PATCH Methods
The patch document has the same structure as the original JSON
resource, but includes just the subset of fields that should be changed or
added
{
"name":"gizmo", {
"category":"widgets", "price":12,
"color":"blue", "color":null,
"price":10 "size":"small"
} }
Patch Document
Original
Conform to HTTP Semantics
JSON MERGE PATCH
A field can be deleted by specifying null for the field value in the patch
document. (That means merge patch is not suitable if the original
resource can have explicit null values)
{
"name":"gizmo", {
"category":"widgets", "price":12,
"color":"blue", "color":null,
"price":10 "size":"small"
} }
Patch Document
Original
Conform to HTTP Semantics
JSON MERGE PATCH
application/merge-patch+json
Conform to HTTP Semantics
JSON PATCH
Operations include add, remove, replace, copy, and test (to validate
values)
Error conditions and Corresponding HTTP Status Code for PATCH requests
The patch document format isn't supported 415 (Unsupported Media Type)
If the resource doesn't exist, the web server can return HTTP 404 (Not
Found)
Conform to HTTP Semantics
DELETE Methods
should be idempotent
sending multiple DELETE requests to the same URI should have the same
effect, although the HTTP status code in the response messages may be
different
the first DELETE request might return status code 204 (No Content),
while a subsequent DELETE request might return status code 404
(Not Found)
Conform to HTTP Semantics
Asynchronous Operations
return HTTP status code 202 (Accepted) to indicate the request was
accepted for processing but is not completed
Conform to HTTP Semantics
Asynchronous Operations
Include the URI of the status endpoint in the Location header of the
202 response. For example:
If the client sends a GET request to the status endpoint, the response
should contain the current status of the request
HTTP/1.1 200 OK
Content-Type: application/json
{
"status":"In progress",
"link": { "rel":"cancel", "method":"delete", "href":"/api/status/12345" }
}
Conform to HTTP Semantics
Asynchronous Operations
In the 303 response, include a Location header that gives the URI of the
new resource
API should allow, when necessary, passing a filter in the query string of
the URI
In the following example the web API is responsible for parsing and
handling the minCost parameter in the query string and returning the
filtered results on the server side
/orders?minCost=n
Conform to HTTP Semantics
Filter, Paginate, and Sort Data
You should design a web API to limit the amount of data returned by
any single request
/orders?limit=25&offset=50
Conform to HTTP Semantics
Filter, Paginate, and Sort Data
You can extend this approach to limit the fields returned for each item, if
each item contains a large amount of data
for example, you could use a query string parameter that accepts a
comma-delimited list of fields, such as
/orders?fields=ProductID,Quantity
Conform to HTTP Semantics
Filter, Paginate, and Sort Data
set the sort parameter to the key of the resource if you implement
ordering, and
set the fields parameter to all fields in the resource if you support
projections
Support Partial Responses for Large Binary Resources
A resource may contain large binary fields, such as files or images
To do this, the web API should support the Accept-Ranges header for
GET requests for large resources
Support Partial Responses for Large Binary Resources
The Accept-Ranges header indicates that the GET operation supports partial
requests
The client application can submit GET requests that return a subset of a
resource, specified as a range of bytes
Support Partial Responses for Large Binary Resources
Also, consider implementing HTTP HEAD requests for these resources
A HEAD request is similar to a GET request, except that it only returns the HTTP
headers that describe the resource, with an empty message body
[...]
Use HATEOAS to Enable Navigation to Related Resources
Each HTTP GET request should return the information necessary to find
the resources related directly to the requested object through
hyperlinks included in the response, and it should also be provided with
information that describes the operations available on each of these
resources
"types":["application/x-www-form-urlencoded" ]
},
{
"rel":"self",
"href":"https://example.com/orders/3" ,
"action":"DELETE",
"types":[]
}]
}
Versioning a RESTful web API
Versioning enables a web API to indicate the features and resources that it
exposes, and a client application can submit requests that are directed to a
specific version of a feature or resource
Question
What will happen to clients who consume an API such as the following, if
you change the schema of the resource
https://example.com/api/customers
Versioning a RESTful web API
URI Versioning
Each time you modify the web API or change the schema of resources,
you add a version number to the URI for each resource
https://example.com/api/v2/customers/3
Versioning a RESTful web API
Query String Versioning
You can specify the version of the resource by using a parameter within
the query string appended to the HTTP request
https://example.com/customers/3?version=2
Versioning a RESTful web API
Header Versioning
You can implement a custom header that indicates the version of the
resource
As part of this initiative, the Swagger 2.0 specification was renamed the
OpenAPI Specification (OAS) and brought under the Open API Initiative
Sample Code
JSON can represent four primitive types (strings, numbers, booleans, and
null) and two structured types (objects and arrays)
{}
{“”: {} }
JSON (ECMA-404, RFC-8259)
A single colon comes after each name, separating the name from the
value and a single comma separates a value from a following name
"": {
"1": "one",
"2": "two",
"1": "ONE"
}
}
JSON (ECMA-404, RFC-8259)
A value MUST be an object, array, number, or string, or one of the
following three literal names: false, null, true
[]
[{}]
JSON Object Example
Example JSON array containing two objects
Question
Which of the following are JSONs
true
False
""
hello
"Hello"
null
Other Web Services
Remote Procedure Call (RPC)is one of the technology that allow one
program to interact with another (SOAP is RPC like)
The RPC model tries to make a request to a remote network service look
the same as calling a function or method in your programming language,
within the same process (this abstraction is called location transparency)
Other Web Services
Some of the example of recent Web Service related technologies includes
As in many RPC systems, gRPC is based around the idea of defining a service
(an interface), specifying the methods that can be called remotely with
their parameters and return types
On the server side, the server implements this interface and runs a gRPC
server to handle client calls
On the client side, the client has a stub that provides the same methods as
the server
gRPC Example
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
gRPC Example
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
gRPC
gRPC and Protocol Buffers
Protocol Buffer is Google’s open source mechanism for serializing
structured data
gRPC can also be used with other data formats such as JSON
Working with Protocol Buffers
The first step when working with protocol buffers is to define the structure
for the data you want to serialize in a proto file: this is an ordinary text file
with a .proto extension
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
Working with Protocol Buffers
Once you’ve specified your data structures, you use the protocol buffer
compiler protoc to generate data access classes in your preferred
language(s) from your proto definition
These provide simple accessors for each field, like name() and
set_name(), as well as methods to serialize the whole structure to raw
bytes or parse from raw bytes
Working with Protocol Buffers
You can then use the generated class in your application to populate,
serialize, and retrieve Person protocol buffer messages.
gRPC and Protocol Buffer References
https://grpc.io/docs/guides/
https://developers.google.com/protocol-buffers/docs/gotutori
al
https://grpc.io/docs/what-is-grpc/core-concepts/
GraphQL
GraphQL is a query language for your API, and a server-side runtime for
executing queries by using a type system you define for your data
GraphQL isn't tied to any specific database or storage engine and is instead
backed by your existing code and data
GraphQL
A GraphQL service is created by defining types, and fields on those types, then
providing functions for each field on each type
A received query is first checked to ensure it only refers to the types and fields
defined, then runs the provided functions to produce a result.
GraphQL: Describe your data
type Project {
name: String
tagline: String
contributors: [User]
}
GraphQL: Ask for what you want
{
project(name: "GraphQL") {
tagline
}
}
GraphQL: Get predictable results
{
"project": {
"tagline": "A query language for APIs"
}
}
GraphQL References
https://graphql.org/
https://graphql.org/learn/