Merge pull request #42 from adidas/changes/API-165

application/problem+json added as possible media type in successful responses
This commit is contained in:
Jesus de Diego
2021-02-18 15:50:21 +00:00
committed by GitHub
24 changed files with 623 additions and 665 deletions

2
.gitignore vendored
View File

@@ -105,3 +105,5 @@ dist
# SSHFS
._*
.DS_Store

View File

@@ -244,24 +244,40 @@ rules:
match: "/^https:/"
adidas-oas3-response-success-hal:
description: "All success responses MUST be of media type `application/hal+json`"
description: "All success responses MUST be of media type `application/hal+json` "
severity: error
given: $.paths..responses[?( @property >= 200 && @property < 300 && @property != 204)].content[*]~
given: $.paths..responses[?( @property >= 201 && @property < 300 && @property != 204)].content[*]~
recommended: true
# type: "style"
formats:
- oas3
message: "Response documents MUST be of application/hal+json media type: {{error}}"
message: "Response documents MUST be of application/hal+json media types: {{error}}"
then:
function: enumeration
functionOptions:
values:
- application/hal+json
# sync and async patterns that can return hal OR problem+json
adidas-oas3-response-success-OK:
description: "All success responses MUST be of media type `application/hal+json` or `application/problem+json`"
severity: error
given: $.paths..responses[?( @property == 200 )].content[*]~
recommended: true
formats:
- oas3
message: "Response documents MUST be of application/hal+json or application/problem+json media types: {{error}}"
then:
function: enumeration
functionOptions:
values:
- application/hal+json
- application/problem+json
adidas-oas3-response-success-hal-body: # schemes and/or produces
description: "All success responses MUST follow `application/hal+json` schema"
severity: error
given: $.paths..responses[?( @property >= 200 && @property < 300 && @property != 204)].content[?(@property === "application/hal+json")]
given: $.paths..responses[?( @property == 200 && @property < 300 && @property != 204)].content[?(@property === "application/hal+json")]
recommended: true
type: "style"
formats:

View File

@@ -4,7 +4,7 @@ description: Guidelines for the API design and development at adidas
# adidas API Guidelines
![adidas logo](https://adidas-group.gitbooks.io/api-guidelines/content/assets/adidas-logo.svg)
![adidas logo](adidaslogo.jpg)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -23,7 +23,7 @@ The API Guidelines are split into two main parts:
* [General Guidelines](general-guidelines/general-guidelines.md)
* API type-specific Guidelines
* [REST APIs Guidelines](rest-api-guidelines/rest.md)
* [Kafka Guidelines](kafka-guidelines/kafka.md)
* [Asynchronous APIs Guidelines](asynchronous-api-guidelines/asyncapi.md)
The general guidelines section discusses the core principles relevant to any kind of API. The API type-specific section further defines the guidelines specific to a given architectural style or API technique \(such as REST, Kafka or GraphQL APIs\).
@@ -61,7 +61,7 @@ For further documentation on Spectral refer to their [documentation](https://sto
### Questions & Comments
_Please contact_ [_Zdenek.Nemec@externals.adidas-group.com_](mailto:Zdenek.Nemec@externals.adidas-group.com), [_andrzej.jarzyna@adidas.com_](mailto:andrzej.jarzyna@adidas.com) or [_samir.amzani@adidas.com_](mailto:samir.amzani@adidas.com) _in case of questions._
_Please contact_ [_samir.amzani@adidas.com_](mailto:samir.amzani@adidas.com) or [_jesusjavier.dediego@adidas.com_](mailto:jesusjavier.dediego@adidas.com) _in case of questions._
## Intended Use Cases
@@ -69,6 +69,10 @@ This project is intended to provide the guidelines for design & development of A
adidas is not responsible for the usage of this software for different purposes that the ones described in the use cases.
## Last Review
February 2021
## License and Software Information
© adidas AG
@@ -83,5 +87,5 @@ For further information open the [adidas terms and conditions](https://github.co
### License
[MIT](https://github.com/adidas-group/api-guidelines/tree/657bc6fd49f1499f10c30ab18420f4bdb7cd841b/LICENSE/README.md)
[MIT](https://github.com/adidas/api-guidelines/blob/master/LICENSE)

View File

@@ -39,7 +39,10 @@
* [Common Data Types](rest-api-guidelines/application/common-data-types.md)
* [Execution](rest-api-guidelines/execution/README.md)
* [Pagination](rest-api-guidelines/execution/pagination.md)
* [Asynchronous Tasks](rest-api-guidelines/execution/asynchronous-tasks.md)
* [Long Running Tasks](rest-api-guidelines/execution/long-running-tasks/README.md)
* [Polling](rest-api-guidelines/execution/long-running-tasks/polling.md)
* [Callback](rest-api-guidelines/execution/long-running-tasks/callback.md)
* [Files Upload](rest-api-guidelines/execution/long-running-tasks/files-upload.md)
* [Batch Operations](rest-api-guidelines/execution/batch-operations.md)
* [Search Requests](rest-api-guidelines/execution/search-requests.md)
* [Query Requests with Large Inputs](rest-api-guidelines/execution/query-requests-with-large-inputs.md)
@@ -61,7 +64,7 @@
* [Loose Coupling](rest-api-guidelines/clients/loose-coupling.md)
* [Further References](rest-api-guidelines/miscellaneous.md)
## Kafka Guidelines
## Asynchronous API Guidelines
* [Introduction](kafka-guidelines/kafka.md)
* [Introduction](asynchronous-api-guidelines/asyncapi.md)

BIN
adidaslogo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,6 @@
# Introduction
## adidas Asynchronous APIs Guidelines

View File

@@ -1,365 +0,0 @@
swagger: '2.0'
info:
version: '3.0.0'
title: '[Demo] Orders API'
contact:
name: Z
email: "z@goodapi.co"
description: |
Sample API conforming to [adidas API Guidelines](https://adidas.gitbook.io/api-guidelines/).
produces:
- application/hal+json # Representation message format
- application/problem+json # Error message format
schemes:
- https
host: "example.com"
securityDefinitions:
'API Key':
type: apiKey
in: header
name: x-api-key
security:
- "API Key": []
paths:
/:
x-summary: API Root
get:
summary: Retrieve API Root
description: The API Root contains the initial set of link relations.
responses:
"200":
description: The root of the API
schema:
allOf:
- $ref: '#/definitions/supermodelIoAdidasApiHAL'
example:
_links:
self:
href: /
orders:
href: /orders
/orders:
x-summary: List of Orders
get:
summary: Retrieve List of Orders
description: Retrieves a list of orders with pagination.
parameters:
- $ref: '#/parameters/offset'
- $ref: '#/parameters/limit'
responses:
"200":
description: The list of Orders
schema:
$ref: '#/definitions/supermodelIoAdidasExamplesOrderApiOrders'
post:
summary: Create a New Order
description: Creates a new order.
consumes:
- application/json
parameters:
- name: Order
in: body
description: Order to be created
required: true
schema:
$ref: '#/definitions/supermodelIoAdidasExamplesOrderOrder'
responses:
"201":
description: Newly created order
schema:
$ref: '#/definitions/supermodelIoAdidasExamplesOrderApiOrder'
/orders/{orderId}:
x-summary: Order
parameters:
- name: orderId
in: path
description: Id of the Order
required: true
type: string
x-example: '1234'
get:
summary: Retrieve Order
description: Retrieves an order with specified fields.
parameters:
- $ref: '#/parameters/fields'
responses:
"200":
description: A particular Order
schema:
$ref: '#/definitions/supermodelIoAdidasExamplesOrderApiOrder'
"404":
description: The request Order wasn't found
headers:
Content-Type:
type: string
default: application/problem+json
schema:
allOf:
- $ref: '#/definitions/supermodelIoAdidasApiProblemDetail'
example:
title: 'Not Found'
detail: 'Cannot find the requested order'
status: 404
instance: '/orders/1234'
patch:
summary: Update Order
description: Does a partial update of an order.
consumes:
- application/json
parameters:
- name: Order
in: body
description: Partial order update
required: true
schema:
$ref: '#/definitions/supermodelIoAdidasExamplesOrderApiOrderPatch'
responses:
"200":
description: The Order was updated
schema:
$ref: '#/definitions/supermodelIoAdidasExamplesOrderApiOrder'
delete:
summary: Delete Order
description: Deletes an order without returning its instance.
produces: []
responses:
"204":
description: The Order was deleted
parameters:
# adidas API guidelines: Pagination
offset:
name: offset
in: query
description: Number of results to skip from the start of the list
required: false
type: string
default: '0'
x-example: '10'
# adidas API guidelines: Pagination
limit:
name: limit
in: query
description: The maximum number of reusults to return
required: false
type: string
default: '10'
x-example: '5'
# adidas API guidelines: Sparse fieldset
fields:
name: fields
in: query
description: Comma-separated list of fields to include in the response
required: false
type: array
items:
type: string
collectionFormat: csv
x-example:
- articleNumber
- modelNumber
# adidas API guidelines: Sparse fieldset
embedded:
name: embedded
in: query
description: Comma-separated list of resource (relations) to embed in the response
required: false
type: array
items:
type: string
collectionFormat: csv
x-example:
- prices
- assets
# DO NOT EDIT
# This definitions section is automatically generated by supermodel.io
#
# http://supermodel.io
# https://github.com/supermodel/supermodel-cli
definitions:
supermodelIoAdidasExamplesOrderApiOrder:
title: Order HAL Representation
type: object
allOf:
- $ref: '#/definitions/supermodelIoAdidasApiHAL'
- $ref: '#/definitions/supermodelIoAdidasExamplesOrderOrder'
example:
_links:
self:
href: /orders/1234
edit:
href: /orders/1234
delete:
href: /orders/1234
profile:
href: 'https://adidas-group.com/gdm/OMS'
orderNumber: 1234
itemCount: 42
status: pending
supermodelIoAdidasExamplesOrderApiOrderPatch:
title: OrderPatch
description: OrderPatch model description
type: object
allOf:
- $ref: '#/definitions/supermodelIoAdidasExamplesOrderOrder'
example:
status: cancelled
orderNumber: 1
itemCount: 2
supermodelIoAdidasExamplesOrderApiOrders:
title: Collection of Orders HAL Representation
type: object
allOf:
- $ref: '#/definitions/supermodelIoAdidasApiHAL'
example:
_links:
self:
href: /orders
create:
href: /orders
next:
href: /orders?offset=5&limit=5
first:
href: /orders?offset=0&limit=5
last:
href: /orders?offset=40&limit=5
_embedded:
order:
- _links:
self:
href: /orders/1234
edit:
href: /orders/1234
delete:
href: /orders/1234
profile:
href: 'https://adidas-group.com/gdm/OMS'
orderNumber: 1234
itemCount: 42
status: pending
supermodelIoAdidasExamplesOrderApiProblemDetail:
title: Problem Detail
type: object
allOf:
- $ref: '#/definitions/supermodelIoAdidasApiProblemDetail'
supermodelIoAdidasApiHAL:
title: HAL
description: >-
JSON Hypertext Application Language. Definition of [HAL message
format](https://tools.ietf.org/html/draft-kelly-json-hal-08)
type: object
properties:
_links:
type: object
additionalProperties:
allOf:
- $ref: '#/definitions/supermodelIoAdidasApiHALDefinitionsHalLinkObject'
- type: array
items:
$ref: '#/definitions/supermodelIoAdidasApiHALDefinitionsHalLinkObject'
properties:
curies:
allOf:
- $ref: '#/definitions/supermodelIoAdidasApiHALDefinitionsHalCuriesLink'
- type: array
items:
$ref: >-
#/definitions/supermodelIoAdidasApiHALDefinitionsHalCuriesLink
_embedded:
type: object
additionalProperties:
allOf:
- $ref: '#/definitions/supermodelIoAdidasApiHAL'
- type: array
items:
$ref: '#/definitions/supermodelIoAdidasApiHAL'
supermodelIoAdidasApiHALDefinitionsHalLinkObject:
title: HAL Link Object
type: object
properties:
href:
type: string
templated:
type: boolean
type:
type: string
deprecation:
type: string
name:
type: string
profile:
type: string
title:
type: string
hreflang:
type: string
required:
- href
supermodelIoAdidasApiHALDefinitionsHalCuriesLink:
title: HAL Curies Link
allOf:
- type: object
properties:
templated:
enum:
- true
required:
- templated
- $ref: '#/definitions/supermodelIoAdidasApiHALDefinitionsHalLinkObject'
supermodelIoAdidasExamplesOrderOrder:
title: Order
type: object
description: Order model description
properties:
orderNumber:
type: number
itemCount:
type: number
status:
type: string
required:
- orderNumber
- itemCount
example:
orderNumber: 42
itemCount: 3
status: pending
supermodelIoAdidasApiProblemDetail:
title: Problem Details for HTTP APIs
description: >-
Definition of [RFC7807](https://tools.ietf.org/html/rfc7807) problem
detail
type: object
properties:
type:
type: string
title:
type: string
status:
type: number
detail:
type: string
instance:
type: string
required:
- title
- detail

View File

@@ -1,158 +1,164 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification
termsOfService: http://swagger.io/terms/
contact:
name: Swagger API Team
email: apiteam@swagger.io
url: http://swagger.io
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
- url: http://petstore.swagger.io/api
paths:
/pets:
get:
description: |
Returns all pets from the system that the user has access to
Nam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam. Cras quis velit non tortor eleifend sagittis. Praesent at enim pharetra urna volutpat venenatis eget eget mauris. In eleifend fermentum facilisis. Praesent enim enim, gravida ac sodales sed, placerat id erat. Suspendisse lacus dolor, consectetur non augue vel, vehicula interdum libero. Morbi euismod sagittis libero sed lacinia.
Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condimentum ligula luctus nec. Phasellus semper velit eget aliquet faucibus. In a mattis elit. Phasellus vel urna viverra, condimentum lorem id, rhoncus nibh. Ut pellentesque posuere elementum. Sed a varius odio. Morbi rhoncus ligula libero, vel eleifend nunc tristique vitae. Fusce et sem dui. Aenean nec scelerisque tortor. Fusce malesuada accumsan magna vel tempus. Quisque mollis felis eu dolor tristique, sit amet auctor felis gravida. Sed libero lorem, molestie sed nisl in, accumsan tempor nisi. Fusce sollicitudin massa ut lacinia mattis. Sed vel eleifend lorem. Pellentesque vitae felis pretium, pulvinar elit eu, euismod sapien.
operationId: findPets
parameters:
- name: tags
in: query
description: tags to filter by
required: false
style: form
schema:
type: array
items:
type: string
- name: limit
in: query
description: maximum number of results to return
required: false
schema:
type: integer
format: int32
responses:
'200':
description: pet response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
description: Creates a new pet in the store. Duplicates are allowed
operationId: addPet
requestBody:
description: Pet to add to the store
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NewPet'
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/pets/{id}:
get:
description: Returns a user based on a single ID, if the user does not have access to the pet
operationId: find pet by id
parameters:
- name: id
in: path
description: ID of pet to fetch
required: true
schema:
type: integer
format: int64
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
description: deletes a single pet based on the ID supplied
operationId: deletePet
parameters:
- name: id
in: path
description: ID of pet to delete
required: true
schema:
type: integer
format: int64
responses:
'204':
description: pet deleted
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Pet:
allOf:
- $ref: '#/components/schemas/NewPet'
- type: object
required:
- id
properties:
id:
type: integer
format: int64
NewPet:
type: object
required:
- name
properties:
name:
type: string
tag:
type: string
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification
termsOfService: http://swagger.io/terms/
contact:
name: Swagger API Team
email: apiteam@swagger.io
url: http://swagger.io
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
- url: http://petstore.swagger.io/api
paths:
/pets:
get:
tags: []
description: |
Returns all pets from the system that the user has access to
Nam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam. Cras quis velit non tortor eleifend sagittis. Praesent at enim pharetra urna volutpat venenatis eget eget mauris. In eleifend fermentum facilisis. Praesent enim enim, gravida ac sodales sed, placerat id erat. Suspendisse lacus dolor, consectetur non augue vel, vehicula interdum libero. Morbi euismod sagittis libero sed lacinia.
Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condimentum ligula luctus nec. Phasellus semper velit eget aliquet faucibus. In a mattis elit. Phasellus vel urna viverra, condimentum lorem id, rhoncus nibh. Ut pellentesque posuere elementum. Sed a varius odio. Morbi rhoncus ligula libero, vel eleifend nunc tristique vitae. Fusce et sem dui. Aenean nec scelerisque tortor. Fusce malesuada accumsan magna vel tempus. Quisque mollis felis eu dolor tristique, sit amet auctor felis gravida. Sed libero lorem, molestie sed nisl in, accumsan tempor nisi. Fusce sollicitudin massa ut lacinia mattis. Sed vel eleifend lorem. Pellentesque vitae felis pretium, pulvinar elit eu, euismod sapien.
operationId: findPets
parameters:
- name: tags
in: query
description: tags to filter by
required: false
style: form
schema:
type: array
items:
type: string
- name: limit
in: query
description: maximum number of results to return
required: false
schema:
type: integer
format: int32
responses:
'200':
description: pet response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags: []
description: Creates a new pet in the store. Duplicates are allowed
operationId: addPet
requestBody:
description: Pet to add to the store
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NewPet'
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/pets/{id}:
get:
tags: []
description: Returns a user based on a single ID, if the user does not have access to the pet
operationId: getPetById
parameters:
- name: id
in: path
description: ID of pet to fetch
required: true
schema:
type: integer
format: int64
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags: []
description: deletes a single pet based on the ID supplied
operationId: deletePet
parameters:
- name: id
in: path
description: ID of pet to delete
required: true
schema:
type: integer
format: int64
responses:
'204':
description: pet deleted
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Pet:
allOf:
- $ref: '#/components/schemas/NewPet'
- type: object
required:
- id
properties:
id:
type: integer
format: int64
NewPet:
type: object
required:
- name
properties:
name:
type: string
tag:
type: string
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
tags:
- name: test

View File

@@ -9,3 +9,7 @@ Any JSON-based message **MUST** conform to the following rules:
5. Empty arrays and objects **SHOULD NOT** be `null` \(use `[]` or `{}` instead\)
6. Array field names **SHOULD** be plural \(e.g. `"orders": []`\)
## Validation
All API designers **MUST** validate the definition of the payloads in requests/responses with the [JSON Schema](https://json-schema.org/) for the defined structure prior to the publication of the API Contract in SwaggerHub.
The publication of the JSON schema corresponding to the expected payloads in the bodies of requests and responses **SHOULD** be kept up to date according to the evolution of the API.

View File

@@ -1,6 +0,0 @@
# Introduction
## adidas Kafka Guidelines

View File

@@ -1,6 +1,6 @@
# API Design Platform
1. [SwaggerHub](https://swagger.io/tools/swaggerhub/) is the primary platform supporting [API first approach](../../general-guidelines/api-first.md). SwaggerHub **SHOULD** be used during API Design.
1. [SwaggerHub](https://design.api.3stripes.io/) is the primary platform supporting [API first approach](../../general-guidelines/api-first.md). SwaggerHub **MUST** be used during API Design.
2. Every API description **MUST** be stored in [SwaggerHub](https://design.api.3stripes.io/) under the adidas team.
3. SwaggerHub **MUST** be the **single source of truth** to learn about existing APIs within the organization.

View File

@@ -1,6 +1,6 @@
# OpenAPI Specification
Every API **MUST** be described using an API description format. The API description format used MUST be the [OpenAPI Specification \(formerly known as Swagger Specification\) version 2.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md).
Every API **MUST** be described using an API description format. The API description format used MUST be the [OpenAPI Specification \(formerly known as Swagger Specification\) version 2.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md) OR the[OpenAPI Specification \(formerly known as Swagger Specification\) version 3.0.x](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md).
Every API description **MUST** be published in adidas [API design platform](design-platform.md) and it **SHOULD** be stored in version control system \(Bitbucket, GitHub\) in the same repository as the API implementation.

View File

@@ -2,7 +2,7 @@
## Processing Similar Resources
An operation that needs to process several related resources in bulk **SHOULD** use a collection resource with the appropriate HTTP Request Method. When processing existing resource the request message body **MUST** contain the URLs of the respective resources being processed.
An operation that needs to process several related resources in bulk **SHOULD** uses a collection resource with the appropriate HTTP Request Method. When processing existing resource the request message body **MUST** contain the URLs of the respective resources being processed.
### Example

View File

@@ -1,43 +1,88 @@
# Caching
Every API implementation **SHOULD** return both the cache expiry information \([`Cache-Control` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)\) and specific resource version information \([`ETag` HTTP Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag)\).
> From an architectural point of view, the API cache strategy can be defined at two main levels:
>
> - Backend service
> - API Gateway.
>
> These guidelines handle the cache strategy in the backend service as part of the API implementation. Please consider additional cache settings to be defined in the **API Gateway** can dramatically improve the performance and API consumer experience but they have to be defined in a specific way in the adidas product.
## Cache-Control
As a general rule, every API implementation **SHOULD** return both the cache expiry information \([`Cache-Control` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)\) and specific resource version information \([`ETag` HTTP Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag)\).
## Cache-Control
Every API implementation's response **SHOULD** include information about cache-ability and cache expiration of the response. For HTTP 1.1 this is achieved using the `Cache-Control` header.
### Settings
#### adidas API Gateway
The configuration of cache in the adidas API Gateway is mainly based on:
- Cacheable HTTP methods
- When to cache. Response content types, headers to be considered for the cache key, relevant query parameters, etc.
- Expiration time, meaning the number of seconds to keep resources in the storage backend.
- Strategy. This means, which is the backing data store in which to hold cache entities. The only accepted value is `memory` for now.
> A complete reference for configuration can be seen [here](https://docs.konghq.com/hub/kong-inc/proxy-cache/).
#### API Consumer
Clients **SHOULD** be capable of using `max-age` and `max-stale` headers to exclude the entity from being cached entirely or request stale copies of data if necessary.
### Common Cache-Control Scenarios
Two, most common scenarios for controlling the cache-ability of a response includes \(1\) Setting expiration and revalidation and \(2\) disabling the caching of a response. Refer to the [Cache-Control Documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) for additional controls.
Most common scenarios for controlling the cache-ability of a response includes:
1. Setting expiration and revalidation.
2. Disabling the caching of a response. Refer to the [Cache-Control Documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) for additional information.
> Remember the adidas **API Gateway** identifies the status of the requests proxy cache behavior via the `X-Cache-Status` header. There are several possible values for this header:
> - `Miss` The request could be satisfied in cache, but an entry for the resource was not found in cache, and the request was proxied upstream.
> - `Hit` The request was satisfied and served from cache.
> - `Refresh` The resource was found in cache, but could not satisfy the request, due to Cache-Control behaviors or reaching its hard-coded cache_ttl threshold.
> - `Bypass` The request could not be satisfied from cache based on plugin configuration.
#### 1. Cache Expiration & Revalidation
You **SHOULD** define the expiration time and the case for revalidation in your API.
The common scenario to set cache expiration and revalidation policy is to use the `max-age` and `must-revalidate` directives:
`max-age` is the oldest that a response can be, as long as the Cache-Control from the origin server indicates that it is still fresh. The value means seconds.
> **API Consumer Notes**
> Remember an API consumer's request **MAY** specify the **maximum age** (`max-age`) it is willing to accept an unvalidated response; specifying a value of zero forces the cache to revalidate all responses. A client MAY also specify the minimum time remaining before a response expires. (Reference)[https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html].
> An API consumer **MAY** also specify that it will accept **stale responses**, up to some maximum amount of staleness. API consumers can cache a resource but must revalidate each time before using it. This means HTTP request occurs each time though, it can skip downloading HTTP body if the content is valid. (Reference)[https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html].
From the semantic point of view `no-cache` and `max-age=0`, `must-revalidate` indicates same meaning: The backend service has to be contacted to get a stale result.
The common scenario to set cache expiration and revalidation policy is to use the `max-age`, `must-revalidate` or `max-age` as part of the `Cache-Control` directives.
The `max-age` directive states the maximum amount of time in seconds that fetched responses are allowed to be used again. For instance, `max-age=300` indicates that an asset can be reused (remains in the browser cache) for the next 5 minutes. For instance:
```text
HTTP/1.1 200 OK
Date: Mon, 19 Aug 2017 00:00:00 CEST
Last-Modified: Mon, 19 Aug 2017 00:00:00 CEST
Cache-Control: max-age=3600,must-revalidate
Content-Type: application/hal+json; charset=UTF-8
Cache-Control: max-age=300
```
...
The `must-revalidate` directive is used to tell a cache that it must first revalidate an asset with the origin after it becomes stale. The asset must not be delivered to the client without doing revalidation against the backend service. In short, stale assets must first be verified and expired assets should not be used. For instance:
```text
Cache-Control: must-revalidate
```
#### 2. Disabling Cache
To disable caching completely API implementation **SHOULD** use the `no-cache` and `no-store` directives:
The `no-cache` directive shows that returned responses can't be used for subsequent requests to the same URL before checking if server responses have changed. If a proper ETag (identity of the specific version of the returned resource) is present as a result, no-cache incurs a roundtrip in an effort to validate cached responses.
```text
HTTP/1.1 200 OK
Date: Mon, 19 Aug 2017 00:00:00 CEST
Last-Modified: Mon, 19 Aug 2017 00:00:00 CEST
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/hal+json; charset=UTF-8
...
Cache-Control: no-cache
```
## ETag
Every API implementation's response to a [cacheable request](https://github.com/for-GET/know-your-http-well/blob/master/methods.md#cacheable) **SHOULD** include the [`ETag` HTTP Header](https://tools.ietf.org/html/rfc7232#section-2.3) to identify the specific version of the returned resource.

View File

@@ -0,0 +1,10 @@
# Long Running Tasks
This section includes the recommended approaches to handling long running tasks (LRTs) in REST APIs.
You can identify a LRT quite easily. The main factor to consider are the metrics from latency of the endpoint. If it requiress tens of seconds even minutes we are facing a problem related to LRTs.
LRTs cannot be handled in a regular straight synchronous call. The amount of commited recources at the network, client and server levels are huge when connections are blocked for several minutes.
It is strongly recommended to follow a non-blocking solution as it is proposed in this section.

View File

@@ -0,0 +1,136 @@
# Callback
Callback or Webhooks are another way of handling long running tasks (LRTs). Callbacks are based on the subscription principle, whereas the API notifies the API Consumer in a different connection. This pattern is also applicable to the subscription to any kind of events to get notifications from your API.
The roles are:
- API Consumer / Subscriber
- API Producer / Publisher
If the chosen way is based on using callbacks, the response to such an asynchronous operation **MUST** return, in the case of success, the **202 Accepted** status code together with an `application/hal+json` representation of a new **task-tracking resource**.
> This pattern is described by [OAS v3.0.x](https://swagger.io/docs/specification/callbacks/).
## Subscription
The subscriber enrolls to specfic notifications. The subscriber resource **MUST** provide the information about the callback URL. Any data needed to require the execution of a task **MUST** be included in the request body.
The subscription is created by using the HTTP POST Request Method. It **SHOULD** be designed as follows:
1. Subscription is accepted
Return **201 Created** and representation of the current status. Content type: `application/hal+json`
The publisher resource **MUST** provide a UUID to identify the subscription.
2. Subscription is not accepted
Return **403 Forbidden** . Content type: `application/problem+json` with the problem detail information.
## Notification
The publisher resource **MUST** use callback URL provided by the subscriber. Any data with the output of the requested task **SHOULD** be sent to the subscriber in this request.
The callback request has to use the HTTP POST Request Method **SHOULD** as follows:
1. The subscriber accepts the callback. Content type: `application/hal+json`
Return **200 OK**.
2. The subscriber does not accept the callback
Return **403 Forbidden** . Content type: `application/problem+json` with the problem detail information.
## Cancel Subscription
The subscriber resource **MUST** include the UUID to identify the subscription.
It has to be used the HTTP PUT Request Method **SHOULD** as follows:
1. Subscription is accepted
Return **202 Accepted**. Content type: `application/hal+json`
2. Subscription is not accepted
Return **403 Forbidden** . Content type: `application/problem+json` with the problem detail information.
## Design Note
- The subscription pattern supports two main approaches:
- On one side, it can be **only-once**. The callback will be invoked only once by the publisher and it will be cancelled automatically after.
- On the other side, it can be **continuous**. In this case the subscription **MUST** be explicitly cancelled. Regarding the subscriber, its API is also the subject of the adidas API guidelines.
- The callback can be based on an Asynchronous/Streaming API topic. In this case the subscription is made as mentioned above but with the following differences in the workflow:
- The API Consumer does not send a callback URL in the initial request.
- The API Producer **SHOULD** provide the name of the topic and the UID of the task to correlate the input.
- It is up to the API Consumer to subscribe to the Asynchronous/Streaming API topic to receive the input from the provider. Please read the Asynchronous/Streaming API section.
### Example
1. **Settle the subscription**
```
POST /items/tasks/ HTTP/1.1
Content-Type: application/json
{
"callbackUrl": "https://myserver.com/send/callback/here"
}
...
HTTP/1.1 201 Created
Content-Type: application/hal+json
{
"_links": {
"self": { "href": "/items/tasks/4746" }
},
"message": "Your request to subscribe to the progress of the task has been accepted.",
"UUID": "4746"
}
```
2. **The Publisher sends the callback**
```
POST https://myserver.com/send/callback/here HTTP/1.1
{
"_links": {
"self": { "href": "/items/tasks/4746" }
},
"UUID": "4746",
{
<Data with the callback>
}
}
...
HTTP/1.1 200 Ok
Content-Type: application/hal+json
```
3. **Eventually the subscriber cancels the subscription**
```
PUT /feeds/tasks/1 HTTP/1.1
...
HTTP/1.1 202 Accepted
Content-Type: application/hal+json
{
"_links": {
"self": { "href": "/feeds/tasks/4746" }
},
"message": "Your subscription is cancelled."
}
```

View File

@@ -0,0 +1,82 @@
# Files Upload
The upload of files using a REST API endpoint is a common practice. It implies certain concerns taht have to be addressed in the design phase of the API.
The API Consumer performs a key role in this case. The MIME type in the Content-Type header of the request is an important factor for a successful operation. An operation that needs to upload binary files **SHOULD** uses a collection resource with the POST HTTP Request Method. When processing an existing resource the request message body **MUST** contain the right MIME type of the resources being processed.
## Main Issues
- Too long time periods in timeout settings, blocking open HTTP connections for too long. It makes the API less reliable and more error-prone as it is more vulnerable to network-related issues.
- Interrupted connections that can result into corrupted files and false response status to the API Consumer.
- No size limit in server can suppose an unacceptable load to the API operation in terms of resources, security and robustness as well as a huge increase in operational cost.
## Checklist in File Upload Operations
### Use the right MIME Type in the API Consumer Side
It is a common practice to use
[IANA](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) distinguishes between two main generic types, **discrete** and **multipart**:
- Discrete types are types which represent a single file or medium, such as a single text, video, or music file.
- Multipart type represents a document that is comprised of multiple component parts, each of which may have its own individual MIME type. It can also encapsulate multiple files being sent together in one single transaction.
#### Using a Multipart Type
- multipart/form-data
- multipart/byteranges
Frameworks like Spring offfer support for multipart files sending like the [MultipartFile](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/multipart/MultipartFile.html) interface.
#### Using a Discrete Type
It is recommended to upload the file alone, with no other content in the request. This approach allows to include the MIME type corresponding to the specific type of file. For instance:
- Graphical file -> image/jpeg, image/gif, image/bmp, etc.
- Data file -> text/csv,
- Text file -> text/plain
- PDF -> application/pdf
etc.
It is also recommended to compress the file to be uploaded, then using these MIM types (examples):
- gzip -> application/gzip
- zip -> application/zip
- 7z -> application/x-7z-compressed
- tar -> application/x-tar
etc.
> You can find a complete reference about the MIME types [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types).
### Set Maximum Size Limit in the API Producer Side
The maximum size of the whole file **MUST** be set for the given endpoint/s in the APi upstream/backend service side.
The maximum size value depends on the use case and the expected payload in upload requests.
The settings **MUST** included in the upstream/backend service as a part of the configuration.
Otherwise, the API Gateway (Kong) **COULD** be configured enabling a maximum size of the payload for specific endpoint/s.
Frameworks like Spring includes configuration settings for multipart file uploading. The operation **SHOULD** be constrained as follows:
```
spring.servlet.multipart.enabled=true # enables multipart uploads
spring.servlet.multipart.file-size-threshold=2KB # the threshold after which files are written to disk.
spring.http.multipart.max-file-size=128KB # the total file size cannot exceed the amount o.
spring.http.multipart.max-request-size=128KB # the total request size for a multipart/form-data cannot exceed 128KB.
```
### Configure Properly all the Components
Load tests should give you metrics about the average latency of the operations. Use these metrics to calcuate the best value for the timeout settings in the upstream/backend service.
The API Gateway timeout settings have to be considered for the expected timeout values, aligned with the values in the upstream/backend service. Al other components in the infrastructure **MUST** be considered for the calculation of the final metrics.
git commit
```
|API Consumer/Client Timeout| ---> |External Load Balancer| ---> |API Gateway Timeout| ---> |Internal Load Balancer| ---> |Upstream/Backend Service Tiemout|
```
The approach based on too long timeout values is not acceptable. You **MUST** follow a fast-fail approach with a expected duration of the upload. If this time is exceeded a timeout error **SHOULD** be sent to the API Consumer. The maximum size limit **SHOULD** be consistent with the timeout value.
> Please also consider the client and API Gateway Timeout settings. In this case the lack of retrieval of a response during a too long upload operation can trigger a timeout error.

View File

@@ -1,6 +1,6 @@
# Asynchronous Tasks
# Polling
If an API operation is asynchronous, but a client could track its progress, the response to such an asynchronous operation **MUST** return, in the case of success, the **202 Accepted** status code together with an `application/hal+json` representation of a new **task-tracking resource**.
If an API operation can be considered as a long running task and the API Consumer can track its progress, the response to the LRT **MUST** return, in the case of success, the **202 Accepted** status code together with an `application/hal+json` representation of a new **task-tracking resource**.
## Task Tracking Resource
@@ -22,13 +22,16 @@ Retrieval of such a resource using the HTTP GET Request Method **SHOULD** be des
## Design Note
The asynchronous operation task-tracking resource can be either **polled** by client or the client might initially provide a **callback** to be executed when the operation finishes.
The polling (task-tracking) operation requires a clear adaptation on the API Consumer side:
- Polling requests frequency depend on the type of operation and specific latency of thre resource.
- The identification of the resource has to be correlated along the series of polling requests. The API Consumer has to be able to save this ID and the API Producer has to be able to identify the progress of the operation with that ID.
- A security problem can be raised if a non-authorized client retrieves the response for a different resource ID. The authorization data and tasks in progress have to be strongly correlated and controlled to avoid consistency issues.
In the case of callback, the API and its client MUST agree on what HTTP method and request format is used for the callback invitation. If built within adidas, the "client" API is also the subject of the adidas API guidelines.
### Example
1. **Initiate the asynchronous task**
1. **Initiate the polling task**
```
POST /feeds/tasks/ HTTP/1.1

View File

@@ -1,69 +1,43 @@
# Rate Limiting
The API rate limiting is provided by the selected adidas API management platform Mashery.
Rate limit means how many HTTP requests can be made in a given period of time.
Rate limit information is provided in the for of HTTP headers. There are two types of rate limits: **Quota** and **Throttle**. The quota is a limit enforced per a longer period \(typically a day\). The throttle is the limit of calls per second.
The API rate limiting is provided by the selected adidas API Gateway [Kong](https://konghq.com/kong/). It can be applied to 1 or more endpoints or to the whole API.
## Quota Limit
Rate limit information is provided in the for of HTTP headers.
The limit on the number of calls per a period \(day\). The default quota limit is 5000 calls per day.
## Settings (adidas API Gateway)
### Example
The limit on the number of calls per a time period \(second, minute, hour, day, month, year\). The configuration settings have to be obtained from the Non-Functional Requirements of the API to be included as part of the settings of the API Gateway.
Example response to a request over the quota limit:
A complete reference for configuration can be seen [here](https://adidas.gitbook.io/api-guidelines/rest-api-guidelines/execution/rate-limiting).
## Rate Limit
When this feature is enabled, the API Gateway will send some additional headers back to the client telling what are the limits allowed, how many requests are available and how long it will take until the quota will be restored. For instance (successful response):
```text
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
X-Error-Detail-Header: Account Over Rate Limit
X-Mashery-Error-Code: ERR_403_DEVELOPER_OVER_RATE
{
"title": "Rate Limit Exceeded",
"detail": "Account Over Rate Limit"
}
RateLimit-Limit: 6
RateLimit-Remaining: 4
RateLimit-Reset: 47
X-RateLimit-Limit-Minute: 10
X-RateLimit-Remaining-Minute: 9
```
## Throttle Limit
## Rate Limit Exceeded
The limit on the number of calls per second. The default throttle limit is two calls per second.
### Example
Example response to a request over the throttle limit:
If any of the limits configured in the API Gateway is being reached, it will return a HTTP/1.1 429 status code to the client:
```text
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 1
X-Error-Detail-Header: Account Over Queries Per Second Limit
X-Mashery-Error-Code: ERR_403_DEVELOPER_OVER_QPS
{
"title": "Quota Limit Exceeded",
"detail": "Account Over Queries Per Second Limit"
}
{ "message": "API rate limit exceeded" }
```
> NOTE: The `Retry-After` gives a hint how long before the same request should be repeated \(in seconds\).
## Detail Information
By default, the headers do not contain details about the current usage and quotas. The default can be changed in the API management.
### Example
A successful response with the details about throttle \(`X-Plan-QPS`\) and quota \(`X-Plan-Quota`\) rate limits:
```text
HTTP/1.1 200 OK
X-Plan-QPS-Allotted: 10
X-Plan-QPS-Current: 1
X-Plan-Quota-Allotted: 1000
X-Plan-Quota-Current: 2
X-Plan-Quota-Reset: Tuesday, June 6, 2017 12:00:00 AM GMT
```
> NOTE: The response header `Retry-After` gives a hint how long before the same request should be repeated \(in seconds\).

View File

@@ -10,7 +10,7 @@ The following must be available in the CI environment before testing:
```text
$ node -v
v12.16.0
v14.15.5
```
3. [**Dredd**](https://github.com/apiaryio/dredd) MUST be installed globally in the CI environment:
@@ -21,7 +21,7 @@ The following must be available in the CI environment before testing:
```text
$ dredd --version
dredd v13.0.1
dredd v14.0.0
```
## Testing an API

View File

@@ -1,6 +1,6 @@
# Complete API Development
> NOTE: The content of this file is outdated, refering to previous technologies used at adidas. It is kept for reference until its refresh
1-Design --> 2-Develop --> 3-Deploy --> 4-API Gateway --> 5-Use --> 6-Analyze --> 7-Update
1. **Design the API**
1. Analyze business requirements
@@ -16,23 +16,25 @@
> e.g.: User has many Orders via order relation, all of the required affordances should be mapped to relations.
5. Formalize the design in the [Open API Specification](http://swagger.io/specification/) \(OAS, formerly known as "Swagger"\) format
5. Formalize the design in the [Open API Specification](http://swagger.io/specification/) \(OAS, formerly known as "Swagger"\) version 2.x or 3.0.x format.
> Use **[SwaggerHub](https://design.api.3stripes.io/)** for the whole design process to the publication of the API specification.
6. Follow the [adidas API guidelines](https://adidas.gitbook.io/api-guidelines/introduction/readme)
7. Put the OAS file into [Apiary adidas group](https://apiary.io)
8. Make sure the OAS file passes all adidas API Apiary style guide checks
9. Verify the design using Apiary Documentation and Apiary Mock Service
7. Publish the OAS file in SwaggerHub [under a specific project](https://design.api.3stripes.io/help/organizations/index) in the adidas organization.
8. Verify the OAS file you have written passes the Spectral test.
9. Make sure the OAS file passes all adidas SwaggerHub style guide checks. A red banned will be showed at the bottom of the editor if something is wrong with the OAS content.
10. Review the API Design
11. Put the OAS file in a version control system \(VCS\) repository
12. Set up a CD pipeline to push OAS file from VCS to Apiary, whenever the file is changed
12. Set up a CD pipeline to push OAS file from VCS to SwaggerHub, whenever the file is changed
2. **Develop the API**
1. Check out the VCS repository with the OAS file
2. Set up the [Dredd API testing tool](https://github.com/apiaryio/dredd) locally
3. Configure the Dredd for your project
```text
$ dredd init
```
4. Run the Dredd test locally
> Against locally running API implementation, Every test should fail.
@@ -41,74 +43,88 @@
> Keep running the Dredd locally to see the progress.
6. Set up a [CI/CD pipeline](https://adidas-group.gitbooks.io/api-guidelines/content/guides/api-testing-ci-environment.html) to execute the Dredd tests automatically
6. Set up a [CI/CD pipeline](https://adidas.gitbook.io/api-guidelines/rest-api-guidelines/guides/api-testing-ci-environment) to execute the Dredd tests automatically.
> NOTE: Both TeamCity and Jenkins environments are available, contact adidas API Evangelist for details.
> NOTE: Both TeamCity and Jenkins environments are available, contact adidas API evangelist for details.
3. **Deploy the API**
1. Deploy the service
2. Update the OAS file to add the deployment HOST
2. Update the OAS file to add the deployment host (OAS v2.x) or the deployment servers (OAS v3.0.x). For instance:
> ```text
> host: adidas.api.mashery.com
> basePath: /demo-approval-api
> ```
OAS Version 2.x
```text
host: adidas.api.myapp.com
basePath: /demo-approval-api
```
OAS Version 3.0.x
```yaml
servers:
- url: https://adidas.api.myapp.com/
description: Production cluster
- url: http://stg.adidas.api.myapp.com/
description: Staging cluster
- url: http://dev.adidas.api.myapp.com/
description: Development cluster
```
3. Verify the deployment with Dredd
> Use Dredd pointed towards the deployment host, be careful NOT to run it against the production OR using real production credentials.
4. Monitor the API usage "From performance and technical standpoint."
4. **Expose the API using Mashery**
1. **API**
1. Create new API Definition in Mashery
2. Create a new API Endpoint the API Definition
4. **Expose the API using Kong**
> Ensure you have all the operational context information:
- Type of application
- Servers
- Detailed ownership information (Organiational unit, API Owner, Support contact, etc)
> Set the "Your Endpoint Address" to the internal deployment HOST.
> Ensure you have all the Non-Functional Requirements for your API like:
- Caching strategy detailed for each endpoint
- Rate Limits information
- Scope (internal to adidas or public)
- List of consumers and ACLs
- Authentication & Authorization
3. Create a new API Package in Mashery
4. Create a new API Plan within the API Package
5. Use Mashery API Designer to add the newly created API Definitions' API Endpoint to the API Plan
6. Revisit the API Plan's API key default settings
7. Revisit the API Plan's API default rate limits
8. Revisit the API Plan's access policy/authorization
9. **API Documentation**
1. Create new adidas API developer's portal page in the Mashery
Please read the [API On-Boarding Kong](https://tools.adidas-group.com/confluence/pages/viewpage.action?spaceKey=API2&title=Demand+-+API+Onboarding+in+Kong) to include your API in the adidas API Gateway if it is not done yet.
Once all the information is ready create an [on-boarding request in JIRA](https://tools.adidas-group.com/jira/Secure/CreateIssueDetails!Init.jspa?issuetype=3&pid=28605&issueTemplateId=3701&summary=null&priority=2&labels=Kong-Onboarding).
> Manage &gt; Content &gt; Documentation &gt; APIs
> Read the [API Team Service Catalog](https://tools.adidas-group.com/confluence/pages/viewpage.action?spaceKey=API2&title=Service+catalog) to get more information.
2. [Embed Apiary documentation](https://help.apiary.io/tools/embed/#apiary-embed-api-reference) on the newly created API Page
3. Revisit the API documentation access policy/authorization
5. **Use the API**
> This step can be done at the same time as "Develop the API" thank Apiary hosted Mock, Inspector, and Documentation.
> This step can be done at the same time as "Develop the API" using [SwaggerHub auto-mock service](https://design.api.3stripes.io/help/integrations/api-auto-mocking) and the continuous inspection of the OAS file.
1. Read API documentation at Apiary
2. Use API mock service provided by Apiary
3. Use API call inspector provided by Apiary
4. Obtain your API key
1. Read API documentation at SwaggerHub
2. Use an API implementation stub provided by SwaggerHub.
> The key is part of the API Plan created in Mashery and can be requested from your dashboard in the adidas API developer's portal.
> This is a good starting point for implementing the API, you can run and test it locally, implement the business logic for the API, and then deploy it to your server.
3. Obtain your API key and other information to apply the authentication/authorization mode in your API
5. When available use API implementation via Apiary proxy to debug the API calls
6. Use production deployment
> The key is part of the adidas API Gateway on-boarding process and can be requested from your dashboard in the adidas API developer's portal.
4. Use production deployment
6. **Analyze the API**
1. Examine the use of production API Using Mashery
1. Examine the use of production API Using Kong
2. Analyze the technical performance metrics
3. Collect the feedback from users
7. **Update API Design**
> Based on the analysis, new or changing business requirements
1. Create a new branch in the VCS repository with OAS file
2. Create a new project \(alternative\) in Apiary
2. Create a new project \(alternative\) in SwaggerHub
3. Make sure the CI/CD pipeline is:
1. Set to push the OAS file to Apiary but make sure to modify the Apiary project name
1. Set to push the OAS file to SwaggerHub but make sure to modify the SwaggerHub project name under the adidas organization
2. Set to run Dredd test in the CI/CD
4. Modify the design \(OAS file\) accordingly, follow the "Design API" step
5. Follow the [**rules for extending**](https://adidas-group.gitbooks.io/api-guidelines/content/core-principles/rules-for-extending.html) and [**adidas API guidelines versioning policies**](https://adidas-group.gitbooks.io/api-guidelines/content/evolution/versioning.html)
5. Follow the adidas API Guidelines for [**changes and versioning**](https://adidas.gitbook.io/api-guidelines/rest-api-guidelines/evolution/versioning)
6. Use VCS pull request \(PR\) to propose the change to review
7. After the API Design change is verified, reviewed and approved, continue with the "Develop the API" phase
8. Eventually, when the updated design is ready to be deployed for production, merge the branch into the production branch
9. Follow this guide from "Expose the API using Mashery" step
9. Follow this guide from "Expose the API using Kong" step

View File

@@ -1,16 +1,20 @@
# HAL
The [`application/hal+json`](http://stateless.co/hal_specification.html) \(HAL\) **MUST** be used as the representation format of a resource.
The Hypertext Application Language [`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._
The HAL format is strictly coupled to [HATEOAS](https://en.wikipedia.org/wiki/HATEOAS). The main target of HATEOAS is to decouple the API Consumer from the paths used ion the API. The API Client uses the links generated by our API instead of building them from the documentation. This is less eror-prone for the API Consumer and it can allow making changes in the API without affecting the API Consumer code.
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).
HAL document follow the object model defined in JSON-schema [here](https://supermodel.io/adidas/api/HAL).
IANA created a list explaining the standard relationships for REST. Do not forget to have a look [here](http://www.iana.org/assignments/link-relations/link-relations.xhtml) to find the role of each type of relation.
YAML code snippets are provided for [OpenAPI Specification 2.0/Swagger](https://github.com/adidas/api-guidelines/tree/4a033eb0cf8ec582102c09c1eb5ba1fa8a5597d9/rest-api-guidelines/functionality/message/HAL-snippet.yaml) and [OpenAPI Specification 3.x](https://github.com/adidas/api-guidelines/tree/4a033eb0cf8ec582102c09c1eb5ba1fa8a5597d9/rest-api-guidelines/functionality/message/HAL-snippet-full-OpenApi3.yaml).
@@ -119,9 +123,18 @@ Some APIs using 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.
### Java
### Spring Framework
#### 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).
#### Quarkus Framework
Quarkus framework supports HAL out of the box. More info can be found in [Quarkus Documentation](https://quarkus.io/guides/rest-data-panache).
### NodeJS
For working with HAL and Node.js using [HALson npm package](https://www.npmjs.com/package/halson) is suggested.

View File

@@ -8,3 +8,10 @@
## Tools documentation
* [SwaggerHub Documentation](https://app.swaggerhub.com/help/index)
## Learning Path (adidas-Udemy)
* [Basic](https://adidas-itlearning.udemy.com/course/onboarding-16-api-development-management/)
* [Deep Dive](https://adidas-itlearning.udemy.com/course/onboarding-21-api-development-management/)
* [OpenAPI](https://adidas-itlearning.udemy.com/course/openapi-beginner-to-guru/learn/)

View File

@@ -10,6 +10,8 @@ At a minimum everyone **MUST** be familiar with the semantics of ["Common" HTTP
## Use Codes 4xx or 5xx to Communicate Errors
Remember the 4xx range concern to errors in the API Consumer/Client side while 5xx range concerns to the upstream/backend service, the API implementation.
A request:
```text