REST: Versprechen,
Wirklichkeit & die
Alternativen GraphQL,
gRPC, JSON RPC...
Version 1.2 vom 17.4.2017
Thomas Bayer
bayer@predic8.de
@thomasub
REST
#1 ist zu technisch
#2 ist kein Standard
#3 ist datengetrieben
#4 Design ist kompliziert
#5 fehlen Hypermedia Clients
#6 wird von Swagger bedroht!
Server
Remote Procedure Call
Runtime
Client
Product
Service
Stub
createProduct( mango)
Eigener Code
Eigener Code
!= REST
Scheinbar direkter
Aufruf
Funktion
ParameterService
productService.create( mango);
Remote == Lokal
Server
Produkt
Service
Client
Produkt
Service
Stub
.proto
GRPC2JAVA
Problem: Build ist komplex und erfordert Know-How
Server
REST
GET /produkte/65
/produkte/64
/produkte/65
/produkte/66
Client
HTTP Client
Repräsentation
{ name:
... }
Kopie!
Ressource
GetMethod method = new GetMethod("http://api.predic8.de/shop/products/65");
int sc = client.executeMethod(method);
if (sc != HttpStatus.SC_OK) {
...
}
byte[] responseBody = method.getResponseBody();
200 OK
• Kein Build
• Skripting ist möglich
Quelle: https://trends.google.de/trends/explore?date=all&q=%2Fm%2F03nsxd,%2Fm%2F0315s4
SOA & REST Hype Cycle
Quelle: https://trends.google.de/trends/explore?date=all&q=%2Fm%2F03nsxd,%2Fm%2F0315s4
SOA & REST Hype Cycle
REST Ressource!
REST
#1 ist zu technisch
#2 ist kein Standard
#3 ist datengetrieben
#4 Design ist kompliziert
#5 fehlen Hypermedia Clients
#6 wird von Swagger bedroht!
Die Bibel
HTTP Spezifikationen
sind verbindlich
HTTP/1.1 201 Created
Content-Type: application/json
Location: /shop/products/96
{
"name": "Pears",
"price": 1.78,
"self_uri": "/shop/products/96"
}
POST /shop/products/ HTTP/1.1
Content-Type: application/json
{
"name":"Pears",
"price":1.78
}
RFC 7231
3.1.4.2. Content-Location
HTTP/1.1 201 Created
Content-Type: application/json
Location: /shop/products/96
Content-Location: /shop/products/96
{
"name": "Pears",
"price": 1.78,
"self_uri": "/shop/products/96"
}
POST /shop/products/ HTTP/1.1
Content-Type: application/json
{
"name":"Pears",
"price":1.78
}
Quellen: https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf
https://de.wikipedia.org/wiki/Roy_Fielding#/media/File:Roy_Fielding.jpg
Wichtige Schrift für REST
Fans! Geniales Papier über
die Architektur des Webs,
aber nichts Konkretes zu
REST API Design.
Fielding Dissertation
According to Fielding:
PUT vs. POST in REST auf Stackoverflow
Quelle: https://stackoverflow.com/questions/630453/put-vs-post-in-rest
Guidelines
• Whitehouse
• Twitter
• Haufe Lexware
• ...
REST
#1 ist zu technisch
#2 ist kein Standard
#3 ist datengetrieben
#4 ist kompliziert
#5 fehlen Hypermedia Clients
#6 wird von Swagger bedroht!
C POST /products/
R GET /products/65
U PUT /products/65
D DELETE /products/65
storniereBestellung( 74)
DELETE /bestellung/74
PATCH /bestellung/74 {
“status“: “storniert“
}
PUT /bestellung/74/storno
/machines/46
PUT /machines/46/stop
PUT /machines/46/start
/rechnungen/
/rechnungen/{rid}
/positionen/
/positionen/{pid}
/rechnungen/
/rechnungen/{rid}
/rechnungen/{rid}/positionen/
/rechnungen/{rid}/positionen/{pid}
REST ohne Hypermedia ist CRUD over HTTP!
DB
Service
API
Client
Logik
Logik
Logik wandet
zum Client
Logik ist Seiteneffekt
einer Datenänderung
Zum wenig
Abstraktion
Innere Struktur
wird offen gelegt
REST
#1 ist zu technisch
#2 ist kein Standard
#3 ist datengetrieben
#4 Design ist kompliziert
#5 fehlen Hypermedia Clients
#6 wird von Swagger bedroht!
GET /products
oder
GET /products/
?
POST /produkte/
PUT /produkte/65
PATCH /produkte/65
Resource GET POST PUT DELETE
/articles/ List aller Artikel 201 Created
Neuer Artikel
erzeugen*
Location
Header setzen!
400 Bad
Request
Alle Artikel
löschen
/articles/7 Details zu
einem Artikel
400 Bad
Request
Artikel
erzeugen* oder
ändern
Artikel löschen
?
Subressoucen
/products/11/photo
/kunden/65/vertraege/
/vendors/32/products/
/kunden/65/vertraege/6/policy/24
?
/shop/products/65
/shop/products/65?limit=10
/shop/products;limit=10/
{ “Limit“: 10 }
Parameter
?Limit: 10
?Quelle: https://httpstatusdogs.com/
Prozesse &
Nicht-Ressource Anfragen
 Ressourcen passen irgendwie nicht richtig oder sind uninteressant
 Beispiele
 Errechnen
 Umwandeln
 Prozess als Ressource oft umständlich
/order/4/actions/cancel
/antrag/4354/freigabe
/calculator/compute
REST Design Probleme
 Mehrere Lösungen für ein Problem
 REST ist nicht einfach, wenn die Aufgaben größer werden
 Styleguide ist notwenig
 Auswahl & Erstellung sind schwer
 Es gibt keinen perfekten Styleguide
 Auswirkung vieler Designentscheidungen nicht sofort erkennbar!
 Viel Interpretation und Kreativität ist gefordert
 Man beschäftigt sich mehr mit der Auslegung von REST als mit der
Fachlichkeit
Welches REST API hat ein gutes Design?
API Design: The Musical
Quelle: https://events.drupal.org/losangeles2015/sessions/api-design-musical
Play
Automatisierte Design Tests
swagger-analyzer.com
REST
#1 ist zu technisch
#2 ist kein Standard
#3 ist datengetrieben
#4 ist kompliziert
#5 fehlen Hypermedia Clients
#6 wird von Swagger bedroht!
{
"products": [
{
"name": "Pineapples",
"product_url": "https://api.predic8.de/shop/products/33“
}
...
]
}
https://api.predic8.de/shop/products/
{
"name": "Pineapples",
"price": 3.55,
"photo_url": "https://api.predic8.de//shop/products/33/photo",
}
{
"products": [
{
"name": "Pineapples",
"product_url": "https://api.predic8.de/shop/products/33“
}
...
]
}
https://api.predic8.de/shop/products/
{
"name": "Pineapples",
"price": 3.55,
"photo_url": "https://api.predic8.de//shop/products/33/photo"
}
{
"products": [
{
"name": "Pineapples",
"product_url": "https://api.predic8.de/shop/products/33“
}
...
]
}
https://api.predic8.de/shop/
const traverson = require('traverson');
traverson
.from('https://api.predic8.de/shop/products/33')
.json()
.follow('vendor_url')
.getResource((err, json) => {
console.log("Hersteller: " + json.name)
});
https://github.com/traverson/traverson
Traverson Hypermedia Client for Node
Vertrag =Repräsentationen
Vertrag =Repräsentationen
URIs sind nicht Bestandteil
des Vertrages!
Hypermedia ist cool!
Wer verwendet Hypermedia?
... und auf dem Client?
Client sendet Link in einer Repräsentation
POST /shop/products/ HTTP/1.1
Content-Type: application/json
{
"name": "Pears",
"price": 1.78,
"vendor_url": "/shop/vendors/32"
}
HTTP/1.1 201 Created
Content-Type: application/json
Location: /shop/products/97
{
"name": "Pears",
"price":1.78,
"vendor_url":"/shop/vendors/32",
"product_url":"/shop/products/97"
}
Hypermedia Probleme
 Design ist aufwendig
 Dokumentewerdenlang undhäßlich
 VieleFormate, Best Practice, ...
 Clientverschmäht Hypermedia!
REST
#1 ist zu technisch
#2 ist kein Standard
#3 ist datengetrieben
#4 ist kompliziert
#5 fehlen Hypermedia Clients
#6 wird von Swagger bedroht!
Id angeben anstatt Link
verfolgen.
URI Template
Wer URIs dokumentiert macht RPC!
Fixe URIs führen zu starker Kopllung!
Mediatypes erfordern Dokumentation
Fielding, Kapitel 5!
Contract First mit Swagger
Swagger
mvn deploy
MVN
client.jar
Dependency
call
Projekt wird nur
gebaut. Kein
eigener Code
notwendig.
Code
Generation
Server Stub wird um
die Implementierung
erweitert
Client
• Das Remoting ist komplett
verborgen
• RPC sieht genauso aus
Erzeugte Methode
erfordert Id
Regex macht aus
URI id für Template
In Zahl umwandeln
/produkt/{pid}
+ 65
= /produkt/65
URI Templates sind nicht REST!
 Hypermedia und Swagger passen nicht zusammen!
 Swagger => RPC Stil
+
Swagger kills Hypermedia
• Swagger hat Vorteile
• HATEOAS hat Vorteile
• Swagger + HATEOAS gleichzeitig
• => Nachteil
REST ist nur (gutes) REST mit Hypermedia
Keiner macht Hypermedia => REST?
REST Alternativen
JSON RPC
GraphQL
GRPC
JSON RPC über HTTP
POST / HTTP/1.1
Content-Type: application/json;
{
"method": “get-preis",
"jsonrpc":“ 2.0",
"params": {
"name": "Mango"
},
"id":null
}
JSON RPC Server
var jayson = require('jayson');
const server = jayson.server({
createProduct: ( product, cb) => {
console.log("Creating " + product.name)
cb( null, { "success": true});
}
});
server.http().listen(8080);
REST Alternativen
JSON RPC
GraphQL
GRPC
Aufgabe: App mit Liste der Produkte
Mango
Kiwi
Apfel
Banane
Pfirsich
Client Server
t
Zeitverhalten entfernter Aufrufe
Preis?
Mango 1,99
Kiwi 2,10
Apfel 1,99
Banane 0,79
Pfirsich 1,29
Preis?
Client API
/shop/products/
/shop/products/3
/shop/products/10
/shop/products/33
Eine Abfrage der
Container Ressource
n-Abfragen für alle
Produkte der Liste
N + 1 Calls!
Chatty
Client Server
t
Zeitverhalten entfernter Aufrufe
/products/
/products/3
/products/7
Chunky or Chatty?
 Over Fetching
 Mehr Daten als notwendig werden übertragen
 => Chunky
 Under Fetching
 Nicht genug Daten werden übertragen
• => Subressourcen oder Relationen müssen verfolgt werden
• => Chatty
Quelle:
• https://pixabay.com/de/blabla-tafel-belanglosigkeit-1432922/
• https://pixabay.com/de/katze-dunkel-kaffee-faul-liegen-1351612/
/products/65?expand=vendor&fields=name,price
{
"name": "Pineapples",
"price": 3.55,
"vendor": {
“name“: “Exotic Fruits“
}
}
/products/65?expand=vendor&fields=name,price
{
"name": "Pineapples",
"price": 3.55,
"vendor": {
“name“: “Exotic Fruits“
}
}
Query Language
expand=vendor&fields=name,price
Genügt die Query Language?
GraphQL
REST Alternativen
JSON RPC
GraphQL
GRPC
GRPC
 RPC Framework
 Basiert auf Google Protocol Buffers
 Verwendet IDL
 Protocol Buffers als Message Format
• JSON ist auch möglich
 Art neues CORBA
 HTTP/2 Transport
 Geeignet für Mobile
 Google stellt auf GRPC für Microservices um
 Features
 Streaming
 Sprachunterstützung
 Android, C++,C#, Go, Java, Node, Objective-C, PHP, Python, Ruby
 Quelle
 https://grpc.io
Java ServerObjective-C Client
Stub
get(id)
gRPC Server
get(id)
MyCode
MyCode
protoc
.proto
service ProductManager {
rpc get(int32) returns (Product) {}
}
protobuf
Interface Definition Language
package fruitshop;
service ProductService {
rpc Create (CreateProductRequest) returns (CreateProductResponse) {}
}
message CreateProductRequest {
string name = 1;
float price = 2;
}
message CreateProductResponse {
}
ServiceImpl
class ProductServiceImpl extends ProductServiceGrpc.ProductServiceImplBase {
@Override
public void create(CreateProductRequest req,
StreamObserver<CreateProductResponse> resObserv) {
System.out.println("request = " + req);
CreateProductResponse reply = CreateProductResponse.newBuilder().build();
resObserv.onNext(reply);
resObserv.onCompleted();
}
}
Server
Server server = ServerBuilder.forPort(5000)
.addService(new ProductServiceImpl())
.build()
.start();
server.awaitTermination();
Client
ManagedChannel channel =
ManagedChannelBuilder.forAddress("localhost", 5000)
.usePlaintext(true)
.build();
ProductServiceBlockingStub stub = newBlockingStub(channel);
CreateProductRequest req = CreateProductRequest
.newBuilder()
.setName("Mango")
.setPrice(1.90f)
.build();
stub.create(req);
„The REST interface is designed to be efficient for large-
grain hypermedia data transfer, optimizing for the
common case of the Web, but resulting in an interface that
is not optimal for other forms of architectural
interaction.“
Quelle: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
Fielding in 5.1.5 Uniform Interface
Anwendung?
Public APIs Mobile Komplexe APIs
REST ++ - -
JSON RPC ++ + -
GRPC - + ++
GraphQL - ++ +
?
Fazit
 REST ist ideal für Public APIs
 REST kann jeder!
REST Design ist schwer
 Es gibt Alternativen zu REST
Messaging
RPC
Query Languages
REST is dead.
Long live REST!
@thomasub
bayer@predic8.de
Quellen
 Architectural Styles and the Design of Network-based Software
Architectures, Roy Thomas Fielding
 https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm
 RFC 7230, Hypertext Transfer Protocol (HTTP/1.1): Message
Syntax and Routing
 https://tools.ietf.org/html/rfc7230
 RFC 7231, Hypertext Transfer Protocol (HTTP/1.1): Semantics and
Content
 https://tools.ietf.org/html/rfc7231
 White House Web API Standards
 https://github.com/WhiteHouse/api-standards
 Haufe API Style Guide
 https://github.com/Haufe-Lexware/api-style-guide
 RESTful APIs, the big lie, Michael S. Mikowski
 https://mmikowski.github.io/the_lie/
 Status Dogs
 https://httpstatusdogs.com/

REST: Versprechen, Wirklichkeit & Alternativen: GraphQL, GRPC, JSON RPC...

Hinweis der Redaktion

  • #4 Technik ist verborgen
  • #6 Wir reden heute über REST API Interfaces zw. Client und Server zw. Maschine und Maschine
  • #7 Client/Server https://pixabay.com/de/sanduhr-uhr-zeitgeber-sand-zeit-152090/ https://pixabay.com/de/zahnrad-getriebe-kogge-optionen-145804/
  • #11 HTTP Spec ist verbindlich
  • #13 Sollen Anwendungsentwickler oder Schnittstellendesigner die HTTP Spec auswendig lernen?
  • #14 2000 Kapitel 5: REST Kapitel 6: Probleme bei REST auf HTTP übertragen Steht alles was ich wissen muss, wenn ich REST richtig mache!
  • #15 In den Köpfen ist POST zum Anlegen Ich habs Probiert idempotentes Anlegen mit PUT wird nicht akzeptiert und führt immer wieder zu Diskussion Erfahrung der Kommunity und Beispiele in Produkten. Auslegung: Relgion
  • #16 Notwendig, zum Teil wiedersprüchlich
  • #31 Welche Methode, Wie Life-Cycle?
  • #36 REST ist nicht uniform!
  • #37 Ab 5:28 abspielen!
  • #44 Kunden wollen URIs modellieren, kein Interesse am Design der Daten
  • #46 Alle einverstanden
  • #49 Welche API verarbeitet links in Repräsentationen, die von Clients übergeben werden?
  • #59 Von irgendwo kenne ich das API Beschreibung von CORBA/Web Services
  • #68 REST ist das verfolgen von Links
  • #69 REST kann für Swagger nichts! Hypermedia war nie lebendig
  • #71 Nicht Messaging, aber da gibt es auch Alternativen
  • #72 RPC Protokoll Designed to be simple Transport Agnostisch HTTP, TCP, Memory Positional & Named Parameters Batches Spezifikation JSON-RPC 2.0  ( März 2010) In 10 Minuten gelesen
  • #77 Pfeil normal wagrecht, aber um Zeit zu illustrieren nach unten Verzögerung spielt bei Mobile die größte Rolle
  • #81 Pfeil normal wagrecht, aber um Zeit zu illustrieren nach unten Verzögerung spielt bei Mobile die größte Rolle Chattyhttps://pixabay.com/de/blabla-tafel-belanglosigkeit-1432922/
  • #83 Levels?
  • #99 Now I have to wash my mouth with SOAP