mirror of
https://github.com/adidas/api-guidelines.git
synced 2025-10-25 15:19:19 +00:00
GitBook: [master] 69 pages modified
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
# Message
|
||||
|
||||
This section covers the message format governance.
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# Content Negotiation
|
||||
|
||||
Every API **MUST** implement and every API Consumer **MUST** use the [HTTP content negotiation](https://tools.ietf.org/html/rfc7231#section-3.4) where a representation of a resource is requested.
|
||||
|
||||
> NOTE: The content negotiation plays the key role in evolving an API, **change management and versioning**.
|
||||
|
||||
## Example
|
||||
|
||||
A client is programmed to understand the `application/vnd.example.resource+json; version=2` message format semantics. The client requests a representation of the `/greeting` resource in desired the media type \(including its version\) from the server:
|
||||
|
||||
```text
|
||||
GET /greeting HTTP/1.1
|
||||
Accept: application/vnd.example.resource+json; version=2
|
||||
...
|
||||
```
|
||||
|
||||
The server can provide only a newer version of the requested media type `version=2.1.3`. But since the newer version is backward compatible with the requested `version=2` \(related: Changes & Versioning\) it can satisfy the request and responds:
|
||||
|
||||
```text
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/vnd.example.resource+json; version=2.1.3
|
||||
...
|
||||
```
|
||||
|
||||
> NOTE: A server that doesn't have the requested representation media type available MUST respond with the HTTP Status Code **406 Not Acceptable**.
|
||||
>
|
||||
> NOTE: A server MAY have multiple choices available and MAY respond with the **300 Multiple Choices** response. In which case client SHOULD choose from the presented choices.
|
||||
>
|
||||
> You can read more about content negotiation at [MDN Content negotiation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation).
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
# Problem Detail
|
||||
|
||||
The [`application/problem+json`](https://tools.ietf.org/html/rfc7807) \(Problem Detail\) **MUST** be used to communicate details about an error.
|
||||
|
||||
Problem Detail is intended for use with the HTTP status codes 4xx and 5xx. Problem Detail **MUST NOT** be used with 2xx status code responses.
|
||||
|
||||
At the minimum, any Problem Detail response **MUST** have the `title` and `detail` fields.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
{
|
||||
"title": "Authentication required",
|
||||
"detail": "Missing authentication credentials for the Greeting resource."
|
||||
}
|
||||
```
|
||||
|
||||
## Optional Fields
|
||||
|
||||
It **SHOULD** has the `type` field with the identifier of the error, besides it **MAY** have the `instance` field with the URI of the resource in question. If the Problem Detail response has the `status` field it **MUST** have the same value as HTTP Status code from of the response.
|
||||
|
||||
```javascript
|
||||
{
|
||||
"type": "https://adidas-group.com/problems/scv/unauthorized",
|
||||
"title": "Authentication required",
|
||||
"detail": "Missing authentication credentials for the Greeting resource.",
|
||||
"instance": "/greeting",
|
||||
"status": 401
|
||||
}
|
||||
```
|
||||
|
||||
> NOTE: The `type` field is an identifier, and as such it **MAY** be used to denote additional error codes. Keep in mind that the identifier should be a URI.
|
||||
|
||||
## Additional Fields
|
||||
|
||||
If needed, the Problem Detail **MAY** include additional fields, refer to [RFC7807](https://tools.ietf.org/html/rfc7807) for details.
|
||||
|
||||
## Validation Errors
|
||||
|
||||
When necessary, a Problem Detail response **MAY** include additional error details about the problems that have occurred.
|
||||
|
||||
These additional errors **MUST** be under the `errors` and **MUST** follow the Problem Detail structure.
|
||||
|
||||
### Example
|
||||
|
||||
Request:
|
||||
|
||||
```text
|
||||
POST /my-resource HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"age": -32,
|
||||
"color": "cyan"
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```text
|
||||
HTTP/1.1 400 Bad Request
|
||||
Content-Type: application/problem+json
|
||||
Content-Language: en
|
||||
|
||||
{
|
||||
"type": "https://example.net/validation_error",
|
||||
"title": "Your request parameters didn't validate.",
|
||||
"instance": "/my-resource",
|
||||
"status": 400,
|
||||
|
||||
"errors": [
|
||||
{
|
||||
"type": "https://example.net/invalid_params",
|
||||
"instance": "/age",
|
||||
"title": "Invalid Parameter",
|
||||
"detail": "age must be a positive integer"
|
||||
},
|
||||
{
|
||||
"type": "https://example.net/invalid_params",
|
||||
"instance": "/color",
|
||||
"title": "Invalid Parameter",
|
||||
"detail": "color must be 'green', 'red' or 'blue'"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Problem Detail and Content Negotiation
|
||||
|
||||
### Example
|
||||
|
||||
A request is made to retrieve a resource representation:
|
||||
|
||||
```text
|
||||
GET /greeting HTTP/1.1
|
||||
Accept: application/hal+json
|
||||
```
|
||||
|
||||
However, in order to make this request, the client needs to be authorized. Since the request is made without the authorization credentials the **401 Unauthorized** response is returned together with details using the `application/problem+json` media type:
|
||||
|
||||
```text
|
||||
HTTP/1.1 401 Unauthorized
|
||||
Content-Type: application/problem+json
|
||||
Content-Language: en
|
||||
|
||||
{
|
||||
"type": "https://adidas-group.com/problems/scv/unauthorized",
|
||||
"title": "Authentication required",
|
||||
"detail": "Missing authentication credentials for the Greeting resource.",
|
||||
"instance": "/greeting",
|
||||
"status": 401
|
||||
}
|
||||
```
|
||||
|
||||
## No Stack Traces or Server Logs
|
||||
|
||||
> _Problem details are not a debugging tool for the underlying implementation; rather, they are a way to expose greater detail about the HTTP interface itself._
|
||||
>
|
||||
> _–_ [_RFC7807_](https://tools.ietf.org/html/rfc7807)
|
||||
|
||||
A Problem Detail response **MUST NOT** contain a program stack trace or server log for debugging purposes. Instead, provide a `logref` field with reference to the particular server log.
|
||||
|
||||
## Working with Problem Detail
|
||||
|
||||
There are a whole plethora of libraries working with Problem Detail, for example, see [Zalando / Problem](https://github.com/zalando/problem) \(Java\).
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
# Foreign Key Relations
|
||||
|
||||
## Link or Embed Foreign Key Relation
|
||||
|
||||
When a resource representation includes relation with another \(foreign\) resource, the relation **MUST** be expressed as a link relation or embed the related resource.
|
||||
|
||||
### Example
|
||||
|
||||
Use:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"_links": {
|
||||
"author": { "href": "/users/john" }
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```javascript
|
||||
{
|
||||
...
|
||||
"_embedded": {
|
||||
"author": {
|
||||
"_links": { "self": "/users/john" },
|
||||
"name": "John Appleseed",
|
||||
"email": "john@apple.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
instead:
|
||||
|
||||
```javascript
|
||||
{
|
||||
...
|
||||
"authorHref": "/users/john"
|
||||
}
|
||||
```
|
||||
|
||||
## Nest Foreign Key Relation
|
||||
|
||||
If a foreign object has another identifier, but URI or the foreign object isn't a resource, the object **MUST** be nested.
|
||||
|
||||
### Example
|
||||
|
||||
Use:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"author": {
|
||||
"id": "1234",
|
||||
"name": "John Appleseed",
|
||||
"email": "john@apple.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
instead:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"authorId": "1234"
|
||||
}
|
||||
```
|
||||
|
||||
> NOTE: As a rule of thumb, in an HTTP message body, there SHOULD NOT be any field with trailing "\_id," "\_href," "\_url" etc. in its name.
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
# HAL
|
||||
|
||||
The [`application/hal+json`](http://stateless.co/hal_specification.html) \(HAL\) **MUST** be used as the representation format of a resource.
|
||||
|
||||
## Introduction to HAL
|
||||
|
||||
> _HAL is a simple format that gives a consistent and easy way to hyperlink between resources in your API._
|
||||
|
||||
This document is an informal introduction to the HAL media type. For more details see [HAL - Hypertext Application Language Specification](http://stateless.co/hal_specification.html).
|
||||
|
||||
## HAL Document Object Model
|
||||
|
||||
HAL document follow the object model defined in JSON-schema [here](https://supermodel.io/adidas/api/HAL).
|
||||
|
||||
YAML code snippets are provided for [OpenAPI Specification 2.0/Swagger](./HAL-snippet.yaml) and [OpenAPI Specification 3.x](./HAL-snippet-full-OpenApi3.yaml).
|
||||
|
||||
## Simple Document Example
|
||||
|
||||
The simplest Hal document looks like an empty JSON \(it is an empty JSON!\):
|
||||
|
||||
```javascript
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
A document representing a "Greeting" resource might look like:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"message": "Hello World!",
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/greeting"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The field `_links` has a special meaning in HAL. It denotes a list of link relations - a pair of a relation identifier and a link \(URI\).
|
||||
|
||||
These link relations are used to express the relation of a resource with other resources.
|
||||
|
||||
In our case the "Greeting" resource isn't related to other resources but itself, hence the `self` relation pointing to the Greeting resource.
|
||||
|
||||
> NOTE: It is **customary** for every resource representation to include the `self` link relation.
|
||||
>
|
||||
> NOTE: The href **MUST** always be **relative path to the API root** \(e.g. without the host and scheme\).
|
||||
|
||||
## Relation Example
|
||||
|
||||
A more complex document example could be an "Order" resource that has a related resource "Author" \(a person who created the order. It might look like:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "/orders/1234"
|
||||
},
|
||||
"author": {
|
||||
"href": "/users/john"
|
||||
}
|
||||
},
|
||||
"orderNumber": 1234,
|
||||
"itemCount": 42,
|
||||
"status": "pending"
|
||||
}
|
||||
```
|
||||
|
||||
## Embedding Example
|
||||
|
||||
Let's assume there is an "Orders" resource which is a collection of all orders from different authors. There is the relation between the Orders resource and possibly many Order resources.
|
||||
|
||||
We could express this in the `_links` object using the `order` relation, but sometimes it is practical to "embed" \(entirely or partially\) related resources representations in the originating resource representation. For a scenario like this HAL offers the `_embedded` field.
|
||||
|
||||
The `_embedded` field's object just contains the related resources HAL representations:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/orders" }
|
||||
},
|
||||
"_embedded": {
|
||||
"order": [
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/orders/1" }
|
||||
},
|
||||
"orderNumber": "1",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"_links": {
|
||||
"self": { "href": "/orders/2" }
|
||||
},
|
||||
"orderNumber": "2",
|
||||
"status": "cancelled"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is important to understand that embedded resource representation might be only **partial** and might also contain their own embedded resources.
|
||||
|
||||
The embedded resource representation should be used as a **convenience** function \(e.g. to reduce the initial number of calls needed at application launch\).
|
||||
|
||||
Where a full and up-to-date representation of a resource is needed the link relation should exercise the affordance \(e.g. `GET /orders/2`\).
|
||||
|
||||
#### Real-world Examples
|
||||
|
||||
Some APIs using HAL:
|
||||
|
||||
* [Amazon AppStream REST API](http://docs.aws.amazon.com/appstream/latest/developerguide/appstream-api-rest.html)
|
||||
* [FoxyCart](https://wiki.foxycart.com/v/2.0/start)
|
||||
* [Clarify.io](http://docs.clarify.io/overview/)
|
||||
* [University of Oxford / Mobile Oxford](http://api.m.ox.ac.uk/browser/#/)
|
||||
|
||||
## Working with HAL
|
||||
|
||||
Refer to the [extensive list of libraries that work with HAL](https://github.com/mikekelly/hal_specification/wiki/Libraries).
|
||||
|
||||
For working with HAL and Node.js using [HALson npm package](https://www.npmjs.com/package/halson) is suggested.
|
||||
|
||||
### Spring Framework
|
||||
|
||||
Spring framework supports HAL out of the box. More info can be found in [Spring Documentation](https://spring.io/guides/gs/rest-hateoas/) and [examples](https://github.com/spring-guides/gs-rest-hateoas).
|
||||
@@ -1,16 +0,0 @@
|
||||
# Message Formats
|
||||
|
||||
## Response Message Format
|
||||
|
||||
All **response** messages **MUST** support an [`application/hal+json`](http://stateless.co/hal_specification.html) \(HAL\) format.
|
||||
|
||||
### Error Response Format
|
||||
|
||||
The [`application/problem+json`](https://tools.ietf.org/html/rfc7807) \(Problem Detail\) **MUST** be used to communicate details about an error.
|
||||
|
||||
## Request Message Format
|
||||
|
||||
**Request** messages with body **SHOULD** support a [`application/json`](http://www.json.org) \(JSON\) format. Where applicable, request message **SHOULD** also support the [`application/hal+json`](http://stateless.co/hal_specification.html) format.
|
||||
|
||||
**Request** messages **MAY** also support the [`application/x-www-form-urlencoded`](https://tools.ietf.org/html/rfc1866#section-8.2.1) \(URL Encoded\) format.
|
||||
|
||||
Reference in New Issue
Block a user