SlideShare ist ein Scribd-Unternehmen logo
1 von 164
Downloaden Sie, um offline zu lesen
Consumer
centric API Design
Arrows designed by FreePik
ÜBER MICH
Microservices maßgeschneidert | Arne Limburg
• Enterprise Architect bei der open knowledge GmbH
• Themen
• Microservices
• Domain Driven Design
• APIs
• Architektur
• Coaching
• Technologie (Java EE / Jakarta EE)
Arne Limburg
ÜBER OPEN KNOWLEDGE
Titel der Präsentation | Name des Sprechers
Branchenneutrale Softwareentwicklung und IT-Beratung
Designing an API
Know the goal of the API
#WISSENTEILEN
// Retrieve all products
GET /products
// What about searching, filtering, pagination?
// Retrieve single product
GET /products/1234
// What about buying it?
// i.e. putting to shopping cart, payment, etc.
REST
„URLs“
Wisely choose HTTP
Methods and Resources
#WISSENTEILEN
// Retrieve all customers
GET /customers
// Retrieve single customer with ID 1234
GET /customers/1234
REST
„URLs“
#WISSENTEILEN
// Retrieve single customer with id 1234
GET /customers/1234
// Retrieve all addresses of customer 1234
GET /customers/1234/addresses
// Retrieve address 5 of customer 1234
GET /customers/1234/addresses/5
REST
„root“
#WISSENTEILEN
// Retrieve all addresses of customer 1234
GET /customers/1234/addresses
// vs.
// Retrieve all addresses of customer 1234
GET /addresses/?customerNumber=1234
REST
„root“
#WISSENTEILEN
// Path parameter for identifier
GET /customers/1234
// Query parameter for queries (optional)
GET /customers/?status=verified
// Header parameter for platform (optional)
GET /customers/1234
Accept-Language: de-DE
REST
„param“
#WISSENTEILEN
// Retrieve all addresses of customer 1234
GET /customers/1234/addresses
// vs.
// Retrieve all addresses of customer 1234
GET /addresses/?customerNumber=1234
REST
„root“
#WISSENTEILEN
// Body parameter for resource
PUT /customers/1234
{
... CUSTOMER DATA ...
}
REST
„param“
#WISSENTEILEN
// register customer
POST /customers
{ ... initial customers data ... }
// read customer e.g. to check status
GET /customers/1234
// change customer
PUT /customers/1234
{ ... some changes ... }
// remove customer
DELETE /customers/1234
REST
„method“
#WISSENTEILEN
// „Create new customer“.
POST /customers
// Is this allowed? Guess not. Is it?
POST /customers/1234
// „Change customer“. I‘am sure! But wait ...“
PUT /customers/1234
// „Change customer“, too? Isn‘t it?
PATCH /customers/1234
REST
„method“
#WISSENTEILEN
POST vs. PUT vs. PATCH
POST
erzeugt Child Resource an Server-definierter URI
PUT
erzeugt/ändert Child Resource an Client-definierter URI
PATCH
ändert Teile einer Child Resource an Client-definierter URI
#WISSENTEILEN
// Creates customer. Returns ID 1234
POST /customers
{ ... payload for 1234 ... }
// Hmmm, updates customer 1234? Creates new customer?
POST /customers
{ ... payload for 1234 ... }
REST
„method“
#WISSENTEILEN
// Changes customer with ID 1234
PUT /customers/1234
{ ... changes for 1234 ... }
// Hmmm, will be ignored?
PUT /customers/1234
{ ... changes for 1234, e.g. add e-mail address ... }
// Or additional changes?
PUT /customers/1234
{ ... changes for 1234, e.g. add more e-mail addresses ... }
REST
„method“
Know your Audience
#WISSENTEILEN
// Changes customer with ID 1234
PUT /customers/1234
{ ... changes for 1234 ... }
// Same as PUT? Mayby not!
PATCH /customers/1234
{ ... changes for 1234 ... }
// Same as PUT? Is this what i expect?
GET /customers/1234?status=verified or
GET /customers/1234/setVerified
REST
„method“
#WISSENTEILEN
SAFE / IDEMPOTENT Methods
SAFE*
keine Änderung an der Ressource
IDEMPOTENT**
einmalige Änderung an der Ressource-Repräsentation
mehrfache Wiederholung führt immer zum selben Ergebnis
* GET, HEAD, OPTIONS
** GET, HEAD, OPTIONS, PUT, DELETE
#WISSENTEILEN
REST... Filter, Sorting & Pagination
#WISSENTEILEN
// FILTERING:
// List of paid orders (2015-12-20)
// Common Style
GET /orders?date=20151220&status=payed HTTP 1.1
REST
„filter“
#WISSENTEILEN
// FILTERING:
// Details of order 3 (product, date, ...)
// Facebook Style
GET /orders/3?fields=product,date,status HTTP/1.1
GET /orders/3?fields=item.product,date,status HTTP/1.1
// LinkedIn Style
GET /orders/3:(product, date, status) HTTP/1.1
REST
„filter“
#WISSENTEILEN
// FILTERING:
// Details of order 3
// without date, status
GET /orders/3?exclude=date,status HTTP/1.1
// predefined payload (compact = product, date, status)
GET /orders/3?style=compact HTTP/1.1
REST
„filter“
What is compact?
#WISSENTEILEN
// FILTERING:
// Details of order 3
// using PREFER HEADER for response payload definition
GET /orders/3 HTTP/1.1
Content-Type: application/json
Prefer: return=compact-format
HTTP 1.1 200 OK
Content-Type: application/json; charset=utf-8
Preference-Applied: return=compact-format
REST
„filter“
#WISSENTEILEN
// SORTING:
// orders sorted (date ↓ /item ↑)
// SQL alike style
GET /orders?sort=date+DESC,item+ASC HTTP/1.1
// Sort and asc/desc combination, ascending as default
GET /orders?sort=date,item&desc=date HTTP/1.1
// use prefix „-“ for descending, ascending as default
GET /orders?sort=-date,item HTTP/1.1
REST
„sorting“
#WISSENTEILEN
// FILTERING & SORTING:
// orders of „today“ sorted by ...
// long version
GET /orders?status=open
&date_from=20170510&date_to=20170510
&fields=product,status,time&sort=-time,product
// short and readable version
GET /orders/open_orders_of_today
GET /open_orders_of_today
REST
„filter&sort“
#WISSENTEILEN
// Pagination a.k.a. „Limiting“:
// return page 4 of orders
// Is page a query parameter?
GET /orders?page=4 HTTP/1.1
// Or is page a „virtual“ resource?
GET /orders/pages/4 HTTP/1.1
REST
„pagination“
„4“?
PREV? NEXT?
FIRST? LAST?
#WISSENTEILEN
// Pagination a.k.a. „Limiting“:
// return page 4 of orders
// get “page 4“ and info about PREV/NEXT
GET /orders?offset=10&limit=5 HTTP/1.1
// Response with success code and link header for
// navigation purpose
HTTP/1.1. 200 OK
Link: <.../orders?offset=0&limit=5>; rel=„first“
<.../orders?offset=5&limit=5>; rel=„prev“,
<.../orders?offset=15&limit=5>; rel=„next“,
<.../orders?offset=40&limit=2>; rel=„last“
REST
„pagination“
#WISSENTEILEN
// Pagination a.k.a. „Limiting“:
// return page 4 of orders
// get “page 4“ and info about PREV/NEXT
GET /orders?page=4&limit=5 HTTP/1.1
// Response with success code and link header for
// navigation purpose
HTTP/1.1. 200 OK
Link: <.../orders?page=1&limit=5>; rel=„first“
<.../orders?page=3&limit=5>; rel=„prev“,
<.../orders?page=5&limit=5>; rel=„next“,
<.../orders?page=8&limit=2>; rel=„last“
REST
„pagination“
#WISSENTEILEN
// FULL TEXT SEARCH:
// Fulltext search for coffee
// Global style via virtual resource
GET /searches?q=coffee HTTP/1.1 oder
// Scoped style
GET /orders/searches?q=coffee HTTP/1.1
GET /orders?q=coffee HTTP/1.1
REST
„search“
„GET vs.
POST
„GET vs.
POST
#WISSENTEILEN
// ADVANCED SEARCH:
// Coffee WITH milk for 2€
// Query for ...
GET /orders?type=coffee&ingredient=milk&price=2
REST
„search“
BTW: AND or OR or
AND/OR?
#WISSENTEILEN
// ADVANCED SEARCH:
// Coffee WITH milk for LESS THAN 2€
// Query for ...
GET /orders?query=type=coffee+ingredient=milk+price<=2
REST
„search“
Build your own
„Query Language“?
#WISSENTEILEN
// ADVANCED SEARCH:
// Coffee WITH milk or LESS THAN 2€
// RQL query ... (must possibly be encoded!)
GET /orders?query=
and(eq(type,coffee),
or(eq(ingredients,MILK),lt(price,2))
// RQL alternative query – FIQL (URI friendly) - ...
GET /orders?query=
type==coffee;(ingredients==MILK,price=lt=2)
REST
„search“
Use Standards
Standards promote efficiency, trust and safety
https://www.din.de/en/about-standards/use-standards
#WISSENTEILEN
Caching
#WISSENTEILEN
Always remember: „The Web is your Friend“
• das Web bietet tolle Möglichkeiten zur „Skalierung“
• RESTful Service nutzen das Web bzw. HTTP
• Client (Web Browser, REST Client, ...)
• Proxy Caches („man in the middle cache“)
• Content Delivery Networks (CDNs)
Caching
#WISSENTEILEN
// Caching in REST:
// Expires-Header (HTTP 1.0)
HTTP/1.1 200 Ok
Content-Type: application/json
Expires: Mon, 24 SEP 2018 12:00:01 GMT
{
"id": "1",
"firstName": "Max",
"lastName": "Mustermann",
... ...
}
REST
„Cache“
„Hint, ok. Aber für
wen eigentlich?“
#WISSENTEILEN
CACHING
Cache-Control (HTTP 1.1)
• deutlich genauere Cache-Steuerung als bei Expires Header
• private, public
• no-cache
• no-store
• no-transform
• max-age, s-maxage
#WISSENTEILEN
// Caching in REST:
// Cache-Control (HTTP 1.1)
HTTP/1.1 200 Ok
Content-Type: application/json
Cache-Control: private, no-store, max-age=3600
{
"id": "1",
"firstName": "Max",
"lastName": "Mustermann",
...
}
REST
„Cache“
„Only client side
caching. Valid for
3600 sec. Must not
be stored on disc.“
#WISSENTEILEN
CACHING
Revalidation & Conditional GET (HTTP 1.1)
• Revalidation zur Prüfung, ob Cache-Daten wirklich invalide
• Server sendet speziellen Header zur Prüfung zurück
• Last-Modified
• Etag
#WISSENTEILEN
// Caching in REST:
// Revalidation & Conditional GET
// Cache-Control + Last-Modified Header HTTP 1.1
HTTP/1.1 200 Ok
Content-Type: application/json
Cache-Control: max-age=3600
Last-Modified: Wed, 10 MAI 2017 12:00:01 GMT
{
"id": "1",
...
}
REST
„Cache“
#WISSENTEILEN
// Caching in REST:
// Revalidation & Conditional GET
// Conditional GET after Timeout (max-age)
GET /products/123 HTTP/1.1
If-Modified-Since: Wed, 10 MAI 2017 12:00:01 GMT
REST
„Cache“
Modified since? No,
304 (Not Modified).
Yes, 200 (Ok) plus
Data.
#WISSENTEILEN
// Caching in REST:
// Revalidation & Conditional GET
// Cache-Control + eTag Header HTTP 1.1
HTTP/1.1 200 Ok
Content-Type: application/json
Cache-Control: max-age=3600
eTag: "1234567890987654321"
{
"id": "1",
...
}
REST
„Cache“
#WISSENTEILEN
// Caching in REST:
// Revalidation & Condition GET
// Conditional GET after Timeout (max-age)
GET /products/123 HTTP/1.1
If-None-Match: "1234567890987654321"
REST
„Cache“
Modified since? No,
304 (Not Modified).
Yes, 200 (Ok) plus
Data.
#WISSENTEILEN
// Optimistic Locking
// Conditional PUT
// Conditional PUT
PUT /customers/1234 HTTP/1.1
If-Match: "1234567890987654321"
REST
„Cache“
Modified in between?
No, 200 (OK).
Yes, 412
(Precondition Failed)
#WISSENTEILEN
// Optimistic Locking
// Conditional PUT
// PUT ohne Precondition
PUT /customers/1234 HTTP/1.1
REST
„Cache“
Force Optimistic
Locking:
428 (Precondition
Required)
#WISSENTEILEN
REST ... Headers
#WISSENTEILEN
Headers
HTTP Header Parameter
• Meta Daten für Request / Response
• Accept: ich komme mit Format xyz klar
• Content-Type: ich sende dir Format xyz
• Location-Header: genauere/mehr Info zu „mir“ unter ...
• Link-Header: siehe auch unter ...
• Authorization*-Header: Auth Tokens, Basic Auth ...
• X-Custom-Header: ich habe da noch was für dich ...
{?}
#WISSENTEILEN
REST... Status Codes
(see also: http://www.restpatterns.org/HTTP_Status_Codes/)
#WISSENTEILEN
Pro Tipp: Use them!
• 1xx: Hold on ...
• 2xx: Here you go!
• 3xx: Go away!
• 4xx: You f#!?ed up!
• 5xx: I f#!?ed up!
(http://restlet.com/http-status-codes-map)
Facebook
„Always 200“
Anti-Pattern
HTTP Status Codes
(http://www.restpatterns.org/HTTP_Status_Codes)
#WISSENTEILEN
// HTTP Status Codes:
// signal that new order was created
// „Create new Resource“ of type order
POST /customers HTTP/1.1
[various other headers]
// Response with location header pointing to resource
HTTP/1.1. 201 Created
Location: http://…/customers/1234
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// signal that some work is going on
// Trigger some async workload
POST /customers/
HTTP/1.1
[various other headers]
// Response without payload, cause it‘s not yet calculated
HTTP/1.1. 202 Accepted
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// signal that payload is empty
// DELETE customer with id 1234
DELETE /customers/1234 HTTP/1.1
[various other headers]
// Customer successfully deleted. No content by purpose
HTTP/1.1. 204 No content
HTTP/1.1. 205 Reset content
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// signal that payload is empty
// Retrieve all verified customers
GET /customers?status=verified HTTP/1.1
[various other headers]
// There is no verified customer left.
HTTP/1.1. 204 No content
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// signal that there is more payload
// GET all orders on „page“ two
GET /customers?page=4 HTTP/1.1
[various other headers]
// Response with success code and links for navigation
HTTP/1.1. 206 Partial content
Link: <http://.../customers?page=1>; rel= „first“
<http://.../customers?page=3>; rel= „prev“,
...
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// signal that could not find order
// Ask for customer with id 1234
GET /customers/1234 HTTP/1.1
[various other headers]
// Could not find customer with id 1234
HTTP/1.1. 404 Not found
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// signal that there is a limit problem
// Error Responses: Use them wisely
HTTP/1.1 429 To many request
HTTP/1.1 509 Bandwith limit exceeded
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// Rate limit exceeded (e.g. Twitter)
HTTP/1.1 429 To many requests
[various other headers]
{
"errors": [
{ "code": 88,
"message": "Rate limit exceeded" }
]
}
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// Rate limit exceeded (e.g. Twitter)
HTTP/1.1 200 Ok
[various other headers]
X-Rate-Limit-Limit: ... // rate limit ceiling
X-Rate-Limit-Remaining: ... // for the next 15 minutes
X-Rate-Limit-Reset: ... // in UTC epoch seconds
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// signal that the payload is invalid
// Change customer with id 1234
PUT /customers/1234 HTTP/1.1
[various other headers]
// Some content is invald
HTTP/1.1. 400 Bad Request
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// Bad request
// - Validation error with problem+json
HTTP/1.1 400 Bad request
Content-Type: application/problem+json
[various other headers]
{
"type": "/problems/validation-error",
"title": "Your request parameters didn't validate.",
"status": 400,
"detail": "...",
"instance": "orders/1234"
}
REST
„Codes“
#WISSENTEILEN
// HTTP Status Codes:
// Bad request
// - Validation error with problem+json
HTTP/1.1 400 Bad request
Content-Type: application/problem+json
[various other headers]
{
"type": "/problems/validation-error",
"title": "Your request parameters didn't validate.",
...
"invalid-params": [
{ "path": "firstName",
"message": "firstName is mandatory" } ] }
Custom Extension for
Problem JSON
REST
„Codes“
#WISSENTEILEN
Manchmal kommt es anders, als man denk
• Code for Code: Status Code & Application Level Code
• Message for People: Für Logs, Ausgaben, ...
• Payload and Format: genormte Error-Payload Format
HTTP Status Codes
#WISSENTEILEN
// „Create new customer“.
POST /customers
Content-Type: application/json
// Is this allowed? Guess not. Is it?
POST /customers/1234
Content-Type: application/json
// „Change customer“. I‘am sure! But wait ...“
PUT /customers/1234
Content-Type: application/json
// „Change customer“, too? Isn‘t it?
PATCH /customers/1234
Content-Type: application/json
REST
„method“
#WISSENTEILEN
// HTTP Status Codes:
// Which patch should be used
HTTP/1.1 415 Unsupported Media Type
Content-Type: application/problem+json
[various other headers]
{
"type": "/problems/unsupported-media-type",
"detail": "supported media types are 
application/merge-patch+json or 
application/json-patch+json",
}
REST
„Payload“
#WISSENTEILEN
// HTTP PATCH:
// json/merge-patch+json
POST /customers
Content-Type: application/json
[various other headers]
{
"customerNumber": "1234",
"name": {
"firstName": "Max",
"lastName": "Mustermann"
},
"email": "max.mustermann@beispiel.de"
}
REST
„Payload“
#WISSENTEILEN
// HTTP PATCH:
// json/merge-patch+json
// leave customer number and first name unchanged
// change last name, remove email
PATCH /customers/1234
Content-Type: application/merge-patch+json
[various other headers]
{
"name": {
"lastName": "Muster"
},
"email": null
}
REST
„Payload“
#WISSENTEILEN
// HTTP PATCH:
// json/json-patch+json
PATCH /customers/
Content-Type: application/json-patch+json
[various other headers]
[
{ "op": "remove", "path": "/1234/email" },
{ "op": "replace",
"path": "/1234/name/last", "value": "Muster" },
{ "op": "add",
"path": "/1234/name/additional", "value": "Thomas" },
{ "op": "move", "from": "/1234", "path": "/1235" },
]
REST
„Payload“
#WISSENTEILEN
„Leonard Richardson proposed a
classification for services on the Web.
Leonard’s model promotes three levels of
service maturity based on a service’s
support for URIs, HTTP, and hypermedia!“
(Quelle: „REST in Practice“)
#WISSENTEILEN
RICHARTSON MATURITY MODEL
0
1
2
3 Hypermedia
URI
HTTP
#WISSENTEILEN
RICHARTSON MATURITY MODEL
0
1
2
3 Hypermedia
URI
HTTP
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
Level 0
• a.k.a. „Swamp of PoX“:
• HTTP als Transportsystem
• „RPC“-Style
• eine URI
• eine HTTP Methode (meist POST)
• Parameter und Rückgabe als Payload (XML/JSON/TEXT)
#WISSENTEILEN
RICHARTSON MATURITY MODEL
0
1
2
3 Hypermedia
URI
HTTP
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
Level 1
• Aufbrechen des monolithischen Endpoints aus Level 0 in unterschiedliche
Ressourcen (a.k.a. Nomen), die gezielt angesprochen werden können.
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
Level 1
• a.k.a. „Resources“
• Individuelle Ressourcen statt Service Endpoint
• mehrere URIs
• ein oder zwei HTTP Methode (meist POST/GET)
• Parameter als Query-Parameter oder Payload
• Rückgabe als Payload (XML/JSON/TEXT)
#WISSENTEILEN
RICHARTSON MATURITY MODEL
0
1
2
3 Hypermedia
URI
HTTP
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
Level 2
• Einführen verschiedener „Verben“, um gleiche Situationen mit den selben
Mechanismen behandeln zu können und so unnötige Varianten zu vermeiden.
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
Level 2
• a.k.a. „Verbs“
• „passende“ HTTP Methoden statt nur POST & GET
• mehrere URIs
• mehrere HTTP Methoden
• Rückgabe als Payload & Status Codes
#WISSENTEILEN
RICHARTSON MATURITY MODEL
0
1
2
3 Hypermedia
URI
HTTP
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
Level 3
• Einführen von „Auffindbarkeit“, um so einen Mechanismus anzubieten, der das
Protokoll selbsterklärend(er) macht.
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
Level 3
• a.k.a. „Hypermedia“
• selbsterklärendes System
• nur eine Einstiegs-URI bekannt
• keine weiteren festen URIs
• Rückgabe als Liste von neuen „Möglichkeiten“
Make your API explorable
#WISSENTEILEN
„If the engine of application state (and
hence the API) is not driven by hypertext,
then it cannot be RESTful and cannot be a
REST API. Period. Is there some broken
manual somewhere that needs to be
fixed?“
Roy Fielding
#WISSENTEILEN
„A REST API should be entered with no
prior knowledge beyond the initial URI ...
From that point on, all application state
transitions must be driven by the client
selection of server-provides choices ...“
Roy Fielding
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
/orders/...
POST /orders { order payload }
http/1.1 201 Created
Location: ...
Link: cancel operation
update operation
delete operation
pay operation
C
O
N
S
U
M
E
R
O
R
D
E
R
S
Titel der Präsentation | Name des Sprechers
RICHARTSON MATURITY MODEL
/orders/...
/payments/...
http/1.1 201 Created
Location: ...
Link: http://<status operation>
http://<update operation>
http://<delete operation>
http://<pay operation>
GET
PUT
DELETE
POST
O
R
D
E
R
P
A
Y
#WISSENTEILEN
REST
„Hateoas“ v1
// Richardson Maturity Model:
// Hypermedia as the engine
// of application state
POST /orders/ HTTP/1.1
{ ... payload of order to create ... }
HTTP/1.1. 201 Created
Location: http://restbucks.com/api/orders/1234
Link: <.../orders/1234>; rel=„cancel“
<.../orders/1234>; rel=„update“,
<.../orders/1234>; rel=„delete“,
<.../payment/1234>; rel=„pay“
#WISSENTEILEN
// Aber wie bilde ich Relationen ab?
// the „naive“ way
// all customers
{
[
{ "id":"001", "for":"arne", ..., "addresses":[ ...] },
{ "id":"002", "for":"lars", ..., "addresses":[ ...] },
...
]
}
REST
„relation“
#WISSENTEILEN
// Aber wie bilde ich Relationen ab?
// the „naive“ way
// all customers
{
[
{ "id":"001", "for":"arne", ..., "addresses":[ ...] },
{ "id":"002", "for":"lars", ..., "addresses":[ ...] },
...
]
}
REST
„relation“
Benötige ich die Info hier wirklich?
#WISSENTEILEN
// Aber wie bilde ich Relationen ab?
// the „linked“ way
// all customers
{
[
{ "id":"001", "for":"arne", ..., "address_refs":[...]},
{ "id":"002", "for":"lars", ..., "address_refs":[...] },
...
]
}
REST
„relation“
https://..../customers/002/addresses/1
https://..../customers/002/addresses/2
Benötige ich weitere Infos?
#WISSENTEILEN
// Aber wie bilde ich Relationen ab?
// the „linked“ way
// all customers
{
[
{ "id":"001",
"for":"lars",
...,
"addresses_refs":[...],
"addresses_count" : 2
]
}
REST
„relation“
#WISSENTEILEN
// Aber wie bilde ich Relationen ab?
// the „linked“ way
// all customers
{
[
{ "id":"001",
"for":"lars",
"for_ref ": "http://.../customers/12",
...,
"addresses_refs":[...],
"addresses_count" : 2
]}
REST
„relation“
#WISSENTEILEN
// Aber wie bilde ich Relationen ab?
// the „linked“ way
// all customers
{
[
{ "id":"001", "for":"arne", ..., "address":[
{
"href": "http://.../customers/001/addresses/1"
}
]},
...
]
}
REST
„relation“
Welche Syntax hilft dem Consumer?
#WISSENTEILEN
Content-Type: application/hal+json
{
"_embedded": {
"customers": [{
"_links": {
"self": { "href": "/customers/001“ }, …
},
"name": "Arne Limburg", …
}, …]},
"_links": {
"next": …
"find": {"href": "/customers{?tags}", "templated": true}
}, …
}
REST
„relation“
Document your API
API First
#WISSENTEILEN
DOCUMENTATION
OpenAPI Specification (OAS)
Design mit Swagger Editor Build mit Swagger Codegen Dokumentiere mit Swagger-UI
#WISSENTEILEN
// openapi.json
// JSON-Schema / OpenAPI Example
"post" : {
"parameters" : [ {
"in" : "body",
"name" : "body",
"description" : "new customer",
"required" : true,
"schema" : {
"$ref" : "#/definitions/Customer"
}
} ]
}
REST
„OpenAPI“
#WISSENTEILEN
// openapi.json (JSON Schema)
"definitions" : {
"CustomerResourceType" : {
"type" : "object",
"required" : [ "firstName", "lastName”, … ],
"properties" : {
"firstName" : {
"type" : "string",
"minLength" : 1,
"maxLength" : 30,
"pattern" : "..."
}
}
REST
„OpenAPI“
Evolve your API
MICROSERVICES ARCHITEKTUR
Address Validation Service
Delivery Service
Customer Service
Billing Service
Tolerant Reader Pattern
Tolerant gegenüber unbekannten Feldern
Umgang mit x-extensible-enum
http://zalando.github.io/restful-api-guidelines
EXKURS X-EXTENSIBLE-ENUM
Beispiel
address_type:
type: string
x-extensible-enum:
- private
- business
Tolerant Reader Pattern
Tolerant gegenüber unbekannten Feldern
Umgang mit x-extensible-enum
http://zalando.github.io/restful-api-guidelines
Tolerant gegenüber unbekannten Statuscodes
HTTP Status 301 folgen
TOLERANT READER PATTERN
http://www.example.com/addresses/42
àLiefert Addresse
{
street: {
"name": "Poststraße",
"number": "1",
},
"city": "26122 Oldenburg"
}
TOLERANT READER PATTERN
http://www.example.com/addresses/42
Attribut hinzufügen
{
street: {
"name": "Poststraße",
"number": "1",
"additionalAdressLine": "2. Obergeschoss"
},
"city": "26122 Oldenburg"
}
TOLERANT READER PATTERN
Server schickt
{
street: {
"name": "Poststraße",
"number": "1",
"additionalAdressLine":
"2. Obergeschoss"
}...
}
http://www.example.com/addresses/42
Client erwartet
{
street: {
"name": "Poststraße",
"number": "1",
}...
}
TOLERANT READER PATTERN
http://www.example.com/addresses/42
Attribut-Umbenennung
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
},
"city": "26122 Oldenburg"
}
TOLERANT READER PATTERN
http://www.example.com/addresses/42
àAbwärtskompatible Änderungen: Umbenennen durch Kopieren
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
},
"city": "26122 Oldenburg"
}
Und was ist, wenn der Client kein
Tolerant Reader ist?
PROJEKTIONEN
// Client kann entscheiden, welche Felder er bekommen möchte
// Facebook Style
GET /addresses/3?fields=street,city
GET /addresses/3?fields=street.name,street.number,city
// LinkedIn Style
GET /addresses/3?fields=street:(name,number),city
OK, so soll sich
der Client verhalten.
Aber was ist mit dem Server?
Photo by Irene Fertik, USC News Service. Copyright 1994, USC.
„Be conservative in what you do,
Be liberal in what you accept
from others“
RFC 793, Robustness Principal (John Postel)
Es darf nichts entfernt werden
Keine Veränderung von Verarbeitungsregel
Optionales darf nie Required werden
http://zalando.github.io/restful-api-guidelines
Alles was hinzugefügt wird, muss optional sein
MAGNANIMOUS WRITER PATTERN
Server schickt
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1“
}...
}
http://www.example.com/addresses/42
Client erwartet
{
street: {
"name": "Poststraße",
"number": "1",
}...
}
http://tenderware.blogspot.de/2011/05/magnanimous-writer.html
MAGNANIMOUS WRITER PATTERN
Server schickt
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1“
}...
}
http://www.example.com/addresses/42
Client erwartet
{
street: {
"streetName": "Poststraße",
"houseNumber": "1",
}...
}
http://tenderware.blogspot.de/2011/05/magnanimous-writer.html
MAGNANIMOUS WRITER PATTERN
Server erwartet
PUT http://www.example.com/addresses/42
Client schickt
{
street: {
"name": "Poststraße",
"number": "1",
}...
}
http://tenderware.blogspot.de/2011/05/magnanimous-writer.html
MAGNANIMOUS WRITER PATTERN
PUT http://www.example.com/addresses/42
Client schickt
{
street: {
"name": "Poststraße",
"number": "1",
}...
}
http://tenderware.blogspot.de/2011/05/magnanimous-writer.html
Server erwartet
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1“
}...
}
oder
oder
MAGNANIMOUS WRITER PATTERN
PUT http://www.example.com/addresses/42
Client schickt
{
street: {
"streetName": "Poststraße",
"houseNumber": "1",
}...
}
http://tenderware.blogspot.de/2011/05/magnanimous-writer.html
Server erwartet
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1“
}...
}
oder
oder
MERGE PATCH UND NULL VALUES
PATCH /addresses/42 HTTP/1.1
Content-Type: application/merge-patch+json
Client schickt
{
street: {
"name": null,
}...
}
https://tools.ietf.org/html/rfc7396
ABWÄRTSKOMPATIBILITÄT
http://www.example.com/addresses/42
àAbwärtskompatible Änderungen: Umbenennen durch Kopieren
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
},
"city": "26122 Oldenburg"
}
Geht da noch mehr?
ABWÄRTSKOMPATIBILITÄT
http://www.example.com/addresses/42
àZusammenführen und Teilen von Attributen
{
street: {
...
"streetName": "Poststraße",
"houseNumber": "1",
"addressLine1": "Poststraße 1",
}
...
}
ABWÄRTSKOMPATIBILITÄT
http://www.example.com/addresses/42
àHerausforderungen: Zusammenführen von Attributen
{
street: {
...
"streetName": "Poststraße",
"houseNumber": "1",
"addressLine1": "Poststraße 1",
}
...
}
ABWÄRTSKOMPATIBILITÄT
http://www.example.com/addresses/42
àHerausforderungen: Teilen von Attributen
{
street: {
...
"addressLine1": "Poststraße 1",
}
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg"
}
ABWÄRTSKOMPATIBILITÄT
http://www.example.com/addresses/42
àHerausforderungen: Ebene von Attributen ändern
{
street: {
...
"addressLine1": "Poststraße 1"
}
"addressLine1": "Poststraße 1",
...
}
ABWÄRTSKOMPATIBILITÄT
http://www.example.com/addresses/42
àHerausforderungen: Ebene von Attributen ändern
{
...
"zipCode": "26122",
"cityName": "Oldenburg",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
ABWÄRTSKOMPATIBILITÄT
http://www.example.com/addresses/42
àHerausforderungen: Ebene von Attributen ändern
{
...
"zipCode": "26122",
"cityName": "Oldenburg",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
Bei jeder Modelländerung muss
eine Migrationsstrategie
einbezogen werden!
ABWÄRTSKOMPATIBILITÄT
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
}
"addressLine1": "Poststraße 1",
"addressLine2": "",
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
http://www.example.com/v1/addresses/42
àBisher nur abwärtskompatible Änderungen
ABWÄRTSKOMPATIBILITÄT
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
}
"addressLine1": "Poststraße 1",
"addressLine2": "",
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
http://www.example.com/v1/addresses/42
àViele Attribute deprecated
Wie kann ich Attribute entfernen?
Don‘t ever break your
Client
Incompatible Change
vs. Breaking Change
http://zalando.github.io/restful-api-guidelines
WELCHE CLIENTS NUTZEN MICH?
API (PROVIDER CONTRACT)
CONSUMER CONTRACT
CONSUMER CONTRACT – YAGNI
CONSUMER-DRIVEN CONTRACT TEST
Consumer
Contract
Consumer Provider
Consumer
Tests
Provider
Tests
MICROSERVICES ARCHITEKTUR
Address Validation Service
Delivery Service
Customer Service
Billing Service
PIPELINE TO DEPLOY TO STAGE
Execute
Own
Provider
Tests
Generate
Consumer
Contract
Execute
Depending
Provider
Tests
Deploy
to
Stage
PIPELINE TO DEPLOY TO STAGE
Execute
Own
Provider
Tests
Generate
Consumer
Contract
Execute
Depending
Provider
Tests
Deploy
to
Stage
Achtung:
Abwärtskompatibilität ist
trotzdem notwendig!
BREAKING CHANGE VOM PROVIDER
Execute
Own
Provider
Tests
Generate
Consumer
Contract
Execute
Depending
Provider
Tests
Deploy
to
Stage
BREAKING CHANGE VOM CONSUMER
Execute
Own
Provider
Tests
Generate
Consumer
Contract
Execute
Depending
Provider
Tests
Deploy
to
Stage
Und wenn ich meine Consumer
nicht kenne?
VERSIONSSPRUNG
{
street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
}
"addressLine1": "Poststraße 1",
"addressLine2": "",
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
http://www.example.com/v1/addresses/42
àBisher nur abwärtskompatible Änderungen
INKOMPATIBLE ÄNDERUNG
http://www.example.com/v2/addresses/42
àVersionssprung
{
"addressLine1": "Poststraße 1",
"addressLine2": "",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
INKOMPATIBLE ÄNDERUNG
Version 2.0
ist nur inkompatibel zu 1.0!
Version 2.0 ist identisch zu 1.x!
Das erleichtert das Mapping
zwischen den Versionen!
Ein solcher Versionssprung ist
nicht anforderungsgetrieben,
sondern viel besser und
langfristiger planbar
Wenn eine neue Version
nicht auf die alte abbildbar ist,
ist es keine neue Version,
sondern eine neue Schnittstelle!
• Über URL-Pfad
/v2/addresses
• Über Query-Parameter
/addresses?version=v2
• Über Version-Header
X-Api-Version: v2
• Über Version-Attribut am Media-Type
application/xml;version=v2
• Über Media-Type
application/vnd.de.openknowledge+v2+json
ERMITTELN DER VERSION
ABWÄRTSKOMPATIBILITÄT
Schnittstelle Schnittstelle
{ street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
}
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg",
"addressLine1": "Poststraße 1",
"addressLine2": "",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
{
"addressLine1": "Poststraße 1",
"addressLine2": "“,
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
V1 V2-SNAPSHOT
ABWÄRTSKOMPATIBILITÄT
Schnittstelle Schnittstelle
{ street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
},
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg",
"addressLine1": "Poststraße 1",
"addressLine2": "“,
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
{
"addressLine1": "Poststraße 1",
"addressLine2": "",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
V1 V2-SNAPSHOT
AUTOMATISIERTES MAPPING
Schnittstelle Schnittstelle
{ "street": {
"name": "Poststraße",
"number": "1",
},
"city": "26122 Oldenburg"
}
{
"street": {
"name": "Poststraße",
"number": "1"
},
"city": "26122 Oldenburg"
}
V1 V2-SNAPSHOT
WEITERENTWICKLUNG
Schnittstelle Schnittstelle
{ "street": {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
},
"city": "26122 Oldenburg"
}
{
"street": {
"streetName": "Poststraße",
"houseNumber": "1"
},
"city": "26122 Oldenburg"
}
V1 V2-SNAPSHOT
WEITERENTWICKLUNG
Schnittstelle Schnittstelle
{ "street": {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
},
"city": "26122 Oldenburg"
}
{
"street": {
"addressLine1": "Post… 1",
"addressLine2": ""
},
"city": "26122 Oldenburg"
}
V1 V2-SNAPSHOT
WEITERENTWICKLUNG
Schnittstelle Schnittstelle
{ "street": {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
},
"addressLine1": "Poststraße 1",
"addressLine2": "",
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg",
}
{
"addressLine1": "Poststraße 1",
"addressLine2": "",
"zipCode": "26122",
"cityName": "Oldenburg"
}
V1 V2-SNAPSHOT
WEITERENTWICKLUNG
Schnittstelle Schnittstelle
{ "street": {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
},
"addressLine1": "Poststraße 1",
"addressLine2": "",
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
{
"addressLine1": "Poststraße 1",
"addressLine2": "",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
V1 V2-SNAPSHOT
ABWÄRTSKOMPATIBILITÄT
Schnittstelle Schnittstelle
{ street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
},
"city": "26122 Oldenburg",
"zipCode": "26122",
"cityName": "Oldenburg",
"addressLine1": "Poststraße 1",
"addressLine2": "“,
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
{
"addressLine1": "Poststraße 1",
"addressLine2": "",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
},
"city": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
V1 V2-SNAPSHOT
ABWÄRTSKOMPATIBILITÄT
Schnittstelle
Schnittstelle
{ street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
}
...
}
{
"addressLine1": "Poststraße 1",
"addressLine2": "",
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
V1 V3-SNAPSHOT
Schnittstelle
{ "addressLine1": "Poststraße 1",
"addressLine2": "“,
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
V2
ABWÄRTSKOMPATIBILITÄT
Schnittstelle
Schnittstelle
{ street: {
"name": "Poststraße",
"streetName": "Poststraße",
"number": "1",
"houseNumber": "1",
"addressLine1": "Post... 1",
"addressLine2": ""
}
...
}
{
"addressLine1": "Poststraße 1",
"addressLine2": "",
"city": {
"zipCode": "26122",
"cityName": "Oldenburg"
}
}
V1 V3-SNAPSHOT
Schnittstelle
{ "addressLine1": "Poststraße 1",
"addressLine2": "“,
"location": {
"zipCode": "26122",
"cityName": "Oldenburg"
},
"city": {
"zipCode": "26122",
"cityName": "Oldenburg"
}} V2
KONTAKT
Titel der Präsentation | Name des Sprechers
ARNE LIMBURG,
ENTERPRISE ARCHITECT
arne.limburg@openknowledge.de
+49 (0)441 40820
OFFENKUNDIGGUT
FRAGEN & DISKUSSION
? ? ?

Weitere ähnliche Inhalte

Ähnlich wie Consumer-centric API Design

Pragmatic REST aka praxisnahes Schnittstellendesign
Pragmatic REST aka praxisnahes SchnittstellendesignPragmatic REST aka praxisnahes Schnittstellendesign
Pragmatic REST aka praxisnahes SchnittstellendesignOPEN KNOWLEDGE GmbH
 
Rest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.jsRest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.jsCarol McDonald
 
[drupalday2017] - Drupal come frontend che consuma servizi: HTTP Client Manager
[drupalday2017] - Drupal come frontend che consuma servizi: HTTP Client Manager[drupalday2017] - Drupal come frontend che consuma servizi: HTTP Client Manager
[drupalday2017] - Drupal come frontend che consuma servizi: HTTP Client ManagerDrupalDay
 
REST API Best Practices & Implementing in Codeigniter
REST API Best Practices & Implementing in CodeigniterREST API Best Practices & Implementing in Codeigniter
REST API Best Practices & Implementing in CodeigniterSachin G Kulkarni
 
No REST - Architecting Real-time Bulk Async APIs
No REST - Architecting Real-time Bulk Async APIsNo REST - Architecting Real-time Bulk Async APIs
No REST - Architecting Real-time Bulk Async APIsC4Media
 
Microservice Websites – Micro CPH
Microservice Websites – Micro CPHMicroservice Websites – Micro CPH
Microservice Websites – Micro CPHGustaf Nilsson Kotte
 
Building RESTful applications using Spring MVC
Building RESTful applications using Spring MVCBuilding RESTful applications using Spring MVC
Building RESTful applications using Spring MVCIndicThreads
 
RefCard RESTful API Design
RefCard RESTful API DesignRefCard RESTful API Design
RefCard RESTful API DesignOCTO Technology
 
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013Kiril Iliev
 
Rest api standards and best practices
Rest api standards and best practicesRest api standards and best practices
Rest api standards and best practicesAnkita Mahajan
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to TornadoGavin Roy
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformAntonio Peric-Mazar
 
Are you getting Sleepy. REST in SharePoint Apps
Are you getting Sleepy. REST in SharePoint AppsAre you getting Sleepy. REST in SharePoint Apps
Are you getting Sleepy. REST in SharePoint AppsLiam Cleary [MVP]
 
Architecting &Building Scalable Secure Web API
Architecting &Building Scalable Secure Web APIArchitecting &Building Scalable Secure Web API
Architecting &Building Scalable Secure Web APISHAKIL AKHTAR
 

Ähnlich wie Consumer-centric API Design (20)

Consumer-Centric API Design
Consumer-Centric API DesignConsumer-Centric API Design
Consumer-Centric API Design
 
Pragmatic REST aka praxisnahes Schnittstellendesign
Pragmatic REST aka praxisnahes SchnittstellendesignPragmatic REST aka praxisnahes Schnittstellendesign
Pragmatic REST aka praxisnahes Schnittstellendesign
 
Rest
RestRest
Rest
 
Rest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.jsRest with Java EE 6 , Security , Backbone.js
Rest with Java EE 6 , Security , Backbone.js
 
[drupalday2017] - Drupal come frontend che consuma servizi: HTTP Client Manager
[drupalday2017] - Drupal come frontend che consuma servizi: HTTP Client Manager[drupalday2017] - Drupal come frontend che consuma servizi: HTTP Client Manager
[drupalday2017] - Drupal come frontend che consuma servizi: HTTP Client Manager
 
Ws rest
Ws restWs rest
Ws rest
 
REST API Best Practices & Implementing in Codeigniter
REST API Best Practices & Implementing in CodeigniterREST API Best Practices & Implementing in Codeigniter
REST API Best Practices & Implementing in Codeigniter
 
REST easy with API Platform
REST easy with API PlatformREST easy with API Platform
REST easy with API Platform
 
No REST - Architecting Real-time Bulk Async APIs
No REST - Architecting Real-time Bulk Async APIsNo REST - Architecting Real-time Bulk Async APIs
No REST - Architecting Real-time Bulk Async APIs
 
Microservice Websites – Micro CPH
Microservice Websites – Micro CPHMicroservice Websites – Micro CPH
Microservice Websites – Micro CPH
 
Elasticsearch
ElasticsearchElasticsearch
Elasticsearch
 
Cqrs api v2
Cqrs api v2Cqrs api v2
Cqrs api v2
 
Building RESTful applications using Spring MVC
Building RESTful applications using Spring MVCBuilding RESTful applications using Spring MVC
Building RESTful applications using Spring MVC
 
RefCard RESTful API Design
RefCard RESTful API DesignRefCard RESTful API Design
RefCard RESTful API Design
 
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
 
Rest api standards and best practices
Rest api standards and best practicesRest api standards and best practices
Rest api standards and best practices
 
An Introduction to Tornado
An Introduction to TornadoAn Introduction to Tornado
An Introduction to Tornado
 
Building APIs in an easy way using API Platform
Building APIs in an easy way using API PlatformBuilding APIs in an easy way using API Platform
Building APIs in an easy way using API Platform
 
Are you getting Sleepy. REST in SharePoint Apps
Are you getting Sleepy. REST in SharePoint AppsAre you getting Sleepy. REST in SharePoint Apps
Are you getting Sleepy. REST in SharePoint Apps
 
Architecting &Building Scalable Secure Web API
Architecting &Building Scalable Secure Web APIArchitecting &Building Scalable Secure Web API
Architecting &Building Scalable Secure Web API
 

Mehr von OPEN KNOWLEDGE GmbH

Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AIWarum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AIOPEN KNOWLEDGE GmbH
 
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...OPEN KNOWLEDGE GmbH
 
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die CloudFrom Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die CloudOPEN KNOWLEDGE GmbH
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data ImputationFEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data ImputationOPEN KNOWLEDGE GmbH
 
Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!OPEN KNOWLEDGE GmbH
 
From Zero to still Zero: The most beautiful mistakes going into the cloud.
From Zero to still Zero: The most beautiful mistakes going into the cloud. From Zero to still Zero: The most beautiful mistakes going into the cloud.
From Zero to still Zero: The most beautiful mistakes going into the cloud. OPEN KNOWLEDGE GmbH
 
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & Co
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & CoReady for the Future: Jakarta EE in Zeiten von Cloud Native & Co
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & CoOPEN KNOWLEDGE GmbH
 
Shared Data in verteilten Architekturen
Shared Data in verteilten ArchitekturenShared Data in verteilten Architekturen
Shared Data in verteilten ArchitekturenOPEN KNOWLEDGE GmbH
 
Machine Learning mit TensorFlow.js
Machine Learning mit TensorFlow.jsMachine Learning mit TensorFlow.js
Machine Learning mit TensorFlow.jsOPEN KNOWLEDGE GmbH
 
It's not Rocket Science: Neuronale Netze
It's not Rocket Science: Neuronale NetzeIt's not Rocket Science: Neuronale Netze
It's not Rocket Science: Neuronale NetzeOPEN KNOWLEDGE GmbH
 
Shared Data in verteilten Systemen
Shared Data in verteilten SystemenShared Data in verteilten Systemen
Shared Data in verteilten SystemenOPEN KNOWLEDGE GmbH
 
Mehr Sicherheit durch Automatisierung
Mehr Sicherheit durch AutomatisierungMehr Sicherheit durch Automatisierung
Mehr Sicherheit durch AutomatisierungOPEN KNOWLEDGE GmbH
 
API-Design, Microarchitecture und Testing
API-Design, Microarchitecture und TestingAPI-Design, Microarchitecture und Testing
API-Design, Microarchitecture und TestingOPEN KNOWLEDGE GmbH
 
Supersonic Java für die Cloud: Quarkus
Supersonic Java für die Cloud: QuarkusSupersonic Java für die Cloud: Quarkus
Supersonic Java für die Cloud: QuarkusOPEN KNOWLEDGE GmbH
 
Hilfe, ich will meinen Monolithen zurück!
Hilfe, ich will meinen Monolithen zurück!Hilfe, ich will meinen Monolithen zurück!
Hilfe, ich will meinen Monolithen zurück!OPEN KNOWLEDGE GmbH
 

Mehr von OPEN KNOWLEDGE GmbH (20)

Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AIWarum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
Warum der Computer "Nein" sagt - Mehr Nachvollziehbarkeit dank Explainable AI
 
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
Machine Learning? Ja gerne! Aber was und wie? Eine Kurzanleitung für den erfo...
 
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die CloudFrom Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
From Zero to still Zero: Die schönsten Fehler auf dem Weg in die Cloud
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data ImputationFEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
FEHLENDE DATEN? (K)EIN PROBLEM!: Die Kunst der Data Imputation
 
Nie wieder Log-Files!
Nie wieder Log-Files!Nie wieder Log-Files!
Nie wieder Log-Files!
 
Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!Cloud-native and Enterprise Java? Hold my beer!
Cloud-native and Enterprise Java? Hold my beer!
 
From Zero to still Zero: The most beautiful mistakes going into the cloud.
From Zero to still Zero: The most beautiful mistakes going into the cloud. From Zero to still Zero: The most beautiful mistakes going into the cloud.
From Zero to still Zero: The most beautiful mistakes going into the cloud.
 
API Expand Contract
API Expand ContractAPI Expand Contract
API Expand Contract
 
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & Co
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & CoReady for the Future: Jakarta EE in Zeiten von Cloud Native & Co
Ready for the Future: Jakarta EE in Zeiten von Cloud Native & Co
 
Shared Data in verteilten Architekturen
Shared Data in verteilten ArchitekturenShared Data in verteilten Architekturen
Shared Data in verteilten Architekturen
 
Machine Learning mit TensorFlow.js
Machine Learning mit TensorFlow.jsMachine Learning mit TensorFlow.js
Machine Learning mit TensorFlow.js
 
KI und Architektur
KI und ArchitekturKI und Architektur
KI und Architektur
 
It's not Rocket Science: Neuronale Netze
It's not Rocket Science: Neuronale NetzeIt's not Rocket Science: Neuronale Netze
It's not Rocket Science: Neuronale Netze
 
Shared Data in verteilten Systemen
Shared Data in verteilten SystemenShared Data in verteilten Systemen
Shared Data in verteilten Systemen
 
Business-Mehrwert durch KI
Business-Mehrwert durch KIBusiness-Mehrwert durch KI
Business-Mehrwert durch KI
 
Mehr Sicherheit durch Automatisierung
Mehr Sicherheit durch AutomatisierungMehr Sicherheit durch Automatisierung
Mehr Sicherheit durch Automatisierung
 
API-Design, Microarchitecture und Testing
API-Design, Microarchitecture und TestingAPI-Design, Microarchitecture und Testing
API-Design, Microarchitecture und Testing
 
Supersonic Java für die Cloud: Quarkus
Supersonic Java für die Cloud: QuarkusSupersonic Java für die Cloud: Quarkus
Supersonic Java für die Cloud: Quarkus
 
Hilfe, ich will meinen Monolithen zurück!
Hilfe, ich will meinen Monolithen zurück!Hilfe, ich will meinen Monolithen zurück!
Hilfe, ich will meinen Monolithen zurück!
 

Kürzlich hochgeladen

chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 

Kürzlich hochgeladen (20)

chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 

Consumer-centric API Design

  • 2. ÜBER MICH Microservices maßgeschneidert | Arne Limburg • Enterprise Architect bei der open knowledge GmbH • Themen • Microservices • Domain Driven Design • APIs • Architektur • Coaching • Technologie (Java EE / Jakarta EE) Arne Limburg
  • 3. ÜBER OPEN KNOWLEDGE Titel der Präsentation | Name des Sprechers Branchenneutrale Softwareentwicklung und IT-Beratung
  • 5. Know the goal of the API
  • 6. #WISSENTEILEN // Retrieve all products GET /products // What about searching, filtering, pagination? // Retrieve single product GET /products/1234 // What about buying it? // i.e. putting to shopping cart, payment, etc. REST „URLs“
  • 8. #WISSENTEILEN // Retrieve all customers GET /customers // Retrieve single customer with ID 1234 GET /customers/1234 REST „URLs“
  • 9. #WISSENTEILEN // Retrieve single customer with id 1234 GET /customers/1234 // Retrieve all addresses of customer 1234 GET /customers/1234/addresses // Retrieve address 5 of customer 1234 GET /customers/1234/addresses/5 REST „root“
  • 10. #WISSENTEILEN // Retrieve all addresses of customer 1234 GET /customers/1234/addresses // vs. // Retrieve all addresses of customer 1234 GET /addresses/?customerNumber=1234 REST „root“
  • 11. #WISSENTEILEN // Path parameter for identifier GET /customers/1234 // Query parameter for queries (optional) GET /customers/?status=verified // Header parameter for platform (optional) GET /customers/1234 Accept-Language: de-DE REST „param“
  • 12. #WISSENTEILEN // Retrieve all addresses of customer 1234 GET /customers/1234/addresses // vs. // Retrieve all addresses of customer 1234 GET /addresses/?customerNumber=1234 REST „root“
  • 13. #WISSENTEILEN // Body parameter for resource PUT /customers/1234 { ... CUSTOMER DATA ... } REST „param“
  • 14. #WISSENTEILEN // register customer POST /customers { ... initial customers data ... } // read customer e.g. to check status GET /customers/1234 // change customer PUT /customers/1234 { ... some changes ... } // remove customer DELETE /customers/1234 REST „method“
  • 15. #WISSENTEILEN // „Create new customer“. POST /customers // Is this allowed? Guess not. Is it? POST /customers/1234 // „Change customer“. I‘am sure! But wait ...“ PUT /customers/1234 // „Change customer“, too? Isn‘t it? PATCH /customers/1234 REST „method“
  • 16. #WISSENTEILEN POST vs. PUT vs. PATCH POST erzeugt Child Resource an Server-definierter URI PUT erzeugt/ändert Child Resource an Client-definierter URI PATCH ändert Teile einer Child Resource an Client-definierter URI
  • 17. #WISSENTEILEN // Creates customer. Returns ID 1234 POST /customers { ... payload for 1234 ... } // Hmmm, updates customer 1234? Creates new customer? POST /customers { ... payload for 1234 ... } REST „method“
  • 18. #WISSENTEILEN // Changes customer with ID 1234 PUT /customers/1234 { ... changes for 1234 ... } // Hmmm, will be ignored? PUT /customers/1234 { ... changes for 1234, e.g. add e-mail address ... } // Or additional changes? PUT /customers/1234 { ... changes for 1234, e.g. add more e-mail addresses ... } REST „method“
  • 20. #WISSENTEILEN // Changes customer with ID 1234 PUT /customers/1234 { ... changes for 1234 ... } // Same as PUT? Mayby not! PATCH /customers/1234 { ... changes for 1234 ... } // Same as PUT? Is this what i expect? GET /customers/1234?status=verified or GET /customers/1234/setVerified REST „method“
  • 21. #WISSENTEILEN SAFE / IDEMPOTENT Methods SAFE* keine Änderung an der Ressource IDEMPOTENT** einmalige Änderung an der Ressource-Repräsentation mehrfache Wiederholung führt immer zum selben Ergebnis * GET, HEAD, OPTIONS ** GET, HEAD, OPTIONS, PUT, DELETE
  • 23. #WISSENTEILEN // FILTERING: // List of paid orders (2015-12-20) // Common Style GET /orders?date=20151220&status=payed HTTP 1.1 REST „filter“
  • 24. #WISSENTEILEN // FILTERING: // Details of order 3 (product, date, ...) // Facebook Style GET /orders/3?fields=product,date,status HTTP/1.1 GET /orders/3?fields=item.product,date,status HTTP/1.1 // LinkedIn Style GET /orders/3:(product, date, status) HTTP/1.1 REST „filter“
  • 25. #WISSENTEILEN // FILTERING: // Details of order 3 // without date, status GET /orders/3?exclude=date,status HTTP/1.1 // predefined payload (compact = product, date, status) GET /orders/3?style=compact HTTP/1.1 REST „filter“ What is compact?
  • 26. #WISSENTEILEN // FILTERING: // Details of order 3 // using PREFER HEADER for response payload definition GET /orders/3 HTTP/1.1 Content-Type: application/json Prefer: return=compact-format HTTP 1.1 200 OK Content-Type: application/json; charset=utf-8 Preference-Applied: return=compact-format REST „filter“
  • 27. #WISSENTEILEN // SORTING: // orders sorted (date ↓ /item ↑) // SQL alike style GET /orders?sort=date+DESC,item+ASC HTTP/1.1 // Sort and asc/desc combination, ascending as default GET /orders?sort=date,item&desc=date HTTP/1.1 // use prefix „-“ for descending, ascending as default GET /orders?sort=-date,item HTTP/1.1 REST „sorting“
  • 28. #WISSENTEILEN // FILTERING & SORTING: // orders of „today“ sorted by ... // long version GET /orders?status=open &date_from=20170510&date_to=20170510 &fields=product,status,time&sort=-time,product // short and readable version GET /orders/open_orders_of_today GET /open_orders_of_today REST „filter&sort“
  • 29. #WISSENTEILEN // Pagination a.k.a. „Limiting“: // return page 4 of orders // Is page a query parameter? GET /orders?page=4 HTTP/1.1 // Or is page a „virtual“ resource? GET /orders/pages/4 HTTP/1.1 REST „pagination“ „4“? PREV? NEXT? FIRST? LAST?
  • 30. #WISSENTEILEN // Pagination a.k.a. „Limiting“: // return page 4 of orders // get “page 4“ and info about PREV/NEXT GET /orders?offset=10&limit=5 HTTP/1.1 // Response with success code and link header for // navigation purpose HTTP/1.1. 200 OK Link: <.../orders?offset=0&limit=5>; rel=„first“ <.../orders?offset=5&limit=5>; rel=„prev“, <.../orders?offset=15&limit=5>; rel=„next“, <.../orders?offset=40&limit=2>; rel=„last“ REST „pagination“
  • 31. #WISSENTEILEN // Pagination a.k.a. „Limiting“: // return page 4 of orders // get “page 4“ and info about PREV/NEXT GET /orders?page=4&limit=5 HTTP/1.1 // Response with success code and link header for // navigation purpose HTTP/1.1. 200 OK Link: <.../orders?page=1&limit=5>; rel=„first“ <.../orders?page=3&limit=5>; rel=„prev“, <.../orders?page=5&limit=5>; rel=„next“, <.../orders?page=8&limit=2>; rel=„last“ REST „pagination“
  • 32. #WISSENTEILEN // FULL TEXT SEARCH: // Fulltext search for coffee // Global style via virtual resource GET /searches?q=coffee HTTP/1.1 oder // Scoped style GET /orders/searches?q=coffee HTTP/1.1 GET /orders?q=coffee HTTP/1.1 REST „search“ „GET vs. POST „GET vs. POST
  • 33. #WISSENTEILEN // ADVANCED SEARCH: // Coffee WITH milk for 2€ // Query for ... GET /orders?type=coffee&ingredient=milk&price=2 REST „search“ BTW: AND or OR or AND/OR?
  • 34. #WISSENTEILEN // ADVANCED SEARCH: // Coffee WITH milk for LESS THAN 2€ // Query for ... GET /orders?query=type=coffee+ingredient=milk+price<=2 REST „search“ Build your own „Query Language“?
  • 35. #WISSENTEILEN // ADVANCED SEARCH: // Coffee WITH milk or LESS THAN 2€ // RQL query ... (must possibly be encoded!) GET /orders?query= and(eq(type,coffee), or(eq(ingredients,MILK),lt(price,2)) // RQL alternative query – FIQL (URI friendly) - ... GET /orders?query= type==coffee;(ingredients==MILK,price=lt=2) REST „search“
  • 36. Use Standards Standards promote efficiency, trust and safety https://www.din.de/en/about-standards/use-standards
  • 38. #WISSENTEILEN Always remember: „The Web is your Friend“ • das Web bietet tolle Möglichkeiten zur „Skalierung“ • RESTful Service nutzen das Web bzw. HTTP • Client (Web Browser, REST Client, ...) • Proxy Caches („man in the middle cache“) • Content Delivery Networks (CDNs) Caching
  • 39. #WISSENTEILEN // Caching in REST: // Expires-Header (HTTP 1.0) HTTP/1.1 200 Ok Content-Type: application/json Expires: Mon, 24 SEP 2018 12:00:01 GMT { "id": "1", "firstName": "Max", "lastName": "Mustermann", ... ... } REST „Cache“ „Hint, ok. Aber für wen eigentlich?“
  • 40. #WISSENTEILEN CACHING Cache-Control (HTTP 1.1) • deutlich genauere Cache-Steuerung als bei Expires Header • private, public • no-cache • no-store • no-transform • max-age, s-maxage
  • 41. #WISSENTEILEN // Caching in REST: // Cache-Control (HTTP 1.1) HTTP/1.1 200 Ok Content-Type: application/json Cache-Control: private, no-store, max-age=3600 { "id": "1", "firstName": "Max", "lastName": "Mustermann", ... } REST „Cache“ „Only client side caching. Valid for 3600 sec. Must not be stored on disc.“
  • 42. #WISSENTEILEN CACHING Revalidation & Conditional GET (HTTP 1.1) • Revalidation zur Prüfung, ob Cache-Daten wirklich invalide • Server sendet speziellen Header zur Prüfung zurück • Last-Modified • Etag
  • 43. #WISSENTEILEN // Caching in REST: // Revalidation & Conditional GET // Cache-Control + Last-Modified Header HTTP 1.1 HTTP/1.1 200 Ok Content-Type: application/json Cache-Control: max-age=3600 Last-Modified: Wed, 10 MAI 2017 12:00:01 GMT { "id": "1", ... } REST „Cache“
  • 44. #WISSENTEILEN // Caching in REST: // Revalidation & Conditional GET // Conditional GET after Timeout (max-age) GET /products/123 HTTP/1.1 If-Modified-Since: Wed, 10 MAI 2017 12:00:01 GMT REST „Cache“ Modified since? No, 304 (Not Modified). Yes, 200 (Ok) plus Data.
  • 45. #WISSENTEILEN // Caching in REST: // Revalidation & Conditional GET // Cache-Control + eTag Header HTTP 1.1 HTTP/1.1 200 Ok Content-Type: application/json Cache-Control: max-age=3600 eTag: "1234567890987654321" { "id": "1", ... } REST „Cache“
  • 46. #WISSENTEILEN // Caching in REST: // Revalidation & Condition GET // Conditional GET after Timeout (max-age) GET /products/123 HTTP/1.1 If-None-Match: "1234567890987654321" REST „Cache“ Modified since? No, 304 (Not Modified). Yes, 200 (Ok) plus Data.
  • 47. #WISSENTEILEN // Optimistic Locking // Conditional PUT // Conditional PUT PUT /customers/1234 HTTP/1.1 If-Match: "1234567890987654321" REST „Cache“ Modified in between? No, 200 (OK). Yes, 412 (Precondition Failed)
  • 48. #WISSENTEILEN // Optimistic Locking // Conditional PUT // PUT ohne Precondition PUT /customers/1234 HTTP/1.1 REST „Cache“ Force Optimistic Locking: 428 (Precondition Required)
  • 50. #WISSENTEILEN Headers HTTP Header Parameter • Meta Daten für Request / Response • Accept: ich komme mit Format xyz klar • Content-Type: ich sende dir Format xyz • Location-Header: genauere/mehr Info zu „mir“ unter ... • Link-Header: siehe auch unter ... • Authorization*-Header: Auth Tokens, Basic Auth ... • X-Custom-Header: ich habe da noch was für dich ... {?}
  • 51. #WISSENTEILEN REST... Status Codes (see also: http://www.restpatterns.org/HTTP_Status_Codes/)
  • 52. #WISSENTEILEN Pro Tipp: Use them! • 1xx: Hold on ... • 2xx: Here you go! • 3xx: Go away! • 4xx: You f#!?ed up! • 5xx: I f#!?ed up! (http://restlet.com/http-status-codes-map) Facebook „Always 200“ Anti-Pattern HTTP Status Codes (http://www.restpatterns.org/HTTP_Status_Codes)
  • 53. #WISSENTEILEN // HTTP Status Codes: // signal that new order was created // „Create new Resource“ of type order POST /customers HTTP/1.1 [various other headers] // Response with location header pointing to resource HTTP/1.1. 201 Created Location: http://…/customers/1234 REST „Codes“
  • 54. #WISSENTEILEN // HTTP Status Codes: // signal that some work is going on // Trigger some async workload POST /customers/ HTTP/1.1 [various other headers] // Response without payload, cause it‘s not yet calculated HTTP/1.1. 202 Accepted REST „Codes“
  • 55. #WISSENTEILEN // HTTP Status Codes: // signal that payload is empty // DELETE customer with id 1234 DELETE /customers/1234 HTTP/1.1 [various other headers] // Customer successfully deleted. No content by purpose HTTP/1.1. 204 No content HTTP/1.1. 205 Reset content REST „Codes“
  • 56. #WISSENTEILEN // HTTP Status Codes: // signal that payload is empty // Retrieve all verified customers GET /customers?status=verified HTTP/1.1 [various other headers] // There is no verified customer left. HTTP/1.1. 204 No content REST „Codes“
  • 57. #WISSENTEILEN // HTTP Status Codes: // signal that there is more payload // GET all orders on „page“ two GET /customers?page=4 HTTP/1.1 [various other headers] // Response with success code and links for navigation HTTP/1.1. 206 Partial content Link: <http://.../customers?page=1>; rel= „first“ <http://.../customers?page=3>; rel= „prev“, ... REST „Codes“
  • 58. #WISSENTEILEN // HTTP Status Codes: // signal that could not find order // Ask for customer with id 1234 GET /customers/1234 HTTP/1.1 [various other headers] // Could not find customer with id 1234 HTTP/1.1. 404 Not found REST „Codes“
  • 59. #WISSENTEILEN // HTTP Status Codes: // signal that there is a limit problem // Error Responses: Use them wisely HTTP/1.1 429 To many request HTTP/1.1 509 Bandwith limit exceeded REST „Codes“
  • 60. #WISSENTEILEN // HTTP Status Codes: // Rate limit exceeded (e.g. Twitter) HTTP/1.1 429 To many requests [various other headers] { "errors": [ { "code": 88, "message": "Rate limit exceeded" } ] } REST „Codes“
  • 61. #WISSENTEILEN // HTTP Status Codes: // Rate limit exceeded (e.g. Twitter) HTTP/1.1 200 Ok [various other headers] X-Rate-Limit-Limit: ... // rate limit ceiling X-Rate-Limit-Remaining: ... // for the next 15 minutes X-Rate-Limit-Reset: ... // in UTC epoch seconds REST „Codes“
  • 62. #WISSENTEILEN // HTTP Status Codes: // signal that the payload is invalid // Change customer with id 1234 PUT /customers/1234 HTTP/1.1 [various other headers] // Some content is invald HTTP/1.1. 400 Bad Request REST „Codes“
  • 63. #WISSENTEILEN // HTTP Status Codes: // Bad request // - Validation error with problem+json HTTP/1.1 400 Bad request Content-Type: application/problem+json [various other headers] { "type": "/problems/validation-error", "title": "Your request parameters didn't validate.", "status": 400, "detail": "...", "instance": "orders/1234" } REST „Codes“
  • 64. #WISSENTEILEN // HTTP Status Codes: // Bad request // - Validation error with problem+json HTTP/1.1 400 Bad request Content-Type: application/problem+json [various other headers] { "type": "/problems/validation-error", "title": "Your request parameters didn't validate.", ... "invalid-params": [ { "path": "firstName", "message": "firstName is mandatory" } ] } Custom Extension for Problem JSON REST „Codes“
  • 65. #WISSENTEILEN Manchmal kommt es anders, als man denk • Code for Code: Status Code & Application Level Code • Message for People: Für Logs, Ausgaben, ... • Payload and Format: genormte Error-Payload Format HTTP Status Codes
  • 66. #WISSENTEILEN // „Create new customer“. POST /customers Content-Type: application/json // Is this allowed? Guess not. Is it? POST /customers/1234 Content-Type: application/json // „Change customer“. I‘am sure! But wait ...“ PUT /customers/1234 Content-Type: application/json // „Change customer“, too? Isn‘t it? PATCH /customers/1234 Content-Type: application/json REST „method“
  • 67. #WISSENTEILEN // HTTP Status Codes: // Which patch should be used HTTP/1.1 415 Unsupported Media Type Content-Type: application/problem+json [various other headers] { "type": "/problems/unsupported-media-type", "detail": "supported media types are application/merge-patch+json or application/json-patch+json", } REST „Payload“
  • 68. #WISSENTEILEN // HTTP PATCH: // json/merge-patch+json POST /customers Content-Type: application/json [various other headers] { "customerNumber": "1234", "name": { "firstName": "Max", "lastName": "Mustermann" }, "email": "max.mustermann@beispiel.de" } REST „Payload“
  • 69. #WISSENTEILEN // HTTP PATCH: // json/merge-patch+json // leave customer number and first name unchanged // change last name, remove email PATCH /customers/1234 Content-Type: application/merge-patch+json [various other headers] { "name": { "lastName": "Muster" }, "email": null } REST „Payload“
  • 70. #WISSENTEILEN // HTTP PATCH: // json/json-patch+json PATCH /customers/ Content-Type: application/json-patch+json [various other headers] [ { "op": "remove", "path": "/1234/email" }, { "op": "replace", "path": "/1234/name/last", "value": "Muster" }, { "op": "add", "path": "/1234/name/additional", "value": "Thomas" }, { "op": "move", "from": "/1234", "path": "/1235" }, ] REST „Payload“
  • 71. #WISSENTEILEN „Leonard Richardson proposed a classification for services on the Web. Leonard’s model promotes three levels of service maturity based on a service’s support for URIs, HTTP, and hypermedia!“ (Quelle: „REST in Practice“)
  • 74. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL Level 0 • a.k.a. „Swamp of PoX“: • HTTP als Transportsystem • „RPC“-Style • eine URI • eine HTTP Methode (meist POST) • Parameter und Rückgabe als Payload (XML/JSON/TEXT)
  • 76. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL Level 1 • Aufbrechen des monolithischen Endpoints aus Level 0 in unterschiedliche Ressourcen (a.k.a. Nomen), die gezielt angesprochen werden können.
  • 77. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL Level 1 • a.k.a. „Resources“ • Individuelle Ressourcen statt Service Endpoint • mehrere URIs • ein oder zwei HTTP Methode (meist POST/GET) • Parameter als Query-Parameter oder Payload • Rückgabe als Payload (XML/JSON/TEXT)
  • 79. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL Level 2 • Einführen verschiedener „Verben“, um gleiche Situationen mit den selben Mechanismen behandeln zu können und so unnötige Varianten zu vermeiden.
  • 80. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL Level 2 • a.k.a. „Verbs“ • „passende“ HTTP Methoden statt nur POST & GET • mehrere URIs • mehrere HTTP Methoden • Rückgabe als Payload & Status Codes
  • 82. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL Level 3 • Einführen von „Auffindbarkeit“, um so einen Mechanismus anzubieten, der das Protokoll selbsterklärend(er) macht.
  • 83. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL Level 3 • a.k.a. „Hypermedia“ • selbsterklärendes System • nur eine Einstiegs-URI bekannt • keine weiteren festen URIs • Rückgabe als Liste von neuen „Möglichkeiten“
  • 84. Make your API explorable
  • 85. #WISSENTEILEN „If the engine of application state (and hence the API) is not driven by hypertext, then it cannot be RESTful and cannot be a REST API. Period. Is there some broken manual somewhere that needs to be fixed?“ Roy Fielding
  • 86. #WISSENTEILEN „A REST API should be entered with no prior knowledge beyond the initial URI ... From that point on, all application state transitions must be driven by the client selection of server-provides choices ...“ Roy Fielding
  • 87. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL /orders/... POST /orders { order payload } http/1.1 201 Created Location: ... Link: cancel operation update operation delete operation pay operation C O N S U M E R O R D E R S
  • 88. Titel der Präsentation | Name des Sprechers RICHARTSON MATURITY MODEL /orders/... /payments/... http/1.1 201 Created Location: ... Link: http://<status operation> http://<update operation> http://<delete operation> http://<pay operation> GET PUT DELETE POST O R D E R P A Y
  • 89. #WISSENTEILEN REST „Hateoas“ v1 // Richardson Maturity Model: // Hypermedia as the engine // of application state POST /orders/ HTTP/1.1 { ... payload of order to create ... } HTTP/1.1. 201 Created Location: http://restbucks.com/api/orders/1234 Link: <.../orders/1234>; rel=„cancel“ <.../orders/1234>; rel=„update“, <.../orders/1234>; rel=„delete“, <.../payment/1234>; rel=„pay“
  • 90. #WISSENTEILEN // Aber wie bilde ich Relationen ab? // the „naive“ way // all customers { [ { "id":"001", "for":"arne", ..., "addresses":[ ...] }, { "id":"002", "for":"lars", ..., "addresses":[ ...] }, ... ] } REST „relation“
  • 91. #WISSENTEILEN // Aber wie bilde ich Relationen ab? // the „naive“ way // all customers { [ { "id":"001", "for":"arne", ..., "addresses":[ ...] }, { "id":"002", "for":"lars", ..., "addresses":[ ...] }, ... ] } REST „relation“ Benötige ich die Info hier wirklich?
  • 92. #WISSENTEILEN // Aber wie bilde ich Relationen ab? // the „linked“ way // all customers { [ { "id":"001", "for":"arne", ..., "address_refs":[...]}, { "id":"002", "for":"lars", ..., "address_refs":[...] }, ... ] } REST „relation“ https://..../customers/002/addresses/1 https://..../customers/002/addresses/2 Benötige ich weitere Infos?
  • 93. #WISSENTEILEN // Aber wie bilde ich Relationen ab? // the „linked“ way // all customers { [ { "id":"001", "for":"lars", ..., "addresses_refs":[...], "addresses_count" : 2 ] } REST „relation“
  • 94. #WISSENTEILEN // Aber wie bilde ich Relationen ab? // the „linked“ way // all customers { [ { "id":"001", "for":"lars", "for_ref ": "http://.../customers/12", ..., "addresses_refs":[...], "addresses_count" : 2 ]} REST „relation“
  • 95. #WISSENTEILEN // Aber wie bilde ich Relationen ab? // the „linked“ way // all customers { [ { "id":"001", "for":"arne", ..., "address":[ { "href": "http://.../customers/001/addresses/1" } ]}, ... ] } REST „relation“ Welche Syntax hilft dem Consumer?
  • 96. #WISSENTEILEN Content-Type: application/hal+json { "_embedded": { "customers": [{ "_links": { "self": { "href": "/customers/001“ }, … }, "name": "Arne Limburg", … }, …]}, "_links": { "next": … "find": {"href": "/customers{?tags}", "templated": true} }, … } REST „relation“
  • 99. #WISSENTEILEN DOCUMENTATION OpenAPI Specification (OAS) Design mit Swagger Editor Build mit Swagger Codegen Dokumentiere mit Swagger-UI
  • 100. #WISSENTEILEN // openapi.json // JSON-Schema / OpenAPI Example "post" : { "parameters" : [ { "in" : "body", "name" : "body", "description" : "new customer", "required" : true, "schema" : { "$ref" : "#/definitions/Customer" } } ] } REST „OpenAPI“
  • 101. #WISSENTEILEN // openapi.json (JSON Schema) "definitions" : { "CustomerResourceType" : { "type" : "object", "required" : [ "firstName", "lastName”, … ], "properties" : { "firstName" : { "type" : "string", "minLength" : 1, "maxLength" : 30, "pattern" : "..." } } REST „OpenAPI“
  • 103. MICROSERVICES ARCHITEKTUR Address Validation Service Delivery Service Customer Service Billing Service
  • 104. Tolerant Reader Pattern Tolerant gegenüber unbekannten Feldern Umgang mit x-extensible-enum http://zalando.github.io/restful-api-guidelines
  • 106. Tolerant Reader Pattern Tolerant gegenüber unbekannten Feldern Umgang mit x-extensible-enum http://zalando.github.io/restful-api-guidelines Tolerant gegenüber unbekannten Statuscodes HTTP Status 301 folgen
  • 107. TOLERANT READER PATTERN http://www.example.com/addresses/42 àLiefert Addresse { street: { "name": "Poststraße", "number": "1", }, "city": "26122 Oldenburg" }
  • 108. TOLERANT READER PATTERN http://www.example.com/addresses/42 Attribut hinzufügen { street: { "name": "Poststraße", "number": "1", "additionalAdressLine": "2. Obergeschoss" }, "city": "26122 Oldenburg" }
  • 109. TOLERANT READER PATTERN Server schickt { street: { "name": "Poststraße", "number": "1", "additionalAdressLine": "2. Obergeschoss" }... } http://www.example.com/addresses/42 Client erwartet { street: { "name": "Poststraße", "number": "1", }... }
  • 110. TOLERANT READER PATTERN http://www.example.com/addresses/42 Attribut-Umbenennung { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", }, "city": "26122 Oldenburg" }
  • 111. TOLERANT READER PATTERN http://www.example.com/addresses/42 àAbwärtskompatible Änderungen: Umbenennen durch Kopieren { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", }, "city": "26122 Oldenburg" }
  • 112. Und was ist, wenn der Client kein Tolerant Reader ist?
  • 113. PROJEKTIONEN // Client kann entscheiden, welche Felder er bekommen möchte // Facebook Style GET /addresses/3?fields=street,city GET /addresses/3?fields=street.name,street.number,city // LinkedIn Style GET /addresses/3?fields=street:(name,number),city
  • 114. OK, so soll sich der Client verhalten. Aber was ist mit dem Server?
  • 115. Photo by Irene Fertik, USC News Service. Copyright 1994, USC. „Be conservative in what you do, Be liberal in what you accept from others“ RFC 793, Robustness Principal (John Postel)
  • 116. Es darf nichts entfernt werden Keine Veränderung von Verarbeitungsregel Optionales darf nie Required werden http://zalando.github.io/restful-api-guidelines Alles was hinzugefügt wird, muss optional sein
  • 117. MAGNANIMOUS WRITER PATTERN Server schickt { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1“ }... } http://www.example.com/addresses/42 Client erwartet { street: { "name": "Poststraße", "number": "1", }... } http://tenderware.blogspot.de/2011/05/magnanimous-writer.html
  • 118. MAGNANIMOUS WRITER PATTERN Server schickt { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1“ }... } http://www.example.com/addresses/42 Client erwartet { street: { "streetName": "Poststraße", "houseNumber": "1", }... } http://tenderware.blogspot.de/2011/05/magnanimous-writer.html
  • 119. MAGNANIMOUS WRITER PATTERN Server erwartet PUT http://www.example.com/addresses/42 Client schickt { street: { "name": "Poststraße", "number": "1", }... } http://tenderware.blogspot.de/2011/05/magnanimous-writer.html
  • 120. MAGNANIMOUS WRITER PATTERN PUT http://www.example.com/addresses/42 Client schickt { street: { "name": "Poststraße", "number": "1", }... } http://tenderware.blogspot.de/2011/05/magnanimous-writer.html Server erwartet { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1“ }... } oder oder
  • 121. MAGNANIMOUS WRITER PATTERN PUT http://www.example.com/addresses/42 Client schickt { street: { "streetName": "Poststraße", "houseNumber": "1", }... } http://tenderware.blogspot.de/2011/05/magnanimous-writer.html Server erwartet { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1“ }... } oder oder
  • 122. MERGE PATCH UND NULL VALUES PATCH /addresses/42 HTTP/1.1 Content-Type: application/merge-patch+json Client schickt { street: { "name": null, }... } https://tools.ietf.org/html/rfc7396
  • 123. ABWÄRTSKOMPATIBILITÄT http://www.example.com/addresses/42 àAbwärtskompatible Änderungen: Umbenennen durch Kopieren { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", }, "city": "26122 Oldenburg" } Geht da noch mehr?
  • 124. ABWÄRTSKOMPATIBILITÄT http://www.example.com/addresses/42 àZusammenführen und Teilen von Attributen { street: { ... "streetName": "Poststraße", "houseNumber": "1", "addressLine1": "Poststraße 1", } ... }
  • 125. ABWÄRTSKOMPATIBILITÄT http://www.example.com/addresses/42 àHerausforderungen: Zusammenführen von Attributen { street: { ... "streetName": "Poststraße", "houseNumber": "1", "addressLine1": "Poststraße 1", } ... }
  • 126. ABWÄRTSKOMPATIBILITÄT http://www.example.com/addresses/42 àHerausforderungen: Teilen von Attributen { street: { ... "addressLine1": "Poststraße 1", } "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg" }
  • 127. ABWÄRTSKOMPATIBILITÄT http://www.example.com/addresses/42 àHerausforderungen: Ebene von Attributen ändern { street: { ... "addressLine1": "Poststraße 1" } "addressLine1": "Poststraße 1", ... }
  • 128. ABWÄRTSKOMPATIBILITÄT http://www.example.com/addresses/42 àHerausforderungen: Ebene von Attributen ändern { ... "zipCode": "26122", "cityName": "Oldenburg", "location": { "zipCode": "26122", "cityName": "Oldenburg" } }
  • 129. ABWÄRTSKOMPATIBILITÄT http://www.example.com/addresses/42 àHerausforderungen: Ebene von Attributen ändern { ... "zipCode": "26122", "cityName": "Oldenburg", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } Bei jeder Modelländerung muss eine Migrationsstrategie einbezogen werden!
  • 130. ABWÄRTSKOMPATIBILITÄT { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" } "addressLine1": "Poststraße 1", "addressLine2": "", "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } http://www.example.com/v1/addresses/42 àBisher nur abwärtskompatible Änderungen
  • 131. ABWÄRTSKOMPATIBILITÄT { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" } "addressLine1": "Poststraße 1", "addressLine2": "", "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } http://www.example.com/v1/addresses/42 àViele Attribute deprecated
  • 132. Wie kann ich Attribute entfernen?
  • 133. Don‘t ever break your Client
  • 134. Incompatible Change vs. Breaking Change http://zalando.github.io/restful-api-guidelines
  • 139. CONSUMER-DRIVEN CONTRACT TEST Consumer Contract Consumer Provider Consumer Tests Provider Tests
  • 140. MICROSERVICES ARCHITEKTUR Address Validation Service Delivery Service Customer Service Billing Service
  • 141. PIPELINE TO DEPLOY TO STAGE Execute Own Provider Tests Generate Consumer Contract Execute Depending Provider Tests Deploy to Stage
  • 142. PIPELINE TO DEPLOY TO STAGE Execute Own Provider Tests Generate Consumer Contract Execute Depending Provider Tests Deploy to Stage Achtung: Abwärtskompatibilität ist trotzdem notwendig!
  • 143. BREAKING CHANGE VOM PROVIDER Execute Own Provider Tests Generate Consumer Contract Execute Depending Provider Tests Deploy to Stage
  • 144. BREAKING CHANGE VOM CONSUMER Execute Own Provider Tests Generate Consumer Contract Execute Depending Provider Tests Deploy to Stage
  • 145. Und wenn ich meine Consumer nicht kenne?
  • 146. VERSIONSSPRUNG { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" } "addressLine1": "Poststraße 1", "addressLine2": "", "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } http://www.example.com/v1/addresses/42 àBisher nur abwärtskompatible Änderungen
  • 147. INKOMPATIBLE ÄNDERUNG http://www.example.com/v2/addresses/42 àVersionssprung { "addressLine1": "Poststraße 1", "addressLine2": "", "location": { "zipCode": "26122", "cityName": "Oldenburg" } }
  • 149. Version 2.0 ist nur inkompatibel zu 1.0! Version 2.0 ist identisch zu 1.x! Das erleichtert das Mapping zwischen den Versionen!
  • 150. Ein solcher Versionssprung ist nicht anforderungsgetrieben, sondern viel besser und langfristiger planbar
  • 151. Wenn eine neue Version nicht auf die alte abbildbar ist, ist es keine neue Version, sondern eine neue Schnittstelle!
  • 152. • Über URL-Pfad /v2/addresses • Über Query-Parameter /addresses?version=v2 • Über Version-Header X-Api-Version: v2 • Über Version-Attribut am Media-Type application/xml;version=v2 • Über Media-Type application/vnd.de.openknowledge+v2+json ERMITTELN DER VERSION
  • 153. ABWÄRTSKOMPATIBILITÄT Schnittstelle Schnittstelle { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" } "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg", "addressLine1": "Poststraße 1", "addressLine2": "", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } { "addressLine1": "Poststraße 1", "addressLine2": "“, "location": { "zipCode": "26122", "cityName": "Oldenburg" } } V1 V2-SNAPSHOT
  • 154. ABWÄRTSKOMPATIBILITÄT Schnittstelle Schnittstelle { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" }, "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg", "addressLine1": "Poststraße 1", "addressLine2": "“, "location": { "zipCode": "26122", "cityName": "Oldenburg" } } { "addressLine1": "Poststraße 1", "addressLine2": "", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } V1 V2-SNAPSHOT
  • 155. AUTOMATISIERTES MAPPING Schnittstelle Schnittstelle { "street": { "name": "Poststraße", "number": "1", }, "city": "26122 Oldenburg" } { "street": { "name": "Poststraße", "number": "1" }, "city": "26122 Oldenburg" } V1 V2-SNAPSHOT
  • 156. WEITERENTWICKLUNG Schnittstelle Schnittstelle { "street": { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", }, "city": "26122 Oldenburg" } { "street": { "streetName": "Poststraße", "houseNumber": "1" }, "city": "26122 Oldenburg" } V1 V2-SNAPSHOT
  • 157. WEITERENTWICKLUNG Schnittstelle Schnittstelle { "street": { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" }, "city": "26122 Oldenburg" } { "street": { "addressLine1": "Post… 1", "addressLine2": "" }, "city": "26122 Oldenburg" } V1 V2-SNAPSHOT
  • 158. WEITERENTWICKLUNG Schnittstelle Schnittstelle { "street": { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" }, "addressLine1": "Poststraße 1", "addressLine2": "", "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg", } { "addressLine1": "Poststraße 1", "addressLine2": "", "zipCode": "26122", "cityName": "Oldenburg" } V1 V2-SNAPSHOT
  • 159. WEITERENTWICKLUNG Schnittstelle Schnittstelle { "street": { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" }, "addressLine1": "Poststraße 1", "addressLine2": "", "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } { "addressLine1": "Poststraße 1", "addressLine2": "", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } V1 V2-SNAPSHOT
  • 160. ABWÄRTSKOMPATIBILITÄT Schnittstelle Schnittstelle { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" }, "city": "26122 Oldenburg", "zipCode": "26122", "cityName": "Oldenburg", "addressLine1": "Poststraße 1", "addressLine2": "“, "location": { "zipCode": "26122", "cityName": "Oldenburg" } } { "addressLine1": "Poststraße 1", "addressLine2": "", "location": { "zipCode": "26122", "cityName": "Oldenburg" }, "city": { "zipCode": "26122", "cityName": "Oldenburg" } } V1 V2-SNAPSHOT
  • 161. ABWÄRTSKOMPATIBILITÄT Schnittstelle Schnittstelle { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" } ... } { "addressLine1": "Poststraße 1", "addressLine2": "", "location": { "zipCode": "26122", "cityName": "Oldenburg" } } V1 V3-SNAPSHOT Schnittstelle { "addressLine1": "Poststraße 1", "addressLine2": "“, "location": { "zipCode": "26122", "cityName": "Oldenburg" } } V2
  • 162. ABWÄRTSKOMPATIBILITÄT Schnittstelle Schnittstelle { street: { "name": "Poststraße", "streetName": "Poststraße", "number": "1", "houseNumber": "1", "addressLine1": "Post... 1", "addressLine2": "" } ... } { "addressLine1": "Poststraße 1", "addressLine2": "", "city": { "zipCode": "26122", "cityName": "Oldenburg" } } V1 V3-SNAPSHOT Schnittstelle { "addressLine1": "Poststraße 1", "addressLine2": "“, "location": { "zipCode": "26122", "cityName": "Oldenburg" }, "city": { "zipCode": "26122", "cityName": "Oldenburg" }} V2
  • 163. KONTAKT Titel der Präsentation | Name des Sprechers ARNE LIMBURG, ENTERPRISE ARCHITECT arne.limburg@openknowledge.de +49 (0)441 40820 OFFENKUNDIGGUT