pragmatic rest aka praxisnahes schnittstellendesign

Post on 22-Jan-2018

141 Views

Category:

Software

5 Downloads

Preview:

Click to see full reader

TRANSCRIPT

#WISSENTEILEN

What would MacGywer do?

Pragmatic REST

Lars Röwekamp | open knowledge

@mobileLarson@_openKnowledge

#wissenteilen

#WISSENTEILEN

RESTfuleverywhere

#WISSENTEILEN

SOAPDemoPOST /InStock HTTP/1.1

Host: www.demo.orgContent-Type: application/soap+xml; Content-Length: 348

<?xml version="1.0" encoding="utf-8"?><soap:Envelope

xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header></soap:Header><soap:Body>

<m:GetStockPrice xmlns:m="http://www.demo.org/stock"><m:StockName>IBM</m:StockName>

</m:GetStockPrice></soap:Body>

</soap:Envelope>

#WISSENTEILEN

XML-RPCDemoPOST /InStock HTTP/1.1

Host: www.demo.orgContent-Type: application/xml; Content-Length: 245

<?xml version="1.0" encoding="utf-8"?><getStockPriceRequest

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation=“storckItemRequest.xsd"><stockName>IBM</stockName>

</getStockPriceRequest>

#WISSENTEILEN

GET /stocks/ibm HTTP/1.1Host: www.demo.orgContent-Length: 0

RESTDemo

#WISSENTEILEN

Warum REST?

Keep it stupid simple a.k.a. KISS

• REpresentational State Transfer

• Identifikation von Ressourcen durch URL• Manipulation von Ressourcen durch Representation• Selbstbeschreibende Messages• Hypermedia

/customers/123

JSON/XML

GET, POST, PUT, DELETEMedia Types, CachabilityReferences

{?}

#WISSENTEILEN

Warum PRAGMATIC REST?

„Yo man! But it is

not RESTful, if ...“

{ }…{…}{?}

(RESTafarian, by Mike Schinkel)

#WISSENTEILEN

„But is thispragmatic?“

„Pragmatic? Are you

kidding? ItsCORRECT!“

Warum PRAGMATIC REST?…{?}

#WISSENTEILEN

„Das* API ist das UI des Entwicklers.“

(*wer möchte darf auch “die API“ sagen)

#WISSENTEILEN

„So what? Itspragmatic andworks for me

and myconsumers!“

Warum PRAGMATIC REST?{?}

#WISSENTEILEN

RESTbucks... ordering Coffee the RESTful way

#WISSENTEILEN

„Order 123 for‚Larissa‘.“

„And here‘s thereceipt.“

„Coffee, latte, large, to-go, semi, double shot, please.“

„Here‘s 5$.“

„What‘s thestatus of ‚123‘?“„Still prepering.“

„Now its ready.“

REST by Example

#WISSENTEILEN

// order coffeePOST /orders{ ... initial order data ... }

// check order statusGET /orders/1234

// change orderPUT /orders/1234{ ... changes ... }

// cancel orderDELETE /orders/1234

RESTBucks„crud“

given id?

filter, query, sorting?

PUT? Or PATCH?

Security?

Versionioning?

Error Handling?

Content Type?

#WISSENTEILEN

REST... the simple Stuff

#WISSENTEILEN

• „We only need two URLs“ • „Verbs are bad, nouns are good“• „Plurals are even better“

• „The web is your friend“

• „There is always a root (for associations)“• „There is always a parameter (for complex variations)“• „There is always a method (for an operation)“

Golden Rules of REST

#WISSENTEILEN

// Retrieve single order with id 1234GET /orders/1234

// Retrieve all ingredients of order 1234GET /orders/1234/ingredients

// Retrieve ingriedient 789 (milk) of order 1234?GET /orders/1234/ingredients/789

// Or even better: What kind of milk is in order 1234?GET /orders/1234/ingredients/milk

REST„root“

#WISSENTEILEN

// Path parameter for identifierGET /orders/1234

// Query parameter for queriesGET /orders/?status=ready

// Header parameter for platformGET /orders/1234Accept-Language: de-DE

REST„param“

#WISSENTEILEN

// „Create order“, isn‘t it?POST /orders

// Is this allowed? Guess not. Or ...? POST /orders/1234

// „Change order“. I‘am sure!PUT /orders/1234

// „Change order“, too? Isn‘t it?PATCH /orders/1234

REST„method“

#WISSENTEILEN

POST vs. PUT vs. PATCH

POSTerzeugt 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 order. Returns ID 1234POST /orders{ ... payload for 1234 ... }

// Hmmm, updates order 1234? Creates new order? POST /orders{ ... payload for 1234 ... }

REST„method“

#WISSENTEILEN

// Changes order with ID 1234PUT /orders/1234{ ... changes for 1234 ... }

// Hmmm, will be irgnored? PUT /orders/1234{ ... changes for 1234, e.g. set amount of milk ... }

// Or additional changes? PUT /orders/1234{ ... changes for 1234, e.g. add more milk ... }

REST„method“

#WISSENTEILEN

// Changes order with ID 1234PUT /orders/1234{ ... changes for 1234 ... }

// Same as PUT? Mayby not! PATCH /orders/1234{ ... changes for 1234 ... }

// Same as PUT? Is this what i expect?GET /orders/1234?milk=soja orGET /orders/1234/addSojaMilk

REST„method“

#WISSENTEILEN

SAFE / IDEMPOTENT Methods

SAFE*keine Änderung an der Ressource

IDEMPOTENT**einmalige Änderung an der Ressource-Representationmehrfache Wiederholung führt immer zum selben Ergebnis

* GET, HEAD, OPTIONS** GET, HEAD, OPTIONS, PUT, DELETE

#WISSENTEILEN

REST... Filter, Sorting & Pagination

#WISSENTEILEN

Filter, Sorting, Pagination,

Was ist eigentlich mit ...

• komplex(er)en Anfragen?• eingeschränkten Rückgabeobjekten?• (alternativen) Sortierungen?• alternativen Rückgabeformat?

Und wie sieht es mit „allgemeiner“ Suche aus?

#WISSENTEILEN

// FILTERING: // List of paid orders (2015-12-20)

// Common StyleGET /orders?date=20151220&status=payed HTTP 1.1

REST„filter“

#WISSENTEILEN

// FILTERING: // Details of order 3 (product, date, ...)

// Facebook StyleGET /orders/3?fields=product,date,status HTTP/1.1

GET /orders/3?fields=item.product,date,status HTTP/1.1

// LinkedIn StyleGET /orders/3:(product, date, status) HTTP/1.1

REST„filter“

#WISSENTEILEN

// FILTERING: // Details of order 3

// without date, statusGET /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 definitionGET /orders/3 HTTP/1.1Content-Type: application/jsonPrefer: return=compact-format

HTTP 1.1 200 OKContent-Type: application/json; charset=utf-8Preference-Applied: return=compact-format

REST„filter“

#WISSENTEILEN

// SORTING: // orders sorted (date ↓ /item ↑)

// SQL alike styleGET /orders?sort=date+DESC,item+ASC HTTP/1.1

// Sort and asc/desc combination, ascending as defaultGET /orders?sort=date,item&desc=date HTTP/1.1

// use prefix „-“ for descending, ascending as defaultGET /orders?sort=-date,item HTTP/1.1

REST„sorting“

#WISSENTEILEN

// FILTERING & SORTING: // orders of „today“ sorted by ...

// long versionGET /orders?status=open

&date_from=20170510&date_to=20170510&fields=product,status,time&sort=-time,product

// short and readable versionGET /orders/open_orders_of_todayGET /open_orders_of_today

REST„filter&sort“

#WISSENTEILEN

// Pagination: // 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: // return page 4 of orders

// get “page 4“ and info about PREV/NEXT GET /orders?offset=20&limit=5 HTTP/1.1

// Response with success code and link header for// navigation purposeHTTP/1.1. 200 OKLink: <.../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: // 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 purposeHTTP/1.1. 200 OKLink: <.../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 resourceGET /searches?q=coffee HTTP/1.1

// Scoped styleGET /orders/searches?q=coffee HTTP/1.1GET /orders?q=coffee HTTP/1.1

REST„search“

#WISSENTEILEN

// ADVANCED SEARCH: // Coffee WITH milk for 2€

// Query for ... GET /orders?type=coffee&ingredient=milk&price=2

REST„search“

BTW: AND or OR orAND/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

Filter, Sorting, Pagination

Resource Query Language (RQL*)

• Object-Style Query Language• FIQL Superset (erweiterbar)

• Spezifikation & JS Parser (Client & Server)• JS Array, SQL, MongoDB, Elastic Search• Java Parser + JPA Criteria Builder

(* https://github.com/persvr/rql)

#WISSENTEILEN

// ADVANCED SEARCH: // Coffee WITH milk for 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“

#WISSENTEILEN

// SUPER ADVANCED SEARCH: // All stores with// - employees older than 20 years// - who have soled more than 1000 coffee/day// - even if it was damnd hot outside (> 30 degree)

#WTHREST

„search“

#WISSENTEILEN

Filter, Sorting, Pagination

Super Advanced Queries

• teure Client-Server Roundtrips (n+1 oder mehr)• virtuelle Ressourcen (statisch? dynamisch?)

• GraphQLals Alternative unbedingt anschauen!

(* https://github.com/persvr/rql)

#WISSENTEILEN

Filter, Sorting, Pagination

GraphQL

• beliebige Abfragen via Objekt-Graph auf dem man navigiert• liefern des Abfrage-Results in einem einzigen Round-Trip

#WISSENTEILEN

// SUPER ADVANCED SEARCH: // All stores and their sales// - employees of age 20// - have sold at least 1000 coffee/day// - even if it was damnd hot (> 30 degree){

stores {namesales(unit: EURO) employees(age:20, soldCoffee:1000) {

...}

}}

REST„graphQL“

#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

#WISSENTEILEN

// HTTP Status Codes: // signal that new order was created

// „Create new Resource“ of type orderPOST /orders HTTP/1.1[various other headers]

// Response with location header pointing to resourceHTTP/1.1. 201 CreatedLocation: http//restbucks.com/api/orders/1234

REST„Codes“

#WISSENTEILEN

// HTTP Status Codes: // signal that some work is going on

// Trigger some async workloadPOST /orders/... HTTP/1.1[various other headers]

// Response without payload, cause it‘s not yet calculatedHTTP/1.1. 202 Accepted

REST„Codes“

#WISSENTEILEN

// HTTP Status Codes: // signal that payload is empty

// DELETE order with id 1234DELETE /orders/1234 HTTP/1.1[various other headers]

// Order successfully deleted. No content by purposeHTTP/1.1. 204 No contentHTTP/1.1. 205 Reset content

REST„Codes“

#WISSENTEILEN

// HTTP Status Codes: // signal that payload is empty

// Retrieve all open ordersGET /orders?status=open HTTP/1.1[various other headers]

// There is no open order left. HTTP/1.1. 204 No content

REST„Codes“

#WISSENTEILEN

// HTTP Status Codes: // signal that there is more payload

// GET all orders on „page“ twoGET /orders?page=4 HTTP/1.1[various other headers]

// Response with success code and links for navigationHTTP/1.1. 206 Partial contentLink: <http://.../orders?page=1>; rel= „first“

<http://.../orders?page=3>; rel= „prev“, ...

REST„Codes“

#WISSENTEILEN

// HTTP Status Codes: // signal that payload is empty

// Ask for order with id 1234GET /orders/1234 HTTP/1.1[various other headers]

// Could not find order with id 1234 HTTP/1.1. 204 No content

REST„Codes“

#WISSENTEILEN

// HTTP Status Codes: // signal that payload is empty

// Ask for order with id 1234GET /orders/1234 HTTP/1.1[various other headers]

// Could not find order with id 1234 HTTP/1.1. 404 Not foundHTTP/1.1. 410 Gone

REST„Codes“

#WISSENTEILEN

Manchmal kommt es anders, als man denk

• Code for Code: Status Code & Appliction Level Code• Message for People: Für Logs, Ausgaben, ...• Payload and Format: genormte Error-Payload Format

• Kein Stacktrace• Exception Mapper als Provider auf äußerster Ebene

HTTP Status Codes

#WISSENTEILEN

// HTTP Status Codes: // signal that there is a problem

// Error Responses: Use them wiselyHTTP/1.1 400 Bad Request (unknown/generic status)HTTP/1.1 401 Unauthorized (btw: means unauthenticated)HTTP/1.1 403 Forbidden (btw: means unauthorized)HTTP/1.1 404 Not Found (resource could not be found)HTTP/1.1 405 Method not … (POST, GET, ...)HTTP/1.1 409 Conflict (fixable conflict, e.g. version)HTTP/1.1 410 Gone (update cache)HTTP/1.1 412 Precondition …(If-* header not matching) HTTP/1.1 418 I‘am a teapot (Don‘t ask me for COFFEE!)

REST„Codes“

#WISSENTEILEN

// HTTP Status Codes: // JAX-RS Exception Handler

@Providerpublic class MyAppExceptionHandler implements

ExceptionMapper<MyAppException> {@Overridepublic Response toResponse(MyAppException exception) {

return Response.status(Status.BAD_REQUEST).entity(new ExceptionEntity(exception)).build();

}}

REST„Codes“

#WISSENTEILEN

// HTTP Status Codes: // signal that there is a problem

// Error Responses: Use them wiselyHTTP/1.1 429 To many requestHTTP/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 ceilingX-Rate-Limit-Remaining: ... // for the next 15 minutesX-Rate-Limit-Reset: ... // in UTC epoch seconds

REST„Codes“

#WISSENTEILEN

REST... 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 OkContent-Type: application/jsonExpires: Tue, 20 MAI 2017 12:00 GMT

{"id": "espresso", "displayName": "Espresso", "price": 3.20,...

}

REST„Cache“

„Hint, ok. Aber für wen eigentlich?“

#WISSENTEILEN

// Caching in REST: // Chache-Control (HTTP 1.1)

HTTP/1.1 200 OkContent-Type: application/jsonCache-Control: private, no-store, max-age=3600

{"id": "espresso", "displayName": "Espresso", "price": 3.20,...

}

REST„Cache“

„Only client sidecaching. Valid for

3600 sec. Must not be stored on disc.“

#WISSENTEILEN

// Caching in REST: // Revalidation & Condition GET

// Cache-Control + Last-Modified Header HTTP 1.1HTTP/1.1 200 OkContent-Type: application/jsonCache-Control: max-age=3600Last-Modified: Wed, 10 MAI 2017 12:00 GMT

{"id": "espresso", ...

}

REST„Cache“

#WISSENTEILEN

// Caching in REST: // Revalidation & Condition GET

// Conditional GET after Timeout (max-age)GET /products/123 HTTP/1.1If-Modified-Since: Wed, 10 MAI 2017 12:00 GMT

REST„Cache“

Modified since? No, 304 (Not Modified). Yes, 200 (Ok) plus

Data.

#WISSENTEILEN

// Caching in REST: // Revalidation & Condition GET

// Cache-Control + eTag Header HTTP 1.1HTTP/1.1 200 OkContent-Type: application/jsonCache-Control: max-age=3600eTag: "1234567890987654321"

{"id": "espresso", ...

}

REST„Cache“

#WISSENTEILEN

// Caching in REST: // Revalidation & Condition GET

// Conditional GET after Timeout (max-age)GET /products/123 HTTP/1.1If-Non-Match: "1234567890987654321"

REST„Cache“

Modified since? No, 304 (Not Modified). Yes, 200 (Ok) plus

Data.

#WISSENTEILEN

REST... Security

#WISSENTEILEN

REST„Security“

#WISSENTEILEN

Authentication vs. Authorization

• Authentication a.k.a. „Hotelrezeption“• Authorization a.k.a. „Zimmerschlüssel“

Security

#WISSENTEILEN

Authentication vs. Authorization

• 401 „Unauthorized“meint eigentlich „Unauthenticated“!

• 403 „Forbidden“meint eigentlich „ Unauthorized“!

Security

#WISSENTEILEN

REST„Security“

Server based Security

• Sessions• Skalierbarbeit• Cookies • CORS • CSRF

#WISSENTEILEN

REST„Security“

Token based Security

• Stateless• Token statt Cookie• Individual Expiration• Friend to Friend Permissions

#WISSENTEILEN

JSON Web Token

• neue, einfache Spec• sehr kompakt• Token plus public & private „Claims“

• digitale Signatur und/oder Encryption• als Bearer Token und für SSO

Security

#WISSENTEILEN

REST„Security“

#WISSENTEILEN

JSON Web Token & API Goals

1. Authorize Request2. Verify Sender3. Avoid Man in the Middle4. Expiration5. Request Cloning

Security

#WISSENTEILEN

REST„Security“

#WISSENTEILEN

REST„Security“

#WISSENTEILEN

REST„Security“

#WISSENTEILEN

REST„Security“

#WISSENTEILEN

REST„Security“// Security in REST:

// JSON Web Token

//Reusable verifier instanceJWTVerifier verifier = JWT

.require(Algorithm.RSA256((RSAKey)publicKey))

.withIssuer("http://myAuth.com/auth/")

.build();

DecodedJWT jwt = verifier.verify(token);String userId = jwt.getSubject();String userName = jwt.getClaim("name").asString();String email = jwt.getClaim("email").asString();

com.oauth.jwt

#WISSENTEILEN

REST... API Evolution

#WISSENTEILEN

Was ist das Problem?

• neue APIs• geänderte APIs• deprecaded APIs

• Payload / Parameter Syntax• Payload / Parameter Semantik

API Evolution

#WISSENTEILEN

Postel‘s Law a.k.a. robustness principle:

„Be conservative in what you do*, be liberal in what you acceptfrom others.“

Ben Morris Blog:

„REST APIs don‘t need a versioning strategy – they need a change strategy!“

API Evolution

(* do = change)

#WISSENTEILEN

Versionierung! Aber wie?

• gar nicht• gar nicht (via neue Ressourcen) • gar nicht (via erweiterbarer Datenformate)• Versionsnummer in der URL• Version Request Header• Content Negotiation

API Evolution

#WISSENTEILEN

REST„Version“// Evolution in REST:

// Multiple Resources

// GET all orders v1 GET /orders HTTP/1.1

// GET all neworders, oders are deprecatedGET /neworders HTTP/1.1

// GET all even newer orders, new orders are deprecatedGET /evennewerorders HTTP/1.1

#WISSENTEILEN

REST„Version“// Evolution in REST:

// Multiple Resources

// GET all orders v1 GET /orders HTTP/1.1

// GET all neworders, oders are deprecatedGET /neworders HTTP/1.1

// GET all even newer orders, new orders are deprecatedGET /orders HTTP/1.1

#WISSENTEILEN

REST„Version“// Evolution in REST:

// Backwards compability

// Versioning via adaptable data format{ "items" : [ {

"name" : "coffee","quantity" : 1,"size" : "large",

} ],"location" : ”take-away"

}

#WISSENTEILEN

REST„Version“// Evolution in REST:

// Backwards compability

// Versioning via adaptable data format{ "items" : [ {

"name" : "coffee","quantity" : 1,"size" : "large",”price" : ”4 USD",

} ],”total-price" : ”4 USD","location" : ”take-away"

}

#WISSENTEILEN

REST„Version“// Evolution in REST:

// Backwards compability

// Versioning via adaptable data format{ "items" : [ {

"name" : "coffee","quantity" : 1,“size" : "large",“price" : ”4 USD",

} ],”price" : ”4 USD","location" : ”take-away"

}

„Are you a tolerant reader?“

#WISSENTEILEN

REST„Version“// Evolution in REST:

// via URL

// Versioning via URL (default version)GET /api/orders/1234 HTTP/1.1

// Versioning via URL (version 1)GET /api/v1/orders/1234 HTTP/1.1

// Versioning via URL (version 2)GET /api/v2/orders/1234 HTTP/1.1

No way! This isn‘t a RESOURCE!

#WISSENTEILEN

REST„Version“// Evolution in REST:

// via HEADER

// Versioning via Header(default version)GET /orders/1234 HTTP/1.1

// Versioning via Custom Header GET /orders/1234 HTTP/1.1Api-version: 2.1

// Versioning via Accept HeaderGET /orders/1234 HTTP/1.1Accept: application/vnd.restbucks.orderservice.v2.1+json

No way! This isn‘t a “clickable“ URL!

For chaching: „Vary: Content-Type“

#WISSENTEILEN

REST„Version“// Evolution in REST:

// via URL and HEADER

// Versioning via Header(default version)GET /orders/1234 HTTP/1.1

// Versioning via URL (major) and header (minor) GET /orders/v2/1234 HTTP/1.1my-api-version: 2017-05-01

#WISSENTEILEN

REST„Hateoas“

„If the engine of application state (and hence theAPI) is not driven by hypertext, then it cannot beRESTful and cannot be a REST API.“

Roy Fielding

// Evolution in REST: // Hypermedia as the engins of// application state

#WISSENTEILEN

REST„Hateoas“

„A REST API should be entered with no priorknowledge beyond the initial URI ... From thatpoint on, all application state transitions must bedriven by the client selection of server-provideschoices ...“

Roy Fielding

// Evolution in REST: // Hypermedia as the engins of// application state

#WISSENTEILEN

REST„ Hateoas“// Evolution in REST:

// Hypermedia as the engins of// application state

POST /orders/ HTTP/1.1{ ... payload of order to create ... }

HTTP/1.1. 201 CreatedLocation: http://restbucks.com/api/orders/1234Link: <.../orders/1234>; rel=„cancel“

<.../orders/1234>; rel=„update“, <.../orders/1234>; rel=„delete“,<.../payment/1234>; rel=„pay“

#WISSENTEILEN

FAZIT

#WISSENTEILEN

„The very most important thing is thatyou have an API that your consumersfind consistent and usable. This is not necessarily the same thingas being 100% RESTful.“

#WISSENTEILEN

FRAGEN

? ? ?

Kontakt

LARS RÖWEKAMPCIO NEW TECHNOLOGIES

lars.roewekamp@openknowledge.de+49 (0)441 4082 – 0

@mobileLarson@_openknowledge

OFFENKUNDIGGUT

#WISSENTEILEN

Bildnachweise

#97: © tomertu - shutterstock.com

All other pictures inside this presentation orginatefrom pixabay.com or were created by my own.

#WISSENTEILEN

top related