REST
PHP User Group | 24.10.2013
Maximilian Berghoff
@ElectricMaxxx
Agenda

1. Einführung, Begriffsklärung und HTTP
2. Praxisbeispiel
3. FOSRestBundle
REST

1. Einführung,
Begriffsklärung und
HTTP
HTTP Basics

Request <-> Response
HTTP Basics - Request

Der Brief wird
losgeschickt ...
HTTP Basics - Request

HTTP - Header
GET /my/path HTTP/1.1
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.
8
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host: www.example.de
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML,
like Gecko) Ubuntu Chromium/28.0.1500.71 Chrome/28.0.1500.71
Safari/537.36
HTTP Basics - Response

HTTP - Header
HTTP/1.1 200 OK
Connection:keep-alive
Content-Type: text/html; charset=UTF-8
Date: Mon, 21 Oct 2013 12:20:55 GMT
Last-Modified: Mon, 21 Oct 2013 08:34:57 GMT
Content-Length: …
HTTP - Basics - Statuscode
1xx - Antwort dauert noch an
2xx - Erfolgreiche Operation
3xx - Umleitung
4xx - Client-Fehler
5xx - Server-Fehler
(Liste: http://de.wikipedia.org/wiki/HTTP-Statuscode)
REST

•
•
•
•

WebService (neben SOAP, XML-RPC)
kein fester Standart, viele Ideen
geht aus Dissertation v. Roy Fielding (2000)
hervor
“lebt” HTTP
WebService - Resourcen

Objekte, Dinge,
Entitäten, ...
WebService - Resourcen

Beispiele:
–
–
–
–

Erster Eintrag in einem Webblog
letzte Softwareversion
Quartalszahlen
Karte für eine Region
WebService - Methoden

Was soll ich tun?
WebServices

Unterscheiden sich durch:
• Angabe der Resource
• Angabe der Methode
• Quantität der Methoden
WebService - Beispiel(RPC)

http://www.example.de/rpc
WebService Beispiel(SOAP)

http://www.example.de/soap
WebService Beispiel(REST)

•
•
•
•
•
•
•

GET http://www.example.de/api/user
GET http://www.example.de/api/user/12
POST http://www.example.de/api/user
PUT http://www.example.de/api/user/12
DELETE http://www.example.de/api/user
OPTION http://www.example.de/api/user
HEAD http://www.example.de/api/user
REST

Adressierbarkeit
REST

Statelessness
REST - State

Application State
vs.
Resource State
REST

Repräsentation
REST - Repräsentation

HTTP - Header (Request)
–
–
–

Accept
Accept-Language
Authentification
REST - Repräsentation

HTTP - Header (Response)
–
–

Content-Type
Content-Language
REST - Repräsentation

URI
• http://example.de/api/article/en
• http://example.de/api/article/es
REST

Operationen
•
•
•
•

GET, HEAD, OPTIONS
POST
PUT
DELETE
REST - Operationen

GET, HEAD, OPTIONS
REST - Operationen

GET
REST - Operationen

HEAD
REST - Operationen

OPTIONS
REST - Operationen

POST
REST - Operationen (POST)

•
•
•
•

Kommentare/Anmerkungen an Resource
Nachrichten an Newsgroup, Mailinglist, …
Einem Daten-Prozess Daten (z.B. Formular)
liefern
Daten erweitern
REST - Operationen

PUT
REST - Operationen

POST
REST - Operationen

DELETE
REST

Verlinkung
“Hypermedia as engine of the application state” (Dissertation of Fiedling)
REST - Zusammenfassung
– Adressierbarkeit
– Zustandslosigkeit
– Operationen
– Verlinkung
REST

Representational
State
Transfer
REST

2. Beispielanwendung
Beispielanwendung

Hilfreich:
MVC - Pattern
Beispielanwendung

Hilfreich:
Request-/
Responserepräsentationen
Beispielanwendung

Hilfreich:
Routing - Bootstrapping
Beispiel - Request
Beispiel - Body parsenJSON
Beispiel - Body parsen-XML
Beispiel - Body parsen-Form
Beispiel - Response
Beispiel - Response
Beispiel - POST-Request
> POST /my/collection HTTP/1.1
> User-Agent: …
> Host: www.myhost.de
> Accept: */*
> Content-Type: application/json
> Authorization: …
> Content-Length: 556

{name:”max”,surname:”mustermann”,...}
Beispiel - POST-Response

> HTTP/1.1 201 Created
> Server: …
> Date: …
> Content-Type: application/json; charset=utf-8
> Location: https://.../my/collection/sub/2
> Content-Length 1389
> ETag: ...
Beispiel - GET-Request

> GET /my/collection HTTP/1.1
> User-Agent: …
> Host: www.myhost.de
> Accept: */*
> Authorization: ...
Beispiel - GET-Response

> HTTP/1.1 200 OK
> Server: …
> Date: …
> Content-Type: text/html
> Content-Length: 1111
> Last-Modiefied: …
> ETag: ...
Beispiel - PUT-Request
> PUT /my/Collection/sub/4 HTTP/1.1
> User-Agent: …
> Host:

www.myhost.de

> Accept: */*
> Content-Type: application/json
> Authorisation: …
> Content-Lenght: 161

{name:”marie”,...}
Beispiel - PUT-Response

> HTTP/1.1 200 OK
> Server: …
> Date: …
> Content-Type: application/json; charset=utf-8
> Content-Length: 4654
> ETag: ...
Beispiel - DELETE-Request

> DELETE /my/collection/sub/5 HTTP/1.1
> User-Agent: …
> Accept: */*
> Authorization: ...
Beispiel - DELETEResponse

> HTTP/1.1 204 No Content
> Server: …
> Date: …
REST

3. FOSRestBundle (Symfony)
FOSRestBundle

GitHub:
FriendsOfSymfony/FOSRestBundle
FOSRestBundle

(De-)Serialisierung:
JMSSerializerBundle
oder

Symfony-Komponente
(rudimentär)
Quellen
•

BlogPost zum BeispielCode:
http://www.lornajane.net/posts/2012/building-a-restful-php-server-understanding-the-request

•

Buch: “RESTful Webservice” v. Leonard Richardon & Sam Ruby

•

https://github.com/schmittjoh/JMSSerializerBundle.git

•

https://github.com/FriendsOfSymfony/FOSRestBundle.git

•

Blog zu Links: http://qafoo.com/blog/048_embedding_rest_entities.html

•

Link zu RestTalk von DrupalCon: http://www.youtube.com/watch?v=SSkZZLpaqdI
About Me

Maximilian Berghoff
Maximilian.Berghoff@gmx.de
@ElectricMaxxx
LiveCoding FOSRestBundle
-> Controller vom FOSREstBundle zeigen
-> Beispiel Requests auf diesen
REST

Questions?

Rest

Hinweis der Redaktion

  • #2 {"49":"- eig. wie jeder Webseitenaufruf = GET-Request\n- VERB: GET\n- Resource: z.B Collection (ohne Id), bestimmte resource (mit id) -&gt; CRUD-Sicht der Dinge\n- Accept-Header für die Antwort sind wichtig\n-&gt; Angabe als Liste möglich \n-&gt; hier der dümmste, der geht (IE)\n","38":"- warum?\n- Models können Resourcen repräsentieren\n- Views: content sensitive Ausgabe\n-&gt; entscheiden wie die Repräsentation aussehen soll\n-&gt; ausgehend vom Accept Header und dem was der Service kann\n-&gt; Content-Type setzen,...\n- Controller: Logic =&gt; Methoden abbilden\n-&gt; getAction($id), postAction($data,$format), putAction($data,$format),deleteAction($id)\n-&gt; muss nicht immer alles an eine id gebunden sein\n","27":"- ähnlich wie GET\n- nur ohne Body\n-&gt; also alle MetaInformationen die mit GET kommen würden\n","16":"Was ist hier anders?\n- Operationen = HTTP-Verben\n- Resourcen direkt in der URL (addressierbarkeit)\n- Methoden beschränkt\n- Resourcen eindeutig (URL, URI)\n-&gt; jetzt endlich REST \n","5":"Vorstellen wie einen Brief:\n- Adresse - URI\n- Adresszusätze - Metadaten im HTTP-Header\n- Informationen zum Absender\n-&gt; im sog. HTTP-Header\n","33":"- zum Löschen einer Resource\n- Identifizierung über URI\n","22":"Mögliche Header für einen Response:\n- der content-type der Antwort im Body\n- die mögliche Sprache der Antwort\n","50":"Erfolg: StatusCode 200 OK\n- Content-Type\n-&gt; hier html, wie üblich für ein GET-Request auf bspw. einer Webseite\n- Content-Length\nCaching-Data:\n-&gt; Last-Modified und ETag\n-&gt; beispielsweise für nächsten Request, mitsenden -&gt; 304 Not Modified -&gt; cool muss nix neu laden\nBody mit den Daten im angegebenen Format (XML, JSON, HTML, …)\n-&gt; hier können dann Hypermedia-Informationen angegeben werden\n-&gt; aktuelle url, url von Subresourcen, oder userdata\n-&gt; Client kann eigenständig navigieren\n","39":"- Abbildung Request&lt;-&gt;Response Zyklus \n- Client macht Request -&gt; alle Informatioen aus Request-Object\n- Server bereitet Antwort mit Views vor: Response-Object\n- Request-Object kann OOP Wrapper für $_SERVER sein -&gt; nicht schlimm\n","28":"- liefert mögliche Operationen auf Resource\n- kann mit/ohne Authenfication unterschiedlich sein\n","17":"- Möglichkeit Resource anzuwählen\n- eindeutig \n- Siegeszug des Web: Seiten = Resourcen adressierbar\n- z.B. www.google.de -&gt; aufschreiben, weitergeben, verlinken auf andere Resourcen\n- eine Adresse kann nur eine Resource bereitstellen (URI = UniformResourceIdentifier)\n- eine Resource kann aber unter mehren Adressen erreichbar sein (canonical, duplicate)\n","6":"Z1: Adresse \n- Operation = HTTP-Verb (GET später noch erklärt) -&gt; GET die meist verwendete üblichste\n- URI (auf Host aufgerufen) \n- Übertragungsprotokol (HyperTextTransferProtocol in v1.1)\nZ2-7: weitere Meta-Informationen\n- gewünschtes Format für die Antwort\n- gewünschte Sprache für die Antwort\n-&gt; weitere Erklärung später (Repräsentation)\n- caching Eigennschaften\n- Host, der angesprochen wird\n- der User-Agent, der die Anfrage sendet\n-&gt; viele weitere Möglich\n-&gt; einige werden per Default mit gesendet, andere kann/sollte man gezielt für Anfragen setzen\n","56":"- REST-Bundle im Context von Symfony\n-&gt; Routing durch Symfony gegeben\n-&gt; Controller als RestController zum extenden\n-&gt; Rückgabe von ResponseObject oder Daten zum rendern\n- dort README.md lesen\n- Doku vorhanden\n- \n","45":"status($code) \n-&gt; setzt den Status \n-&gt; nur nummer nötig den Text setzt ich aus Array\nsetHeader($val)\n-&gt; mehr ein addHeader() \n-&gt; einfache Strings in eine array bauen \n-&gt; werden später einfach über header(); ausgegeben\n-&gt;send()\n-&gt; switch der type sentisitiv den output vorbereitet\n-&gt; jeder Fall ruft weitere methode auf, die dann die Daten ausgibt\n-setData($data)\n-&gt; the data to render with an template\nsetFormat($format)\n-&gt; wenn ich aus dem ProgrammCode heraus unabhängig den Content-Type setzen will\nredirect($url)\n-&gt; setzt ein location header und setzt, wenn was drin ist den status\n","34":"- Was wäre Web ohne Links?\n- Webseiten (=Resourcen) beinhalten Links \n-&gt; andere Seiten (=Resourcen) erreichbar\n- ebenso in REST möglich \n-&gt; noch nicht so tief drin, aber:\n- durch: Hypermedia \n-&gt; HTML, XML als Links zu anderen Resourcen \n-&gt; “MultimediaLinks” \n-&gt; verschiedene Resourcen, nicht nur Text (Hypertext)\n-&gt; Vorschläge für den Pfad durch den sog. Application State\nRelative Resourcen angegeben\n","23":"Informationen über Repräsention auch in der URI möglich\n-&gt; Ansichtssache\n- viele Informationen in URI als Vorsatz\n- Struktur nicht verlieren\n","12":"- Client muss WebService mitteilen was zu tun ist\n- nur Daten abrufen\n- neues Item anlegen\n- bestehende Resource ergänzen\n","1":"Schon wieder ein REST Talk?\n- Auswerten der Umfrage auf Xing, festellen wie Wissenstand ist\n","51":"Eigentlich wie POST\n- Resource muss genau bekannt sein (also deren Adresse)\n-&gt; vorher GET Request um die Daten zu haben -&gt; Verändern\n- Content-Type/Content-Length weil Daten im Body vorhanden\n- Body mit den Daten\n","40":"- url auslesen (Request-Object)\n- muss sehr ausgeklügelt sein\n- Controller für Resource aufrufen\n","29":"- am meisten “missverstandenes” HTTP-Verb\n- als Standart für SOAP/XML-RPC apis alles ist POST an eine bestimmte uri\n","18":"- Zustandslosigkeit (engl. schöner)\n- Grundwert von HTTP\n- jeder Request für sich abgeschlossen\n- keine Seitenefekte möglich\n- Reihenfolge unabhängig (Back-Button geht nicht -&gt; nicht Stateless)\n- eigentlich Web so aufgebaut\n- man muss effektiv etwas dafür tun um dagegen zu verstoßen (Sessions)\n","7":"Z1: Protokol + Status der Antwort als Headline\n-&gt; viele verschiedene Statuscodes \n-&gt; Liste Wikipedia\n- Typ der Verbindung\n- Content-Type, das Format der Daten im Body -&gt; zum parsen nötig\n- Datum\n- letzte Änderung -&gt; Caching\n- Content-Length: Größe der Antwort, z.B. auch beim Download\n","57":"- POST,PUT Daten in Objekte umwandeln\n- Ausgaben von GET content sensitive erstellen\n","46":"selbst erklärend:\n-&gt; content-type setzen\n-&gt; restliche header ausgeben\n-&gt; daten rendern ausgeben \n-&gt; html per twig, xml per simpleXML (noch) sonst json_encode\n","24":"- gibt noch weitere, aber diese sollen reichen\n- Beispiele folgen\n","2":"1.)\n- Definition\n- Vokalbeln\n- Wdh. HTTP Basics\n2.)\n- Beispiel nach dem Vorbild von Lorna Jane \n- eigene Entwürfe\n3.)\n- SymfonyBundle\n- zusammen mit dem JMSSerializerBundle\n","52":"Unterscheidung von POST\nErfolg: StatusCode 200 OK\n-&gt; man erhält die selbe Instanz der Resource zurück\n-&gt; Content-Type/Content-Length nötig\n","41":"post() -&gt; einfach nur ein OOP Wrapper für $_POST \nget() -&gt; einfach nur ein OOP Wrapper für $_GET\ngetHeader(), kann sowohl einzelnes Header d. Request zurück liefern als auch array aus allen\ngetVerb() liefert das Verb, Achtung: es gibt Clients (Backbone.js), die Verben per Method_Override schicken\ngetAcceptFormat() -&gt; dummer Name, aber ließt gesondert den Accept-Header aus -&gt; für die Response sinnvoll\ngetContentFormat() -&gt; für das Parsing des Bodies -&gt; Content-Type sehr wichtig\ngetData() -&gt; parst die im Body gesendeten Daten anhand des Content-Type \n","30":"- aus RFC 2616 HTTP-Standart\n-&gt; wenig mit $_POST zu tun (ebenso für $_GET)\n- wirkliche POST-Daten sogar: aus dem Body des Requests auslesen!\n- Wichtig: Body wird gesendet -&gt; Content-Type+Content-Length senden!\n","19":"- Untescheidung nötig\n- Nutzer kann in gewissen Status in der Application haben\nz.B Google Unterseite 5 nach Suche auf\n- interessiert die Resource (Liste an Suchergebnissen) erst einmal wenig \n- Service muss aber unterschiedliche Nutzer in unterschiedlichen Stati unterscheiden können\nz.B. google api (alt) mit max queries: \n- Nutzer A hat 999 Queries gesendet, bekommt noch eine, danach 402 Payment Required\n- Nutzer B hat 400 Queries gesendet, bekommt noch länger Ergebnis\n-&gt; Probleme bei Load Balancern = Scaleability\nmit Statelesness nur Problemenatisch wenn ich Resource auf Cluster splitten muss\n","8":"StatusCodes als Headlines -&gt; erste Info, die man sieht\n1 - manchmal nötig, da sonst Clients in Timeout gehen (noch nie verwendet)\n2 - Häufig: 200 OK \n-&gt; alles mit 2 ist gut\n3:\n-&gt; alles mit 3 heißt ja, aber…\n301 Moved Permanently\n304 Not Modified \n- header(“location: /path”); -&gt; 302 Moved Temporary -&gt; header(“HTTP/1.1 301); vorher nötig!\n4:\n-&gt; Fehler im Request\n400 Bad Request \n404 Not Found (Anfrage nach einer Resource, die nicht gefunden werden kann)\n5 - 504 Gateway Timeout\n","47":"- Verb: POST -&gt; klar\n- URI mit Resource unter der eine SubResource angelegt werden soll\n-&gt; also der collection\n- Content-Type der Daten, die im Bode mitgesendet werden müssen\n- Conten-Length\n- Accept, denn meist eine Antwort: komplette Repräsentation der Resource mit URI\n- Body die Daten\n","36":"Endlich bei der Bedeutung des Akronyms\n- es geht um Repräsentationen von Daten\n- deren Status wird ausgetauscht\n- aber zwischem wem?\n- Application State -&gt; Resource State (POST, DELETE, PUT)\n-&gt; application state wird übernommen\n-&gt; soll übernommen werden\n- Resource State -&gt; Application State (GET,HEAD, OPTIONS)\n-&gt; man erhält den “aktuellen” Stand der Resource\n","25":"- keine Änderungen an der Resource\n- client erwartet keine SideEffekte\n- sog. “Sichere” Operationen\n","14":"- da sieht man nicht viel\n- Methode + Resource Inforamtion im Body\n- Verteter: XML-RPC -&gt; Body im XML-Format \n","53":"- Verb: DELETE\n- URI: genaue Resource\n-&gt; sehr einfach\n","31":"- zum Ändern einer Resource\n- resource muss direkt angesprochen werden\n- wichtig: vorher muss ein GET-Request passiert sein, damit man die Resource vor sich hat -&gt; Ändern\n- Daten im Body mitsenden\n- Content-Type angeben -&gt; Identifizierung des Body/der Daten\n- Anlegen einer Resource, wenn genaue Adresse bekannt\n","20":"- Resource nicht nur Daten\n- Darstellung/Aufbereitung der Daten oder Sprache des Inhalts\n-&gt; Eine Resource verschiedenen Repräsentationen\n- Wie wählt man Repräsentation?\n","9":"sog. WebService\n- Softwareanwendung über Netzwerk für Maschine-Maschine-Interaktion (Wikipedia)\n- unsere Software meist Client \n- z.B. google api\n","48":"Erfolg: StatusCode 201 Created\nContent-Type/Content-Length -&gt; klar\nLocation: URI der neuen Resource = Redirect auf die neue Resource -&gt; man hat die Daten\n","37":"- nun ein kleines Beispiel\n- kein vollständiger Code\n-&gt; nach zu lesen in Blog-Article von Lorna Jane\n","26":"- Informationen zu einer Resource erhalten\n- Daten werden im Body (mit content-type, content-length) geliefert\n","15":"SOAP:\n- Spezialisierung von XML-RPC\n-&gt; Body (mit Method und Resource Information) in SOAP- Envelope eingebettet\nMethoden:\n- unbestimmt viele\n- durch Doko festgehalten\n- GET/POST -&gt; unterschiedlich\n","4":"- egal ob Browser, Curl oder sonstiger Client\n-&gt; alles beginnt mit dem sog. Request v. Client\n-&gt; Antwort vom Server: Response\nBeispiel:\n- Browser (Client) fordert Inhalt einer Seite an: Request\n- Server bearbeitet diesen,\n- gibt eine HTML-Seite aus: Response\n","54":"Erfolg: StatusCode: 204 No Content\n- resource wurde gelöscht\n-&gt; da gibt es Nichts zurück zu sende, was denn auch???\n","32":"- zum Anlegen einer Resource\n- unter einer Resource anlegen\n- wo man die neue uri nicht kennt\n-&gt; Body/Daten identifizieren\n","21":"Mögliche Header für einen Request:\n- in welchem Format will ich die Resource haben\n- in welche Sprache\n- auch Authenfication spielt eine Rolle (siehe OPTIONS)\n- Metadaten \n","10":"- geht um Erhalten, Verändern oder anlegen von Daten bzw. Informationen\n- viele Dinge können Resourcen sein\n- nicht nur sog. CRUD-Items \n- nicht nur Abbildung von SQL-Schemata\n- auch als “Scoping Information” bezeichnet\n"}