Die ressourcenorientierte Architektur - beim O'Reilly Verlag
Die ressourcenorientierte Architektur - beim O'Reilly Verlag
Die ressourcenorientierte Architektur - beim O'Reilly Verlag
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Frischer Wind für<br />
Web Services durch REST<br />
Deutsche<br />
Ausgabe<br />
Web Services<br />
mit<br />
REST<br />
O’Reilly<br />
Leonard Richardson & Sam Ruby<br />
Deutsche Übersetzung von<br />
Thomas Demmig & Sebastian Tussing
Web Services mit REST<br />
Leonard Richardson und Sam Ruby<br />
Deutsche Übersetzung von<br />
Thomas Demmig und Sebastian Tussing<br />
Beijing · Cambridge · Farnham · Köln · Paris · Sebastopol · Taipei · Tokyo
<strong>Die</strong> Informationen in diesem Buch wurden mit größter Sorgfalt erarbeitet. Dennoch können<br />
Fehler nicht vollständig ausgeschlossen werden. <strong>Verlag</strong>, Autoren und Übersetzer übernehmen<br />
keine juristische Verantwortung oder irgendeine Haftung für eventuell verbliebene Fehler und<br />
deren Folgen.<br />
Alle Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt und sind<br />
möglicherweise eingetragene Warenzeichen. Der <strong>Verlag</strong> richtet sich im Wesentlichen nach den<br />
Schreibweisen der Hersteller. Das Werk einschließlich aller seiner Teile ist urheberrechtlich<br />
geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung,<br />
Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.<br />
Kommentare und Fragen können Sie gerne an uns richten:<br />
O’Reilly <strong>Verlag</strong><br />
Balthasarstr. 81<br />
50670 Köln<br />
Tel.: 0221/9731600<br />
Fax: 0221/9731608<br />
E-Mail: kommentar@oreilly.de<br />
Copyright der deutschen Ausgabe:<br />
© 2007 by O’Reilly <strong>Verlag</strong> GmbH & Co. KG<br />
1. Auflage 2007<br />
<strong>Die</strong> Originalausgabe erschien 2007 unter dem Titel<br />
RESTful Web Services bei O’Reilly Media, Inc.<br />
<strong>Die</strong> Darstellung eines Fuchskusu im Zusammenhang<br />
mit dem Thema Web Services mit REST ist ein<br />
Warenzeichen von O’Reilly Media, Inc.<br />
Bibliografische Information Der Deutschen Bibliothek<br />
<strong>Die</strong> Deutsche Bibliothek verzeichnet diese Publikation in der<br />
Deutschen Nationalbibliografie; detaillierte bibliografische Daten<br />
sind im Internet über http://dnb.ddb.de abrufbar.<br />
Übersetzung und deutsche Bearbeitung: Thomas Demmig, Sebastian Tussing, Mannheim<br />
Lektorat: Volker Bombien, Köln<br />
Fachliche Begutachtung: Dr. Claudia Nölker, Bielefeld<br />
Korrektorat: Eike Nitz, Köln<br />
Satz: DREI-SATZ, Husby<br />
Umschlaggestaltung: Michael Oreal, Köln<br />
Produktion: Andrea Miß, Karin Driesen, Köln<br />
Belichtung, Druck und buchbinderische Verarbeitung:<br />
Druckerei Kösel, Krugzell; www.koeselbuch.de<br />
ISBN 978-3-89721-727-0<br />
<strong>Die</strong>ses Buch ist auf 100% chlorfrei gebleichtem Papier gedruckt.
First<br />
Inhalt<br />
Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .<br />
Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .<br />
IX<br />
XI<br />
Max.<br />
Linie<br />
1 Das programmierbare Web und seine Bewohner . . . . . . . . . . . . . . . . . . . . . . . 1<br />
Lebewesen im programmierbaren Web . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
HTTP: Dokumente in Umschlägen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6<br />
Methodeninformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
Fokusinformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
<strong>Die</strong> konkurrierenden <strong>Architektur</strong>en . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />
Technologien im programmierbaren Web . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />
Weitere Terminologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />
2 Clients für Web Services schreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25<br />
Web Services sind Web-Sites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25<br />
del.icio.us: <strong>Die</strong> Beispielanwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28<br />
Einen Request stellen: HTTP-Bibliotheken . . . . . . . . . . . . . . . . . . . . . . . . 31<br />
Verarbeiten der Response: XML-Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . 42<br />
JSON-Parser: Umgang mit serialisierten Daten . . . . . . . . . . . . . . . . . . . . . 48<br />
Clients ganz einfach – mit WADL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52<br />
3 Was macht REST-konforme Services anders? . . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />
Einführung in den Simple Storage Service . . . . . . . . . . . . . . . . . . . . . . . . . 55<br />
Objektorientiertes Design von S3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57<br />
Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58<br />
HTTP-Responsecodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60<br />
Ein S3-Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62<br />
Signierte Requests und Zugriffskontrolle . . . . . . . . . . . . . . . . . . . . . . . . . . 72<br />
Verwenden der S3-Client-Bibliothek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79<br />
Max.<br />
Linie<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
| V
Transparente Clients durch ActiveResource . . . . . . . . . . . . . . . . . . . . . . . 80<br />
Abschlusswort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86<br />
Links<br />
Max.<br />
Linie<br />
4 <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89<br />
Ressourcenorientiert: Warum? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90<br />
Was ist eine Ressource? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91<br />
URIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92<br />
Adressierbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95<br />
Zustandslosigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98<br />
Repräsentationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103<br />
Verweise und Verbindungshaftigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106<br />
<strong>Die</strong> einheitliche Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110<br />
Das war’s! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119<br />
5 Entwurf von nur lesbaren <strong>ressourcenorientierte</strong>n Services . . . . . . . . . . . . . . . . 121<br />
Ressourcendesign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123<br />
Anforderungen in nur lesbare Ressourcen umwandeln . . . . . . . . . . . . . . . 124<br />
Welche Daten sind notwendig? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125<br />
Unterteilen der Daten in Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128<br />
Benennen der Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133<br />
Entwerfen Sie Ihre Repräsentationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140<br />
Verbinden der Ressourcen miteinander . . . . . . . . . . . . . . . . . . . . . . . . . . . 154<br />
<strong>Die</strong> HTTP-Response . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156<br />
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160<br />
6 Entwurf von les- und schreibbaren <strong>ressourcenorientierte</strong>n Services . . . . . . . . . 161<br />
Benutzerkonten als Ressourcen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162<br />
Eigene Orte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177<br />
Ein Blick zurück auf den Kartenservice . . . . . . . . . . . . . . . . . . . . . . . . . . . 187<br />
7 Eine Service-Implementierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189<br />
Ein Social Bookmarking-Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189<br />
Welche Daten werden benötigt? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191<br />
Ressourcendesign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193<br />
Vom Client kommende Repräsentation(en) entwerfen . . . . . . . . . . . . . . . 207<br />
Repräsentation(en) zum Senden an den Client entwerfen . . . . . . . . . . . . . 210<br />
Ressourcen miteinander verbinden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211<br />
Was soll passieren? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212<br />
Was kann schiefgehen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213<br />
Controller-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214<br />
Model-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233<br />
Was muss der Client wissen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237<br />
Max.<br />
Linie<br />
VI | Inhalt<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.
Rechts<br />
8 Best Practices: REST und ROA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243<br />
Ressourcenorientierte Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243<br />
Der allgemeine ROA-Ablauf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244<br />
Addressierbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245<br />
Zustand und Zustandslosigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246<br />
Connectedness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247<br />
<strong>Die</strong> einheitliche Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247<br />
Das ist wirklich wichtig . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250<br />
Ressourcendesign . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258<br />
URI-Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264<br />
Ausgehende Repräsentationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265<br />
Eingehende Repräsentationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266<br />
Versionierung des Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267<br />
Permanente URIs vs. lesbare URIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268<br />
Standardeigenschaften von HTTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270<br />
PUT und DELETE vortäuschen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286<br />
Ärger mit Cookies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286<br />
Warum einem HTTP-Client trauen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288<br />
Max.<br />
Linie<br />
9 <strong>Die</strong> Bausteine eines Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295<br />
Repräsentationsformate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295<br />
Zusammengestellte Kontrollflüsse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312<br />
Hypermedia-Technologien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325<br />
10 <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong> vs. dicke Web Services . . . . . . . . . . . . . . 343<br />
Welche Probleme versuchen dicke Web Services zu lösen? . . . . . . . . . . . . 344<br />
SOAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345<br />
WSDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349<br />
UDDI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355<br />
Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356<br />
Reliable Messaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358<br />
Transaktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359<br />
BPEL, ESB und SOA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360<br />
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362<br />
11 Ajax-Anwendungen als REST-Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363<br />
Von AJAX zu Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364<br />
<strong>Die</strong> Ajax-<strong>Architektur</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364<br />
Ein del.icio.us-Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366<br />
<strong>Die</strong> Vorteile von Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369<br />
<strong>Die</strong> Nachteile von Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370<br />
REST geht besser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371<br />
Max.<br />
Linie<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
Inhalt | VII
Durchführung des Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372<br />
Verarbeitung der Response . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374<br />
JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375<br />
Behalten Sie nicht die Vorteile von REST für sich . . . . . . . . . . . . . . . . . . . 376<br />
Cross-Browser-Probleme und Ajax- Bibliotheken . . . . . . . . . . . . . . . . . . . 378<br />
Das Sicherheitsmodell des Browsers untergraben . . . . . . . . . . . . . . . . . . . 382<br />
Links<br />
12 Frameworks für REST-konforme Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391<br />
Ruby on Rails . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391<br />
Restlet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396<br />
Django . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409<br />
A Einige Ressourcen für REST und einige REST-konforme Ressourcen . . . . . . . . . 421<br />
Standards und Leitfäden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421<br />
Services, die Sie verwenden können . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423<br />
B <strong>Die</strong> wichtigsten 42 HTTP-Responsecodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429<br />
Drei bis sieben Statuscodes: Das Minimum . . . . . . . . . . . . . . . . . . . . . . . . 430<br />
1xx: Meta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431<br />
2xx: Erfolgreich . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433<br />
3xx: Weiterleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436<br />
4xx: Fehler auf Clientseite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440<br />
5xx: Fehler auf Serverseite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447<br />
C <strong>Die</strong> HTTP-Header-Hitliste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451<br />
Standard-Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452<br />
Header außerhalb des Standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468<br />
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471<br />
Max.<br />
Linie<br />
Max.<br />
Linie<br />
VIII | Inhalt<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.
First<br />
Kapitel 4<br />
KAPITEL 4<br />
Hier Mini IVZ eingeben!<br />
<strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
Erstellen auf den<br />
Arbeitsseiten<br />
(siehe Muster)<br />
Max.<br />
Linie<br />
Abstand untere Tabellenlinie zu Textanfang 1,8 cm<br />
-> also: manuell auf den Arbeitsseiten ziehen!!!<br />
Ich habe Ihnen zwar die Möglichkeiten von REST gezeigt, habe dabei aber nicht systematisch<br />
erklärt, wie sie strukturiert sind oder wie man sie auch verfügbar macht. In<br />
diesem Kapitel beschreibe ich eine konkrete REST-konforme <strong>Architektur</strong>: die <strong>ressourcenorientierte</strong><br />
<strong>Architektur</strong> (ROA). ROA ist ein Weg, um ein Problem in einen<br />
REST-konformen Web Service umzuwandeln: eine Kombination aus URIs, HTTP<br />
und XML, die so wie der Rest des Webs funktioniert und die Programmierer gerne<br />
nutzen werden.<br />
In Kapitel 1 habe ich REST-konforme Web Services anhand der Beantwortung von<br />
zwei Fragen klassifiziert. <strong>Die</strong>se Antworten entsprechen zwei der vier definierenden<br />
Features von REST:<br />
• <strong>Die</strong> Fokusinformation (»Warum sollte der Server diese Daten senden und nicht<br />
jene?«) befindet sich in dem URI. Das ist das Prinzip der Adressierbarkeit.<br />
• <strong>Die</strong> Methoden-Information (»Warum sollte der Server die Daten schicken und<br />
nicht löschen?«) befindet sich in der HTTP-Methode. Es gibt nur ein paar<br />
HTTP-Methoden und man weiß schon vorher, was sie tun. Das ist das Prinzip<br />
der einheitlichen Schnittstelle.<br />
In diesem Kapitel stelle ich die Kernbestandteile der <strong>ressourcenorientierte</strong>n<br />
<strong>Architektur</strong> vor: Ressourcen (natürlich), ihre Namen, ihre Repräsentationen und die<br />
Verweise zwischen ihnen. Ich erläutere die Eigenschaften der ROA: Adressierbarkeit,<br />
Zustandslosigkeit, Verbindungshaftigkeit und die einheitliche Schnittstelle.<br />
Ich zeige, wie die Web-Technologien (HTTP, URIs und XML) diese Bestandteile<br />
implementieren, um die Eigenschaften möglich zu machen.<br />
In den vorigen Kapiteln habe ich Konzepte präsentiert, indem ich bestehende Web<br />
Services vorgestellt habe, wie zum Beispiel S3. Ich will das in diesem Kapitel fortführen,<br />
möchte aber Konzepte zusätzlich deutlich machen, indem ich auf bestehende<br />
Web-Sites verweise. Ich habe Sie hoffentlich schon davon überzeugt, dass<br />
Web-Sites auch Web Services sind und dass viele Web-Anwendungen (wie zum<br />
Beispiel Suchmaschinen) REST-konforme Web Services darstellen. Wenn ich über<br />
Max.<br />
Linie<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
This is http://www.oreilly.de/catalog/restfulwsger/<br />
the Title of the Book, eMatter Edition<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
| 89
Max.<br />
Linie<br />
abstrakte Konzepte wie Adressierbarkeit spreche, ist es hilfreich, Ihnen reale URIs zu<br />
zeigen, die Sie in Ihren Web-Browser eintippen können, um die Konzepte auch im<br />
wahren Leben zu sehen.<br />
Ressourcenorientiert: Warum?<br />
Warum komme ich hier mit einem neuen Begriff an, <strong>ressourcenorientierte</strong> <strong>Architektur</strong>?<br />
Warum schreibe ich nicht einfach REST? Nun, auf dem Buch steht vorne REST<br />
drauf und ich sage auch, dass alles in der <strong>ressourcenorientierte</strong>n <strong>Architektur</strong> RESTkonform<br />
ist. Aber REST ist keine <strong>Architektur</strong>, sondern eine Zusammenstellung von<br />
Designkriterien. Sie können sagen, dass eine <strong>Architektur</strong> diese Kriterien besser<br />
erfüllt als eine andere, aber es gibt nicht die eine »REST-<strong>Architektur</strong>«.<br />
Bisher neigten die Leute eher dazu, jedes Mal <strong>beim</strong> Entwerfen ihrer Services eine<br />
neue <strong>Architektur</strong> nur für diesen einen Fall zu entwerfen – und zwar entsprechend<br />
ihrem eigenen Verständnis von REST. Das offensichtlichste Ergebnis davon ist die<br />
große Anzahl von REST-RPC-Hybrid-Web Services, von denen ihre Erbauer<br />
behaupten, sie seien REST-konform. Ich versuche, das zu beenden, indem ich eine<br />
Reihe konkreter Regeln für das Erstellen von Web Services vorstelle, die wirklich<br />
REST-konform sind. In den nächsten beiden Kapiteln werde ich sogar einfache<br />
Vorgehensweisen zeigen, denen Sie folgen können, um Anforderungen in Ressourcen<br />
umzuwandeln. Wenn Sie meine Regeln nicht mögen, bekommen Sie zumindest<br />
eine Idee davon, was Sie ändern können, ohne dabei weniger REST-konform zu werden.<br />
Als Sammlung von Designkriterien ist REST sehr allgemein. Insbesondere ist es nicht<br />
an das Web gebunden. Nichts in REST hängt von den Mechanismen von HTTP oder<br />
der Struktur von URIs ab. Aber ich spreche hier über Web Services, daher verbinde<br />
ich die <strong>ressourcenorientierte</strong> <strong>Architektur</strong> explizit mit den Web-Technologien. Ich<br />
möchte darüber reden, wie man REST mit HTTP und URIs umsetzen kann – in spezifischen<br />
Programmiersprachen. Wenn die Zukuft REST-konforme <strong>Architektur</strong>en<br />
schafft, die nicht auf dem Web aufsetzen, werden deren Best Practices wohl ähnlich<br />
wie ROA aussehen, die Details sich aber unterscheiden. Wir werden das noch näher<br />
betrachten, wenn wir dorthin gelangen.<br />
<strong>Die</strong> klassische Definition von REST enthält eine Menge Freiräume, die von den<br />
Anwendern mit Eigenkreationen gefüllt wurden. Ich gehe mit Absicht weiter als Roy<br />
Fielding in seiner Dissertation oder das W3C in seinen Standards: Ich möchte einige<br />
der »offenen« Bereiche klarer gestalten, so dass die Eigenentwürfe sich zu wohldefinierten<br />
Best Practices entwickeln. Selbst wenn REST eine <strong>Architektur</strong> wäre,<br />
fände ich es nicht fair, meine <strong>Architektur</strong> genauso zu benennen. Ich würde meine<br />
empirischen Beobachtungen und Vorschläge mit den allgemeiner gehaltenen Gedanken<br />
derer verbinden, die das Web aufgebaut haben.<br />
Links<br />
Max.<br />
Linie<br />
90 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Mein letzter Grund für einen neuen Begriff ist, dass »REST« in Glaubenskriegen von<br />
Nerds verwendet wird. Seine Nutzung geschieht häufig im Zusammenhang mit der<br />
Meinung, dass es nur eine wirklich REST-konforme <strong>Architektur</strong> gibt – die, die der<br />
Sprecher bevorzugt. Leute, die andere REST-konforme <strong>Architektur</strong>en eher mögen,<br />
widersprechen. <strong>Die</strong> REST-Gemeinschaft ist zersplittert, obwohl es eine gemeinsame<br />
Basis in Bezug auf Dinge wie den Wert von URIs und HTTP gibt.<br />
Idealerweise sollte es keine Glaubenskriege geben, aber ich habe genug gesehen, um<br />
zu wissen, dass dieser Wunsch nicht für ihr Ende sorgen wird. Daher gebe ich meiner<br />
Philosophie, wie REST-konforme Anwendungen entworfen werden sollten, einen<br />
anderen Namen. Wenn diese Ideen – was zwangsläufig geschehen wird – als Munition<br />
in solchen Kriegen genutzt werden, können Leute, die mit mir nicht übereinstimmen,<br />
Elemente der <strong>ressourcenorientierte</strong>n <strong>Architektur</strong> von anderen RESTkonformen<br />
<strong>Architektur</strong>en und von REST im Allgemeinen trennen. Klarheit ist der<br />
erste Schritt zum Verständnis.<br />
<strong>Die</strong> Begriffe »ressourcenorientiert« und »<strong>ressourcenorientierte</strong> <strong>Architektur</strong>« wurden<br />
genutzt, um REST-konforme <strong>Architektur</strong>en im Allgemeinen zu beschreiben. 1 Ich<br />
denke nicht, dass »<strong>ressourcenorientierte</strong> <strong>Architektur</strong>« ein komplett neuer Begriff ist,<br />
aber ich glaube, dass meine Verwendung gut zu früheren Nutzungen passt und es<br />
besser ist, diesen Begriff zu nutzen, als für REST als Ganzes zu sprechen.<br />
Was ist eine Ressource?<br />
Eine Ressource ist alles, was wichtig genug ist, um als eigenständiges Etwas referenziert<br />
zu werden. Wenn Ihre Benutzer »einen Hypertext-Verweis dafür erstellen,<br />
Annahmen darüber erstellen oder widerrufen, eine Darstellung davon holen oder<br />
speichern, alles oder Teile davon per Referenz in andere Darstellungen übernehmen,<br />
es kommentieren oder andere Operationen darauf ausführen wollen«, sollten Sie es<br />
zu einer Ressource machen. 2<br />
Normalerweise ist eine Ressource etwas, das auf einem Computer gespeichert und<br />
als Bit-Stream dargestellt werden kann: ein Dokument, eine Zeile in einer Datenbank<br />
oder das Ergebnis eines Algorithmus. Eine Ressource kann ein physikalisches Objekt<br />
Max.<br />
Linie<br />
1 <strong>Die</strong> älteste Erwähnung von »ressourcenorientiert«, die ich gefunden habe, ist in einem Artikel aus der<br />
IBM developerWorks von 2004 von James Snell: »Resource-oriented vs. activity-oriented Web services«<br />
(http://www-128.ibm.com/developerworks/xml/library/ws-restvsoap/). Alex Bunardzic hat »<strong>ressourcenorientierte</strong><br />
<strong>Architektur</strong>« im August 2006 genutzt, bevor dieses Buch angekündigt worden war: http://<br />
jooto.com/blog/index.php/2006/08/08/replacing-service-oriented-architecture-with-resource-orientedarchitecture/.<br />
Ich stimme nicht mit allem in diesen Artikeln überein, aber ich gebe zu, dass sie die Terminologie<br />
schon zuvor genutzt haben.<br />
2 »The Architecture of the World Wide Web« (http://www.w3.org/TR/2004/REC-webarch-20041215/<br />
#p39), worin viel Zitierwürdiges zu finden ist, so zum Beispiel: »Softwareentwickler sollten davon ausgehen,<br />
dass eine Nutzung der gleichen URIs in mehreren Anwendungen nützlich sein wird, auch wenn<br />
das nicht gleich offensichtlich ist.« Das könnte der Schlachtruf für die ROA sein.<br />
Max.<br />
Linie<br />
Was ist eine Ressource?<br />
This is the Title of the Book, eMatter Edition<br />
| 91<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
sein wie ein Apfel oder ein abstraktes Konzept wie Mut, allerdings ist (wie wir später<br />
sehen werden) die Darstellung solcher Ressourcen meist eher enttäuschend.<br />
Hier ein paar mögliche Ressourcen:<br />
• Version 1.0.3 des Software-Release<br />
• die letzte Version des Software-Release<br />
• der erste Weblog-Eintrag am 24. Oktober 2006<br />
• eine Straßenkarte für Little Rock, Arkansas<br />
• Informationen über Quallen<br />
• ein Verzeichnis mit Ressourcen über Quallen<br />
• die nächstgrößere Primzahl nach 1024<br />
• die nächsten fünf Primzahlen nach 1024<br />
• die Verkaufszahlen für das 4. Quartal 2004<br />
• die Beziehung zwischen Alice und Bob<br />
• eine Liste der offenen Fehler in der Fehlerdatenbank<br />
Links<br />
URIs<br />
Was macht aus einer Ressource eine Ressource? Sie muss mindestens einen URI<br />
haben. Der URI ist der Name und die Adresse einer Ressource. Wenn eine Information<br />
keinen URI hat, ist sie keine Ressource und befindet sich auch nicht wirklich im<br />
Web, höchstens als Datenhäppchen, das andere Ressourcen beschreibt.<br />
Erinnern Sie sich an die Beispielsession in der Einführung, bei der ich ein wenig Spaß<br />
mit HTTP 0.9 hatte? Lassen Sie uns annehmen, das dies ein HTTP-0.9-Request für<br />
http://www.example.com/hello.txt wäre:<br />
Client-Request<br />
GET /hello.txt<br />
Server-Response<br />
Hello, world!<br />
Ein HTTP-Client arbeitet mit einer Ressource, indem er sich mit dem Server verbindet,<br />
der sie hostet (in diesem Fall www.example.com) und dem Server eine Methode<br />
(»GET«) sowie einen Pfad zur Ressource (»/hello.txt«) schickt. Das heutige HTTP 1.<br />
1 ist etwas komplexer als 0.9, funktioniert aber im Prinzip noch genauso. Sowohl der<br />
Server als auch der Pfad kommen aus dem URI der Ressource.<br />
Client-Request<br />
Server-Response<br />
Max.<br />
Linie<br />
GET /hello.txt HTTP/1.1<br />
Host: www.example.com<br />
200 OK<br />
Content-Type: text/plain<br />
Hello, world!<br />
Max.<br />
Linie<br />
92 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
<strong>Die</strong> Prinzipien hinter den URIs sind von Tim Berners-Lee sehr gut in »Universal<br />
Resource Identifiers – Axioms of Web Architecture« beschrieben (http://www.w3.<br />
org/DesignIssues/Axioms). In diesem Abschnitt möchte ich die Prinzipien vorstellen,<br />
die hinter dem Zusammenstellen von URIs und ihrer Zuweisung an Ressourcen stehen.<br />
Max.<br />
Linie<br />
Der URI ist die grundlegende Technologie des Web. Es gab schon<br />
vor HTML Hypertext-Systeme, und Internetprotokolle vor HTTP,<br />
aber sie konnten nicht miteinander sprechen. Der URI verband all<br />
diese Internetprotokolle zu einem Web, so wie TCP/IP die Netzwerke<br />
wie Usenet, Bitnet und CompuServe zu einem Internet vereint<br />
hat. Dann schluckte das Web diese anderen Protokolle und merzte<br />
sie aus, so wie es das Internet mit privaten Netzwerken tat.<br />
Heute surfen wir im Web (und nicht in Gopher), laden Dateien aus<br />
dem Web (und nicht von FTP-Sites), suchen Veröffentlichungen im<br />
Web (und nicht in WAIS) und reden miteinander im Web (und<br />
nicht in Usenet-Newsgroups). Versionsverwaltungssysteme wie Subversion<br />
und arch arbeiten über das Web – im Gegensatz zum CVS-<br />
Protokoll. Selbst E-Mails wandern langsam ins Web.<br />
Das Web merzt alle anderen Protokolle aus, weil es etwas hat, was<br />
den meisten Protokollen fehlt: eine einfache Möglichkeit, jedes verfügbare<br />
Element zu beschriften. Jede Ressource im Web hat mindestens<br />
einen URI. Sie können einen URI auf eine Reklametafel<br />
schreiben. <strong>Die</strong> Leute sehen diese Tafel, geben den URI in ihren Web-<br />
Browser ein und kommen direkt zu der Ressource, die Sie ihnen zeigen<br />
wollten. Es mag seltsam erscheinen, aber diese tagtägliche Interaktion<br />
war nicht möglich, bevor die URIs erfunden wurden.<br />
URIs sollten beschreibend sein<br />
Hier kommt der erste Punkt, bei dem die ROA auf den zurückhaltenden Empfehlungen<br />
des REST-Dokuments und der W3C-Empfehlungen aufbaut. Ich schlage vor,<br />
dass eine Ressource und ihr URI intuitiv zusammenpassen sollten. Hier sind ein paar<br />
gute URIs für die Ressourcen, die ich weiter oben aufgeführt habe:<br />
• http://www.example.com/software/releases/1.0.3.tar.gz<br />
• http://www.example.com/software/releases/latest.tar.gz<br />
• http://www.example.com/weblog/2006/10/24/0<br />
• http://www.example.com/landkarte/strassen/USA/AR/Little_Rock<br />
• http://www.example.com/wiki/Quallen<br />
• http://www.example.com/suche/Quallen<br />
• http://www.example.com/nextprime/1024<br />
• http://www.example.com/next-5-primes/1024<br />
• http://www.example.com/verkaeufe/2004/Q4<br />
Max.<br />
Linie<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008<br />
URIs | 93
• http://www.example.com/beziehungen/Alice;Bob<br />
• http://www.example.com/bugs/nach-zustand/open<br />
URIs sollten eine Struktur haben. Sie sollten vorhersehbar sein. Sie sollten nicht<br />
/suche/Quallen für Quallen und /i-want-to-know-about/Mäuse für Mäuse aufrufen<br />
müssen. Wenn ein Client die Struktur der URIs für die Services kennt, kann er seine<br />
eigenen Einstiegspunkte in den Service aufbauen. Das erleichtert es den Clients,<br />
Ihren Service auf Arten zu nutzen, die Sie gar nicht berücksichtigt haben.<br />
Das ist keine uneingeschränkt gültige Regel, wie wir im Abschnitt »Benennen der<br />
Ressourcen« auf Seite 133 sehen werden. URIs müssen technisch gesehen überhaupt<br />
keine Struktur haben oder vorhersehbar sein, aber ich denke, sie sollten es. <strong>Die</strong>s ist<br />
eine der Regeln guten Web-Designs, und sie zeigt sich sowohl bei REST-konformen<br />
als auch bei REST-RPC-Hybrid-Web Services.<br />
Links<br />
Max.<br />
Linie<br />
<strong>Die</strong> Beziehung zwischen URIs und Ressourcen<br />
Lassen Sie uns ein paar Grenzfälle betrachten. Können zwei Ressourcen gleich sein?<br />
Können zwei URIs die gleiche Ressource ansprechen? Kann ein einzelner URI zwei<br />
Ressourcen ansprechen?<br />
Per Definition können keine zwei Ressourcen gleich sein. Wenn sie es wären, wären<br />
Sie nur eine Ressource. Allerdings kann es Zeitenabschnitte geben, in denen zwei<br />
verschiedene Ressourcen auf die gleichen Daten verweisen. Wenn das aktuelle<br />
Software-Release die Version 1.0.3 ist, werden http://www.example.com/software/releases/1.0.3.tar.gz<br />
und http://www.example.com/software/releases/latest.tar.gz eine<br />
Zeit lang auf dieselbe Datei verweisen. Aber die Ideen hinter diesen beiden URIs sind<br />
verschieden: Eine wird immer auf eine bestimmte Version zeigen, während die<br />
andere auf das zeigt, was zum Zeitpunkt des Zugriffs die neueste Version ist. Das<br />
sind zwei Konzepte und zwei Ressourcen. Sie werden nicht auf latest verweisen,<br />
wenn Sie einen Fehler in Version 1.0.3 melden.<br />
Eine Ressource kann einen oder mehrere URIs haben. <strong>Die</strong> Verkaufszahlen, die unter<br />
http://www.example.com/sales/2004/Q4 verfügbar sind, lassen sich vielleicht auch<br />
über http://www.example.com/sales/Q42004 abrufen. Wenn eine Ressource mehrere<br />
URIs hat, ist es einfacher für die Clients, darauf zu verweisen. Als Nachteil mindert<br />
jeder weitere URI den Wert aller anderen. Manche Clients verwenden einen URI,<br />
manche einen anderen, und es gibt keine automatische Möglichkeit, zu überprüfen,<br />
ob all diese URIs auf die gleiche Ressource verweisen.<br />
Eine Möglichkeit, dies zu umgehen, ist es, mehrere URIs für die gleiche<br />
Ressource bereitzustellen, aber nur einen von ihnen als »kanonischen«<br />
URI für diese Ressource festzulegen. Wenn ein Client den<br />
kanonischen URI anfordert, schickt der Server die entsprechenden<br />
Daten zusammen mit dem Responsecode 200 (»OK«) zurück. For-<br />
Max.<br />
Linie<br />
94 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
dert ein Client einen der anderen URIs an, sendet der Server den<br />
Responsecode 303 (»See also«) zusammen mit dem kanonischen<br />
URI. Der Client kann nicht feststellen, ob zwei URIs auf die gleiche<br />
Ressource zeigen, aber er kann zwei HEAD-Requests abschicken und<br />
kontrollieren, ob ein URI zum anderen weiterleitet oder ob beide zu<br />
einem dritten URI verweisen.<br />
Man kann auch alle URIs gleich behandeln, aber der »kanonische«<br />
URI im Response-Header Content-Location immer dann angeben,<br />
wenn ein Request einen nicht kanonische URI anfordert.<br />
Max.<br />
Linie<br />
Der Aufruf von sales/2004/Q4 bringt Ihnen vielleicht den gleichen Bytestream wie<br />
sales/Q42004, da es sich um verschiedene URIs für dieselbe Ressource handelt:<br />
»Verkäufe im letzten Quartal 2004«. Der Aufruf von releases/1.0.3.tar.gz führt<br />
vielleicht zum selben Bytestream wie releases/latest.tar.gz, aber es handelt sich<br />
um unterschiedliche Ressourcen, die verschiedene Dinge repräsentieren: »Version<br />
1.0.3« und »die letzte Version«.<br />
Jeder URI bezeichnet exakt eine Ressource. Wenn er für mehr als eine Ressource<br />
stünde, wäre er kein Universal Resource Identifier. Aber wenn Sie einen URI<br />
abfragen, wird Ihnen der Server vielleicht Informationen über mehrere Ressourcen<br />
liefern: die eine, die Sie angefordert haben, und andere, die dazu in Beziehung stehen.<br />
Wenn Sie eine Web-Seite holen wollen, enthält diese normalerweise Informationen<br />
über sich selbst, aber auch Verweise auf andere Web-Seiten. Wenn Sie ein S3-<br />
Bucket mit einem Client für Amazons S3 laden, erhalten Sie ein Dokument, das<br />
Informationen über das Bucket, aber auch über dazu in Beziehung stehende<br />
Ressourcen enthält: die Objekte im Bucket.<br />
Adressierbarkeit<br />
Nachdem ich nun Ressourcen und ihre URIs eingeführt habe, kann ich zwei Features<br />
der ROA detaillierter behandeln: Adressierbarkeit und Zustandslosigkeit.<br />
Eine Anwendung ist dann adressierbar, wenn sie die interessanten Aspekte ihrer<br />
Daten als Ressourcen bereitstellt. Da Ressourcen durch URIs zur Verfügung gestellt<br />
werden, bietet eine adressierbare Anwendung eines URI für jedes Informationselement<br />
an, das sie eventuell herausgeben könnte. Das ist normalerweise eine<br />
unendlich große Zahl von URIs.<br />
Aus Sicht des Endanwenders ist die Adressierbarkeit der wichtigste Aspekt jeder<br />
Web-Site und Web-Anwendung. Benutzer sind schlau und ignorieren oder umgehen<br />
so gut wie jede Einschränkung, wenn die Daten nur interessant genug sind – aber es<br />
ist sehr schwer, fehlende Adressierbarkeit zu umgehen.<br />
Stellen Sie sich einen realen URI für eine Ressource »Verzeichnis der Ressourcen zu<br />
Quallen« http://www.google.com/search?q=Qualle vor. <strong>Die</strong>se Suche nach Quallen ist<br />
Max.<br />
Linie<br />
Adressierbarkeit | 95<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
genauso real wie der URI http://www.google.com. Wenn HTTP nicht adressierbar<br />
oder die Such-Engine von Google keine adressierbare Web-Anwendung wäre,<br />
könnte ich diesen URI nicht in einem Buch veröffentlichen. Ich müsste Ihnen Folgendes<br />
erzählen: »Öffnen Sie eine Web-Verbindung zu google.com, geben Sie im<br />
Suchfeld ›Qualle‹ ein und klicken Sie dann auf den Button ›Google Search‹.«<br />
Links<br />
Das ist keine rein akademische Sorge. Bis Mitte der 90er Jahre, als<br />
URIs mit ftp:// beliebt wurden, um Dateien auf FTP-Sites zu<br />
beschreiben, mussten die Leute so ähnlich vorgehen: »Öffne eine<br />
anonyme FTP-Session auf ftp.example.com. Dann wechsle in das<br />
Verzeichnis pub/files/ und lade die Datei file.txt herunter.« URIs<br />
ermöglichten es, FTP genauso adressierbar zu machen wie HTTP.<br />
Jetzt schreiben die Leute einfach: »Lade die Datei ftp://ftp.example.<br />
com/pub/files/file.txt herunter.« <strong>Die</strong> Schritte sind die gleichen, sie<br />
können jetzt aber von einem Rechner durchgeführt werden.<br />
Max.<br />
Linie<br />
Aber HTTP und Google sind beide adressierbar, daher kann ich diesen URI in einem<br />
Buch angeben. Sie können sie lesen und eintippen. Wenn Sie das tun, landen Sie<br />
dort, wo ich auch war, als ich mit der Web-Anwendung von Google gearbeitet habe.<br />
Sie können dann diese Seite als Lesezeichen ablegen und sie später wieder besuchen.<br />
Sie können auf einer eigenen Web-Seite darauf verweisen. Sie können den URI an<br />
jemand anderen mailen. Wenn HTTP nicht adressierbar wäre, müssten Sie die ganze<br />
Seite herunterladen und die HTML-Datei als Anhang mitschicken.<br />
Um Bandbreite zu sparen, können Sie einen HTTP-Proxy-Cache in Ihrem lokalen<br />
Netzwerk einrichten. Wenn jemand das erste Mal http://www.google.com/<br />
search?q=Qualle anfordert, speichert der Cache eine lokale Kopie des Dokuments.<br />
Wenn das nächste Mal jemand diesen URI eingibt, kann der Cache seine gespeicherte<br />
Kopie übermitteln, anstatt sie erneut herunterzuladen. All das ist nur möglich,<br />
wenn jede Seite einen eindeutigen String als Kennzeichen hat: eine Adresse.<br />
Es ist sogar möglich, URIs zu verketten, also einen URI als Eingabe für einen anderen<br />
zu verwenden. Sie können einen externen Web Service nutzen, um den HTML-Code<br />
einer Seite zu validieren, oder um den auf der Seite enthaltenen Text in eine andere<br />
Sprache zu übersetzen. <strong>Die</strong>se Web Services erwarten einen URI als Eingabe. Wenn<br />
HTTP nicht adressierbar wäre, hätten Sie keine Möglichkeit, ihnen mitzuteilen, mit<br />
welcher Ressource sie arbeiten sollen.<br />
Der S3-Service von Amazon ist adressierbar, weil jedes Bucket und jedes Objekt<br />
seinen eigenen URI besitzt, so wie auch die Bucket-Liste. Buckets und Objekte, die<br />
noch nicht existieren, sind noch keine Ressourcen, aber auch sie haben ihre eigenen<br />
URIs: Sie können eine Ressource erzeugen, indem Sie einen PUT-Request an ihren<br />
URI schicken.<br />
Das Dateisystem auf Ihrem eigenen Computer ist ein weiteres adressierbares System.<br />
Anwendungen an der Befehlszeile können einen Pfad zu einer Datei übernehmen<br />
Max.<br />
Linie<br />
96 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
und dann lustige Dinge damit anstellen. <strong>Die</strong> Felder in einer Tabellenkalkulation sind<br />
ebenfalls adressierbar – sie können den Namen eines Felds in eine Formel stecken,<br />
die dann den aktuellen Wert dieses Felds nutzen wird. URIs sind die Dateipfade und<br />
Feldadressen des Web.<br />
Adressierbarkeit ist eine der besten Eigenschaften von Web-Anwendungen. Sie erleichtert<br />
es Clients, Web-Sites anders zu nutzen, als sich das die ursprünglichen<br />
Designer überlegt hatten. Folgen Sie dieser einen Regel, bringt REST Ihnen und<br />
Ihren Anwendern viele Vorteile. Das ist der Grund, warum REST-RPC-Services so<br />
verbreitet sind: Sie kombinieren Adressierbarkeit mit dem Programmiermodell, in<br />
dem Prozeduren aufgerufen werden. Das ist der Grund, warum ich die Ressourcen<br />
so prominent in »<strong>ressourcenorientierte</strong>r <strong>Architektur</strong>« stehen habe: weil sie die<br />
Dinger sind, die sich adressieren lassen.<br />
Das scheint ganz natürlich zu sein – die Art und Weise, wie das Web funktionieren<br />
sollte. Leider arbeiten viele Web-Anwendungen aber nicht so. Das gilt insbesondere<br />
für Ajax-Anwendungen. Wie ich in Kapitel 11 zeigen werden, sind die meisten Ajax-<br />
Anwendungen nur Clients für REST-konforme oder hybride Web Services. Aber<br />
wenn Sie diese Clients so nutzen, als ob es Web-Sites wären, werden Sie feststellen,<br />
dass sie sich nicht wie Web-Sites anfühlen.<br />
Lassen Sie uns nicht weiter darauf herumhacken, sondern unsere Reise zu den Google-Anwendungen<br />
fortführen, indem wir uns den Online-E-Mail-Service Google Mail<br />
anschauen. Aus Sicht des Endandwenders gibt es nur einen URI für Google Mail:<br />
https://mail.google.com/. Was auch immer Sie tun, welche Daten Sie auch von Google<br />
Mail laden oder dort ablegen – Sie werden niemals einen anderen URI zu Gesicht<br />
bekommen. <strong>Die</strong> Ressource »E-Mails zu Quallen« ist nicht adressierbar, wogegen es<br />
die »Web-Seiten über Quallen« von Google sind. 3 Aber wie ich in Kapitel 11 zeige,<br />
gibt es eine Web-Site, die adressierbar ist. <strong>Die</strong> Liste der E-Mails zum Thema Quallen<br />
hat einen URI: https://mail.google.com/mail/?q=Quallen&search=query&view=tl. Das<br />
Problem ist, dass Sie kein Benutzer dieser Web-Site sind. <strong>Die</strong> Site ist in Wirklichkeit<br />
ein Web Service, und der eigentliche Empfänger ist ein JavaScript-Programm, das<br />
innerhalb Ihres Web-Browsers läuft. 4 Der Web Service von Google Mail ist adressierbar,<br />
aber die Web-Anwendung von Google, die ihn nutzt, ist es nicht.<br />
Max.<br />
Linie<br />
3 Vergleichen Sie die Ajax-Schnittstelle mit der besser adressierbaren Version von Google Mail, die Sie<br />
erhalten, wenn Sie die Anwendung mit dem URI https://mail.google.com/mail/?ui=html aufrufen. Bei<br />
dieser Schnittstelle in klassischem HTML ist die Ressource »E-Mails zum Thema Quallen« adressierbar.<br />
4 Andere Konsumenten dieses Web Services nutzen die Bibliothek libgmail für Python (http://libgmail.<br />
sourceforge.net/).<br />
Max.<br />
Linie<br />
Adressierbarkeit | 97<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Max.<br />
Linie<br />
Zustandslosigkeit<br />
Adressierbarkeit ist eines der vier Hauptfeatures der ROA. Das zweite ist die<br />
Zustandslosigkeit. Ich werde Ihnen zwei Definitionen von Zustandslosigkeit geben:<br />
eine allgemeinere und eine praktischere, die zur ROA passt.<br />
Zustandslosigkeit bedeutet, dass jeder HTTP-Request in vollständiger Isolation<br />
geschieht. Wenn der Client einen HTTP-Request abschickt, enthält dieser alle Informationen,<br />
die für den Server notwendig sind, um die Anfrage zu erfüllen. Der Server<br />
verlässt sich niemals auf Informationen aus früheren Requests. Wenn solche Informationen<br />
wichtig gewesen wären, hätte der Client sie mit dem aktuellen Request<br />
erneut mitgeschickt.<br />
Wenn Sie das Ganze praktischer betrachten, stellen Sie sich die Zustandslosigkeit in<br />
Begriffen der Adressierbarkeit vor. Adressierbarkeit besagt, dass jede interessante<br />
Information, die der Server zur Verfügung stellen kann, auch als Ressource bereitstehen<br />
sollte und ihren eigenen URI bekommt. Zustandslosigkeit besagt, dass die<br />
möglichen Zustände des Servers ebenfalls Ressourcen sind und ebenso ihre eigenen<br />
URIs bekommen sollten. Der Client sollte den Server nicht in einen bestimmten<br />
Zustand zwingen müssen, damit er für eine bestimmte Anfrage empfänglich ist.<br />
Im menschlichen Web sehen Sie sich häufig Situationen gegenüber, in denen der<br />
»Zurück«-Button Ihres Browsers nicht richtig funktioniert und Sie in Ihrem Browser-<br />
Verlauf nicht vor- und zurückgehen können. Manchmal liegt das daran, dass Sie eine<br />
unwiderrufliche Aktion ausgelöst haben, wie zum Beispiel einen Weblog-Eintrag zu<br />
veröffentlichen oder ein Buch zu kaufen, aber häufig ist der Grund schlicht, dass eine<br />
Web-Site die Prinzipien der Zustandslosigkeit verletzt. Solch eine Site erwartet, dass<br />
Sie Anfragen in einer bestimmten Reihenfolge abschicken: A, B und dann C. Sie gerät<br />
durcheinander, wenn Sie Anfrage B ein zweites Mal abschicken, anstatt mit Anfrage<br />
C fortzufahren.<br />
Lassen Sie uns nochmals das Suchbeispiel nehmen. Eine Such-Engine ist ein Web<br />
Service mit einer unendlichen Zahl möglicher Zustände: Es gibt mindestens einen für<br />
jeden String, nach dem Sie suchen. Jeder Zustand hat seinen eigenen URI. Sie können<br />
den Service nach einem Verzeichnis mit Ressourcen über Mäuse fragen: http://<br />
www.google.com/search?q=M%E4use. Sie können nach einem Verzeichnis mit<br />
Ressourcen über Quallen fragen: http://www.google.com/search?q=Quallen. Wenn<br />
Sie sich nicht sicher sind, wie man einen URI vollständig selber erstellt, können Sie<br />
den Service nach einem Formular dafür fragen: http://www.google.com/.<br />
Wenn Sie nach einem Verzeichnis der Ressourcen zu Mäusen oder Quallen fragen,<br />
erhalten Sie nicht das gesamte Verzeichnis. Sie bekommen eine einzelne Seite des<br />
Verzeichnisses: eine Liste mit (zum Beispiel) zehn Ressourcen, die nach Ansicht der<br />
Such-Engine Ihre Anfrage am Besten beantworten. Um mehr zu bekommen, müssen<br />
Sie zusätzliche HTTP-Requests absetzen. <strong>Die</strong> zweite und die folgenden Seiten sind<br />
Links<br />
Max.<br />
Linie<br />
98 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
eigene Zustände der Anwendung und müssen ihre eigenen URIs haben, zum Beispiel<br />
http://www.google.com/search?q=Quallen&start=10. Wie bei jeder adressierbaren<br />
Ressource können Sie diesen Zustand der Anwendung an jemand anderen übermitteln,<br />
ihn zwischenspeichern oder zu Ihren Lesezeichen stecken und später dorthin<br />
zurückkehren.<br />
Abbildung 4-1 ist ein einfaches Zustandsdiagramm, das zeigt, wie ein HTTP-Client<br />
mit vier Zuständen einer Such-Engine interagieren könnte.<br />
Such-Formular<br />
“Quallen”<br />
Request<br />
Request<br />
Response<br />
Response<br />
Response<br />
Initialer Zustand<br />
“Mäuse”,<br />
Seite 2<br />
Request<br />
Response<br />
“Mäuse”<br />
Request<br />
Abbildung 4-1: Eine zustandslose Such-Engine<br />
<strong>Die</strong>s ist eine zustandslose Anwendung, weil bei jedem Zugriff, den ein Client tätigt,<br />
wieder von vorn angefangen wird. Jeder Request ist völlig unabhängig von den<br />
anderen. Der Client kann Anfragen an diese Ressourcen beliebig häufig vornehmen<br />
und in beliebiger Reihenfolge. Er kann Seite 2 über »Mäuse« aufrufen, bevor er Seite<br />
1 anfordert (oder Seite 1 völlig ignorieren) – den Server wird es nicht kümmern.<br />
Im totalen Gegensatz dazu zeigt Abbildung 4-2 die gleichen Zustände, nun zustandsbehaftet<br />
angeordnet, wobei die Zustände sinnvoll ineinander übergehen können.<br />
<strong>Die</strong> meisten Desktop-Anwendungen sind so entworfen.<br />
Initialer Zustand<br />
Such-Formular<br />
“Mäuse”<br />
“Quallen”<br />
Max.<br />
Linie<br />
Abbildung 4-2: Eine zustandsbehaftete Such-Engine<br />
“Mäuse”,<br />
Seite 2<br />
Max.<br />
Linie<br />
Zustandslosigkeit | 99<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Max.<br />
Linie<br />
Das ist deutlich besser organisiert, und wenn HTTP so entworfen wäre, dass es<br />
zustandsbehaftete Interaktionen zulassen würde, könnten HTTP-Requests deutlich<br />
einfacher sein. Wenn der Client eine Session mit der Such-Engine starten würde,<br />
könnte er automatisch das Suchformular ausfüllen. Er müsste keinerlei Request-<br />
Daten schicken, da die erste Response vorherbestimmt wäre. Wenn der Client sich<br />
die ersten zehn Einträge im Mäuse-Verzeichnis angeschaut hätte und nun die Einträge<br />
11–20 sehen wollte, müsste er nur einen Request mit dem Inhalt »start=10«<br />
schicken. Er müsste nicht nach /search?q=mice&start=10 fragen und damit die initialen<br />
Vorgaben wiederholen: »Ich suche, und zwar speziell nach Mäusen.«<br />
Genau so funktioniert FTP: Es kennt ein »Arbeitsverzeichnis«, das während der gesamten<br />
Sitzung konstant bleibt, sofern Sie es nicht ändern. Sie können sich an einem<br />
FTP-Server anmelden, per cd zu einem bestimmten Verzeichnis wechseln und per<br />
get eine Datei aus diesem Verzeichnis holen. Dann nutzen Sie get erneut für eine<br />
andere Datei aus demselben Verzeichnis, ohne einen zweiten cd-Befehl ausführen zu<br />
müssen. Warum unterstützt HTTP das nicht?<br />
Zustände würden einzelne HTTP-Anfragen vereinfachen, aber das HTTP-Protokoll<br />
deutlich verkomplizieren. Ein FTP-Client ist weitaus komplizierter als ein HTTP-<br />
Client, und zwar genau aus dem Grund, dass der Session-Zustand zwischen Client<br />
und Server synchron gehalten werden muss. Das ist eine komplexe Aufgabe selbst in<br />
einem stabilen Netzwerk, was das Internet definitiv nicht ist.<br />
Eliminiert man den Zustand aus einem Protokoll, eliminiert man auch eine Reihe<br />
von Fehlerquellen. Der Server muss sich keine Sorgen um das Timeout eines Clients<br />
machen, da keine Interaktion länger als ein einzelner Request dauert. Der Server verliert<br />
nie die Übersicht darüber, »wo« sich jeder Client in der Anwendung befindet, da<br />
der Client alle notwendigen Informationen mit jeder Anfrage mitschickt. Der Client<br />
führt nie eine Aktion im falschen »Arbeitsverzeichnis« aus, nur weil der Server einen<br />
Zustand geändert hat, ohne es dem Client zu erzählen.<br />
Zustandslosigkeit bringt auch neue Features mit. Es ist einfacher, eine zustandslose<br />
Anwendung zum Lastausgleich auf mehrere Server zu verteilen. Da keine zwei<br />
Requests voneinander abhängig sind, können sie von zwei verschiedenen Servern<br />
verarbeitet werden, die sich nicht gegenseitig koordinieren müssen. Skalieren ist einfach:<br />
Man muss dem Load Balancer nur weitere Server hinzufügen. Eine zustandslose<br />
Anwendung lässt sich auch einfach cachen: Eine Software kann entscheiden, ob<br />
die Ergebnisse eines HTTP-Request gecachet werden können, indem nur der<br />
entsprechende Request angeschaut wird. Es gibt keine quälende Unsicherheit, ob<br />
der Zustand aus einer vorigen Anfrage die Cachebarkeit der aktuellen Anfrage beeinflusst.<br />
Der Client zieht aus der Zustandslosigkeit ebenfalls Vorteile. Ein Client kann das<br />
Mäuse-Verzeichnis ab Seite 50 verarbeiten, ein Lesezeichen für /search?q=<br />
Mäuse&start=500 speichern und eine Woche später wiederkommen, ohne sich durch<br />
Dutzende von vorigen Zuständen durcharbeiten zu müssen. Ein URI, der mitten<br />
Links<br />
Max.<br />
Linie<br />
100 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Max.<br />
Linie<br />
während einer langen HTTP-Sitzung abgesetzt wird, funktioniert genauso, als ob er als<br />
erster URI in einer neuen Session angefragt wird.<br />
Um Ihren Service adressierbar zu machen, müssen Sie ein wenig Aufwand treiben<br />
und die Daten Ihrer Anwendung in Ressourcen aufteilen. HTTP ist schon an sich ein<br />
zustandsloses Protokoll, daher erhalten Sie die Zustandslosigkeit automatisch, wenn<br />
Sie Web Services schreiben. Um das zu ändern, müssen Sie etwas tun.<br />
Um die Zustandslosigkeit aufzuheben, nutzen Sie am besten HTTP-Sessions, die von<br />
Ihrem Framework unterstützt werden. Sobald sich ein Benutzer auf Ihre Seiten begibt,<br />
erhält er einen eindeutigen String, der seine Session auf der Site identifiziert.<br />
Der String kann sich in einem Cookie befinden, oder die Site reicht den String in<br />
allen URIs weiter, die sie einem bestimmten Client zur Verfügung stellt. So sieht ein<br />
Session-Cookie aus, das von einer Rails-Anwendung gesetzt wurde:<br />
Set-Cookie: _session_id=c1c934bbe6168dcb904d21a7f5644a2d; path=/<br />
<strong>Die</strong>ser URI gibt die Session-ID in einer PHP-Anwendung weiter: http://www.example.com/forums?PHPSESSID=27314962133.<br />
Wichtig zu beachten ist dabei, das unsinnige hexadezimale oder dezimale Zahlen<br />
kein Zustand sind. Es handelt sich um einen Schlüssel zu einer Datenstruktur auf<br />
dem Server, und diese Datenstruktur enthält den Zustand. An zustandsbehafteten<br />
URIs gibt es nichts, was REST widerspricht: So kommuniziert der Server mögliche<br />
nächste Zustände an den Client weiter. (Aber Cookies sind nicht REST-konform,<br />
wie ich in Abschnitt »Ärger mit Cookies« auf Seite 286 besprechen werde. Um eine<br />
Web-Browser-Analogie zu verwenden: Cookies machen den »Zurück«-Button in<br />
einem Client für einen Web Service kaputt.)<br />
Betrachten Sie einmal die Query-Variable start=10 in einem URI, der in einer<br />
HTML-Seite eingebettet ist, die durch die Such-Engine von Google ausgeliefert<br />
wurde. Damit schickt der Server einen möglichen nächsten Zustand an den Client.<br />
Aber solche URIs müssen den Zustand enthalten und nicht nur einen Schlüssel zu<br />
einem Zustand liefern, der auf dem Server abgelegt ist. start=10 hat von sich aus<br />
Bedeutung, was bei PHPSESSID=27314962133 nicht der Fall ist. REST-konform zu sein<br />
erfordert, dass der Zustand auf Client-Seite vorhanden bleibt und an den Server bei<br />
jedem Request geschickt wird, der dies erfordert. Der Server kann den Client zu<br />
neuen Zuständen drängen, indem er zustandsbehaftete Verweise schickt, denen der<br />
Client folgen kann, aber er kann den Status nicht selber verwalten.<br />
Anwendungszustand vs. Ressourcen-Zustand<br />
Wenn wir uns über »Zustandslosigkeit« unterhalten, müssen wir uns fragen, was ein<br />
»Zustand« ist. Was ist der Unterschied zwischen persistenten Daten, also den nützlichen<br />
Daten auf Serverseite, wegen derer wir den Web Service vor allem nutzen, und<br />
diesem Zustand, den wir vom Server fern halten wollen? Der Flickr-Web Service lässt<br />
Max.<br />
Linie<br />
Zustandslosigkeit | 101<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Max.<br />
Linie<br />
Sie Bilder auf Ihr Konto hochladen, die dann auf dem Server gespeichert werden. Es<br />
wäre verrückt, den Client jedes seiner Bilder zusammen mit jedem Request an<br />
flickr.com schicken zu lassen, nur um den Server davon abzuhalten, irgendeinen<br />
Zustand speichern zu müssen. Das würde den ganzen Service ad absurdum führen.<br />
Aber was ist dann der Unterschied zwischen diesem Szenario und dem Zustand der<br />
Client-Session, von dem ich fordere, dass er vom Server fernbleibt?<br />
Das Problem liegt in der Terminologie. Zustandslosigkeit impliziert, dass es nur eine<br />
Art von Zustand gibt und dass der Server sich davon fernhalten sollte. Tatsächlich<br />
gibt es zwei Zustandsarten. Ich werde in diesem Buch von nun an zwischen dem<br />
Anwendungszustand, der auf dem Client, und dem Ressourcen-Zustand, der auf dem<br />
Server verwaltet werden sollte, unterscheiden.<br />
Wenn Sie eine Such-Engine verwenden, sind Ihre aktuelle Abfrage und die aktuelle<br />
Seite Teile des Anwendungszustands. <strong>Die</strong>ser Zustand unterscheidet sich für jeden<br />
Client. Sie können sich auf Seite 3 der Suchergebnisse für »Quallen« befinden,<br />
während ich mich auf Seite 1 der Suchergebnisse für »Mäuse« tummle. <strong>Die</strong> Seitennummer<br />
und die Abfrage sind verschieden, da wir unterschiedliche Pfade in der<br />
Anwendung eingeschlagen haben. Unsere jeweiligen Clients verwalten unterschiedliche<br />
Anwendungszustände.<br />
Ein Web Service muss sich nur dann um Ihren Anwendungszustand kümmern,<br />
wenn Sie tatsächlich einen Request stellen. Den Rest der Zeit weiß er nicht einmal,<br />
dass Sie existieren. Das bedeutet, dass immer dann, wenn ein Client einen Request<br />
absetzt, dieser alle Anwendungszustände enthält, die der Server benötigt, um die<br />
Anfrage zu verarbeiten. Es kann sein, dass der Server eine Seite mit Verweisen<br />
zurückschickt, die den Client über andere Requests informieren, die er in Zukunft<br />
stellen könnte. Aber danach kann er wieder alles vergessen, was er über den Client<br />
weiß, bis dieser die nächste Anfrage stellt. Das meine ich, wenn ich sage, dass ein<br />
Web Service »zustandslos« sein sollte. Der Client sollte dafür verantwortlich sein,<br />
seinen eigenen Weg durch die Anwendung selbst zu verwalten.<br />
Der Ressourcen-Zustand ist für jeden Client gleich, und sein Platz ist auf dem Server.<br />
Wenn Sie ein Bild in Flickr hochladen, erzeugen Sie eine neue Ressource: Das neue<br />
Bild hat seinen eigenen URI und kann das Ziel zukünftiger Requests sein. Sie können<br />
die Ressource »Bild« per HTTP laden, verändern und löschen. Jeder kann das tun.<br />
Das Bild ist ein Teil des Ressourcen-Zustands und bleibt auf dem Server, bis ein<br />
Client es löscht.<br />
Der Client-Zustand kann an Stellen auftauchen, an denen Sie ihn nicht erwarten<br />
würden. Viele Web Services wollen eine Registrierung, nach der Sie einen eindeutigen<br />
String erhalten (meist als API-Key oder Application Key bezeichnet). Sie<br />
schicken diesen Schlüssel bei jedem Request mit, und der Server verwendet ihn, um<br />
Ihre Anfragen auf eine bestimmte Obergrenze pro Tag einzuschränken. So ist zum<br />
Beispiel ein API Key für Googles auslaufende SOAP-Such-API für 1000 Requests pro<br />
Links<br />
Max.<br />
Linie<br />
102 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Max.<br />
Linie<br />
Tag gut. Das ist ein Anwendungszustand: Er unterscheidet sich für jeden Client.<br />
Nachdem Sie das Limit überschritten haben, ändert sich das Verhalten des Service<br />
drastisch: Bei Anfrage 1000 erhalten Sie Ihre Daten, bei Anfrage 1001 nur eine<br />
Fehlermeldung. Im Moment bin ich bei Anfrage 402, und der Service funktioniert für<br />
mich klasse.<br />
Natürlich kann man Clients nicht vertrauen, dieses Element des Anwendungszustands<br />
selbst zu verwalten: <strong>Die</strong> Versuchung zu schummeln, ist zu groß. Daher<br />
behalten Server diese Art von Anwendungszustand bei sich und verletzen damit das<br />
Prinzip der Zustandslosigkeit. Der API Key ist wie das Rails-Cookie _session_id ein<br />
Schlüssel für eine Client-Session auf Server-Seite, die einen Tag anhält. Das ist soweit<br />
vertretbar, man muss aber bei der Skalierbarkeit einen Preis dafür zahlen. Wenn der<br />
Service über mehrere Maschinen verteilt wird, muss jeder Rechner im Cluster wissen,<br />
dass Sie schon Request 1001 geschickt haben, während ich noch bei Nummer<br />
402 bin (der technische Begriff dafür ist die Session Replication), so dass jede<br />
Maschine weiß, dass sie Ihren Zugriff abblocken und meinen bearbeiten soll. Alternativ<br />
dazu muss der Load Balancer sicherstellen, dass jeder Ihrer Requests auf der<br />
gleichen Maschine im Cluster verarbeitet wird (Session Affinity). Durch Zustandslosigkeit<br />
entfällt diese Anforderung. Als Servicedesigner müssen Sie über Datenreplikation<br />
nur nachdenken, wenn Ihr Ressourcen-Zustand über mehrere Rechner<br />
verteilt werden muss.<br />
Repräsentationen<br />
Wenn Sie Ihre Anwendung in Ressourcen aufteilen, vergrößern Sie den Bereich, der<br />
nach außen hin sichtbar ist. Ihre Anwender können sich passende URIs bauen und in<br />
Ihre Anwendung genau dort einsteigen, wo sie es brauchen. Aber die Ressourcen<br />
sind nicht die Daten, sondern nur die Idee des Servicedesigners, wie die Daten in<br />
»eine Liste offener Bugs« oder »Informationen über Quallen« unterteilt werden. Ein<br />
Web-Server kann keine Ideen senden, er muss eine Abfolge von Bytes in einem<br />
bestimmten Dateiformat und einer bestimmten Sprache schicken. Das ist eine<br />
Repräsentation der Ressource.<br />
Eine Ressource ist eine Quelle für Repräsentationen, und eine Repräsentation<br />
besteht einfach aus Daten zum aktuellen Zustand einer Ressource. <strong>Die</strong> meisten Ressourcen<br />
sind selbst Daten (wie zum Beispiel eine Liste mit Fehlern), daher sind die<br />
Daten selbst eine offensichtliche Repräsentation einer Ressource. Der Server kann<br />
eine Liste mit ungelösten Fehlern als XML-Dokument, als Web-Seite oder als kommaseparierten<br />
Text ausgeben. <strong>Die</strong> Verkaufszahlen für das letzte Quartal 2004 können<br />
numerisch oder als Diagramm ausgegeben werden. Viele News-Sites stellen ihre<br />
Artikel in einem mit Werbung gespickten Format und in einem »druckerfreundlichen«<br />
reduzierten Format bereit. Es handelt sich immer um verschiedene Repräsentationen<br />
der gleichen Ressourcen.<br />
Max.<br />
Linie<br />
Repräsentationen | 103<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Aber manche Ressourcen repräsentieren physikalische Objekte oder andere Dinge,<br />
die nicht auf Informationen reduziert werden können. Was kann man da als gute<br />
Repräsentation verwenden? Sie müssen sich keine Sorgen um eine perfekte Widergabe<br />
machen: Eine Repräsentation ist jede nützliche Information über den Zustand<br />
einer Ressource.<br />
Stellen Sie sich ein physikalisches Objekt vor – z.B. einen Getränkeautomaten –, der<br />
mit einem Web Service verbunden ist. 5 Ziel ist, den Nutzern des Automaten<br />
unnötige Wege dorthin zu ersparen. Durch diesen Service können die Leute wissen,<br />
ob die Getränke kalt sind oder die bevorzugte Marke ausverkauft. Keiner erwartet,<br />
dass die realen Getränkedosen über den Web Service zur Verfügung stehen, da physische<br />
Objekte keine Daten sind. Aber es gibt Daten über sie: Metadaten. Jeder<br />
Schacht im Automaten kann mit einem Kästchen versehen werden, das über die<br />
Sorte, den Preis und die Temperatur der nächsten verfügbaren Dose Bescheid weiß.<br />
<strong>Die</strong> Metadaten dieser Geräte können in den Repräsentationen der Ressourcen verwendet<br />
werden.<br />
Selbst wenn eine der Repräsentationen eines Objekts die eigentlichen Daten enthält,<br />
kann es auch Repräsentationen geben, in denen sich Metadaten finden. Eine<br />
Onlinebuchhandlung kann zum Beispiel zwei Repräsentationen eines Buchs bereitstellen:<br />
1. Eine enthält nur Metadaten, wie zum Beispiel ein Bild des Titels und Reviews,<br />
mit denen das Buch beworben wird.<br />
2. Eine elektronische Variante der Daten im Buch, die Sie via HTTP erhalten,<br />
wenn Sie dafür zahlen.<br />
Repräsentationen funktionieren aber auch andersherum. Sie können eine Repräsentation<br />
einer neuen Ressource an den Server schicken, damit dort die Ressource<br />
erzeugt wird. Das geschieht, wenn Sie bei Flickr ein Bild hochladen. Oder Sie können<br />
dem Server eine neue Repräsentation einer bestehenden Ressource zukommen lassen<br />
und dadurch den Server die Ressource ändern lassen, damit sie mit der neuen<br />
Repräsentation im Einklang steht.<br />
Links<br />
Sich zwischen Repräsentationen entscheiden<br />
Wenn ein Server mehrere Repräsentationen einer Ressource anbietet, stellt sich die<br />
Frage, wie er herausfindet, nach welcher der Client fragt. So kann eine Pressemitteilung<br />
zum Beispiel sowohl auf Deutsch als auch auf Englisch veröffentlicht worden<br />
sein. Welche will ein bestimmter Client dann haben?<br />
Max.<br />
Linie<br />
5 <strong>Die</strong> Idee basiert auf dem CMU-Cola-Automaten (http://www.cs.cmu.edu/%7Ecoke/), der viele Jahre lang<br />
»beobachtet« wurde und dessen jeweiliger Status über das Finger-Protokoll abgefragt werden konnte.<br />
Der Automat existiert immer noch, allerdings war der Status <strong>beim</strong> Schreiben dieses Buchs nicht online<br />
abfragbar.<br />
Max.<br />
Linie<br />
104 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Es gibt eine Reihe von Möglichkeiten, das innerhalb der Grenzen von REST herauszufinden.<br />
Der einfachste – und die, die ich für die <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
empfehle – ist ein eigener URI für jede Repräsentation einer Ressource. http://www.<br />
example.com/releases/104.de könnte für die deutsche Repräsentation der Pressemitteilung<br />
stehen und http://www.example.com/releases/104.en für die englische.<br />
Ich empfehle diese Technik für ROA-Anwendungen, weil der URI damit alle Informationen<br />
enthält, die der Server zum Beantworten des Requests benötigt. Der<br />
Nachteil bei der Bereitstellung von mehreren URIs für die gleiche Ressource ist eine<br />
Abschwächung: Leute, die über die Pressemitteilung in verschiedenen Sprachen<br />
reden, scheinen über unterschiedliche Dinge zu sprechen. Sie können das etwas<br />
abmildern, indem Sie den URI http://www.example.com/releases/104 anbieten, mit<br />
dem die Mitteilung in einer übergreifenden Form gemeint ist, unabhängig von einer<br />
Sprache.<br />
Eine Alternative wird als Content Negotiation bezeichnet. In diesem Szenario wird<br />
nur der übergreifende URI http://www.example.com/releases/104 veröffentlicht.<br />
Wenn ein Client einen Request für diesen URI abschickt, enthält er bestimmte<br />
HTTP-Request-Header, die anzeigen, was für eine Art von Repräsentation der Client<br />
akzeptieren wird.<br />
Ihr Web-Browser hat eine Einstellung für die Sprache: Dort können Sie festlegen, in<br />
welcher Sprache die Web-Seiten erscheinen sollen. Der Browser schickt diese Information<br />
mit jedem HTTP-Request im Header Accept-Language mit. Der Server ignoriert<br />
diese Information meist, da der Großteil der Web-Seiten nur in einer Sprache<br />
zur Verfügung steht. Aber es passt genau zu dem, was wir hier versuchen: Repräsentationen<br />
der gleichen Ressource in verschiedenen Sprachen bereitzustellen. Wenn<br />
ein Client http://www.example.com/releases/104 anfordert, kann der Server abhängig<br />
vom Header Accept-Language des Clients entscheiden, ob er die deutsche oder die<br />
englische Repräsentation ausliefert.<br />
<strong>Die</strong> Such-Engine von Google ist ein guter Ort, das auszuprobieren.<br />
Sie können Ihre Suchergebnisse in so gut wie jeder Sprache präsentiert<br />
bekommen, indem Sie die Spracheinstellungen Ihres Browsers<br />
ändern oder die Query-Variable hl in dem URI anpassen (zum Beispiel<br />
hl=tr für türkisch). <strong>Die</strong> Such-Engine unterstützt sowohl Content<br />
Negotiation als auch verschiedene URIs für unterschiedliche<br />
Repräsentationen.<br />
Max.<br />
Linie<br />
Ein Client kann auch den Header Accept setzen, um anzugeben, welches Dateiformat<br />
er für die Repräsentation bevorzugt. Er kann sagen, dass er lieber XHTML als<br />
HTML oder SVG als ein anderes Grafikformat haben möchte.<br />
Der Server kann alle diese Request-Metadaten nutzen, um zu entscheiden, welche<br />
Repräsentation er schickt. Andere mögliche Metadaten dazu sind Bezahlinformationen,<br />
Authentifizierungs-Credentials, der Zeitpunkt des Requests, Caching-<br />
Max.<br />
Linie<br />
Repräsentationen | 105<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Max.<br />
Linie<br />
Anweisungen und selbst die IP-Adresse des Clients. All diese Daten können in die<br />
Entscheidungsfindung des Servers einfließen, welche Daten in der Repräsentation<br />
enthalten sein sollen, welche Sprache und welches Format genutzt wird und sogar,<br />
ob überhaupt eine Repräsentation geschickt oder der Zugriff verweigert wird.<br />
Es ist REST-konform, diese Information in den HTTP-Headern zu speichern, und es<br />
ist auch REST-konform, sie in den URI zu stecken. Ich empfehle, so viele dieser<br />
Informationen wie möglich in den URI zu packen und so wenige wie möglich in die<br />
Metadaten des Requests. Ich denke, URIs sind nützlicher als Metadaten. URIs werden<br />
von Person zu Person und von Programm zu Programm weitergereicht. <strong>Die</strong><br />
Metadaten des Requests gehen dabei aber so gut wie immer verloren.<br />
Ein einfaches Beispiel für dieses Dilemma ist der W3C-HTML-Validator, ein Web<br />
Service, der unter http://validator.w3.org/ zur Verfügung steht. So sieht ein URI zu<br />
einer Ressource auf der Site des W3C aus, ein Validationsreport der deutschen Version<br />
meiner hypothetischen Pressemitteilung: http://validator.w3.org/check?uri=<br />
http%3A%2F%2Fwww.example.com%2Freleases%2F104.de.<br />
So sieht eine andere Ressource aus, ein Validationsreport der englischen Version der<br />
Pressemitteilung: http://validator.w3.org/check?uri=http%3A%2F%2Fwww.example.<br />
com%2Freleases%2F104.en.<br />
Jeder URI in Ihrem Web-Space wird zu einer Ressource in der Web-Anwendung des<br />
W3C, egal ob es zu einer eigenständigen Ressource auf Ihrer Site verweist. Wenn<br />
Ihre Pressemitteilung einen eigenen URI für jede Repräsentation hat, können Sie<br />
zwei Ressourcen vom W3C bekommen: Validationsreporte für die deutsche und die<br />
englische Version der Pressemitteilung.<br />
Aber wenn Sie nur die übergreifende Form des URI herausgeben und beide Repräsentationen<br />
über diesen URI anbieten, können Sie vom W3C nur eine Ressource bekommen.<br />
Das wäre ein Validationsreport für die Standardversion der Pressemitteilung<br />
(vermutlich die deutsche). Sie haben keine Möglichkeit herauszufinden, ob die<br />
englische Repräsentation HTML-Formatierungsfehler enthält. Wenn der Server die<br />
englische Pressemitteilung nicht als eigenen URI bereitstellt, gibt es keine entsprechende<br />
Ressource auf der W3C-Site. Das bedeutet nicht, dass Sie den übergreifenden<br />
URI nicht anbieten sollten – es sollte nur nicht der einzige URI sein, dene Sie nutzen.<br />
Anders als Menschen sind Computerprogramme sehr schlecht im Umgang mit<br />
Repräsentationen, die sie nicht erwarten. Ich denke, dass ein automatisierter Web-<br />
Client so explizit wie möglich sein sollte, wenn er die Repräsentation beschreibt, die er<br />
haben möchte. Das bedeutet so gut wie immer, dass sie in dem URI spezifiziert wird.<br />
Verweise und Verbindungshaftigkeit<br />
Manchmal sind Repräsentationen nicht viel mehr als serialisierte Datenstrukturen.<br />
Sie sind dazu gedacht, ihrer Daten beraubt und dann weggeworfen zu werden. Aber<br />
Links<br />
Max.<br />
Linie<br />
106 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
in den meisten REST-konformen Services sind Repräsentationen Übermedien:<br />
Dokumente, die nicht nur Daten enthalten, sondern auch Verweise auf andere Ressourcen.<br />
Nehmen wir uns wieder das Suchbeispiel vor. Wenn Sie zu Googles Verzeichnis der<br />
Dokumente über Quallen gehen (http://www.google.com/search?q=Quallen), erhalten<br />
Sie ein paar Suchergebnisse und eine Reihe interner Verweise auf andere Seite<br />
des Verzeichnisses. Abbildung 4-3 zeigt einen passenden Ausschnitt aus der Seite.<br />
Teil des Verzeichnisses<br />
Max.<br />
Linie<br />
Abbildung 4-3: Ausschnitt einer Seite mit Suchergebnissen bei Google<br />
Interne Verzeichnis-Verweise<br />
Es gibt hier Daten und Verweise. <strong>Die</strong> Daten sagen aus, dass es irgendwo im Web<br />
irgendetwas gibt, das irgendwer über Quallen geschrieben hat. <strong>Die</strong> Verweise<br />
ermöglichen Ihnen Zugriff auf andere Ressourcen: manche innerhalb des »Web Service«<br />
von Google, andere irgendwo anders im Web:<br />
• <strong>Die</strong> externe Webseite, die sich mit Quallen befasst: http://de.wikipedia.org/wiki/<br />
Qualle. Hauptaufgabe dieses Web Service ist natürlich, solche Verweise zu präsentieren.<br />
• Ein Verweis auf einen von Google bereitgestellten Cache der externen Seite<br />
(der Verweis »Cached«). <strong>Die</strong>se Verweise haben immer lange URIs, die auf<br />
Google-eigene IP-Adressen zeigen, zum Beispiel http://209.85.135.104/search?q<br />
=cache:nZOeteMPBM...<br />
• Ein Verweis auf ein Verzeichnis mit Seiten, von denen Google denkt, dass sie<br />
zu der externen Seite in Beziehung stehen (http://www.google.com/search?hl=<br />
en&q=related:de.wikipedia.org/wiki/Qualle, bezeichnet als »Similar pages«).<br />
Das ist ein weiterer Fall eines Web Service, der einen URI als Eingabewert<br />
nutzt.<br />
• Eine Reihe von Navigationsverweisen, die Sie zu verschiedenen Seiten des<br />
Quallen-Verzeichnisses führen: http://www.google.com/search?q=Quallen&start<br />
=10, http://www.google.com/search?q=Quallen&start=20 und so weiter.<br />
Max.<br />
Linie<br />
Verweise und Verbindungshaftigkeit<br />
This is the Title of the Book, eMatter Edition<br />
| 107<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Max.<br />
Linie<br />
Weiter oben in diesem Kapitel habe ich gezeigt, was passieren könnte, wenn HTTP<br />
ein zustandsbehaftetes Protokoll wie FTP wäre. Abbildung 4-2 zeigt den Weg, den<br />
ein zustandsbehafteter HTTP-Client während einer »Session« mit www.google.com<br />
nehmen könnte. HTTP funktioniert so natürlich nicht, aber die Abbildung zeigt<br />
ganz gut, wie wir das menschliche Web nutzen. Für die Nutzung einer Such-Engine<br />
beginnen wir auf der Homepage, tragen in ein Formular ihren Suchwunsch ein und<br />
klicken dann auf die Verweise, um die verschiedenen Ergebnisseiten zu erhalten. Wir<br />
tippen normalerweise nicht andauernd URIs ein – stattdessen folgen wir Verweisen<br />
und füllen Formulare aus.<br />
Wenn Sie schon vorher etwas über REST gelesen haben, ist Ihnen vielleicht ein<br />
Axiom aus der Dissertation von Fielding über den Weg gelaufen: »Übermedien als<br />
treibende Kraft des Anwendungszustands.« Das Axiom bedeutet, dass der aktuelle<br />
Zustand einer HTTP-»Session« nicht auf dem Server als Ressourcen-Zustand gespeichert,<br />
sondern vom Client als Anwendungszustand verfolgt und durch den Pfad<br />
erzeugt wird, den der Client im Web beschreitet. Der Server leitet den Client auf<br />
seinem Weg, indem er ihm »Übermedien« anbietet: Verweise und Formulare innerhalb<br />
einer Hypertext-Repräsentation.<br />
Der Server schickt dem Client Hilfestellungen, welche Zustände vom aktuellen aus<br />
gut erreicht werden können. Der Verweis »Next« auf http://www.google.com/<br />
search?q=Quallen ist ein Zustandswegweiser: Er zeigt Ihnen, wie Sie vom aktuellen<br />
Zustand zu einem damit verbundenen Zustand kommen. Das eröffnet viele Möglichkeiten.<br />
Ein Dokument, das einen URI enthält, verweist auf einen anderen möglichen<br />
Zustand der Anwendung: »Seite 2«, »Ähnlich wie dieser URI« oder »eine<br />
gecachete Version dieses URI«. Oder es verweist damit auf einen möglichen Zustand<br />
einer völlig anderen Anwendung.<br />
Ich nenne die Möglichkeit,Verweise zu enthalten, Verbindungshaftigkeit. Ein Web<br />
Service ist insoweit verbunden, als Sie den Service in verschiedene Zustände bringen<br />
können, indem Sie einfach Verweisen folgen und Formulare ausfüllen. Den Begriff<br />
»Verbindungshaftigkeit« nutze ich, weil »Übermedien als treibende Kraft des<br />
Anwendungszustands« das Konzept komplizierter klingen lässt als es ist. Ich will nur<br />
sagen, dass Ressourcen in ihren Repräsentationen miteinander verknüpft sein sollen.<br />
Das menschliche Web ist einfach zu nutzen, weil es so gut vernetzt ist. Jeder erfahrenere<br />
Anwender weiß, wie man URIs in die Adressleiste des Browsers eingibt und wie man auf<br />
einer Site herumspringen kann, indem man die URI verändert, aber viele Benutzer surfen<br />
im Web nur von einem einzigen Startpunkt aus: der Homepage des Browsers, die<br />
durch ihren ISP eingerichtet wurde. Das ist deshalb möglich, weil das Web so gut vernetzt<br />
ist. Seiten verweisen aufeinander, selbst über Site-Grenzen hinweg.<br />
<strong>Die</strong> meisten Web Services sind aber nicht einmal intern vernetzt, ganz zu schweigen<br />
von Verbindungen zu anderen Services. Amazon S3 ist ein REST-konformer Web<br />
Service, der adressierbar und zustandslos ist, aber nicht vernetzt. S3-Repräsenta-<br />
Links<br />
Max.<br />
Linie<br />
108 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
tionen enthalten niemals URIs. Um ein S3-Bucket per GET zu erhalten, müssen Sie<br />
die Regeln kennen, wie der URI des Buckets aufgebaut wird. Sie können nicht einfach<br />
per GET die Bucket-Liste holen und dann einem Verweis zu dem Bucket folgen,<br />
das Sie brauchen.<br />
Beispiel 4-1 zeigt eine S3-Bucket-Liste, die ich geändert habe (durch ein zusätzliches<br />
Tag URI), damit sie verbindungsbehaftet ist. Vergleichen Sie das mit Beispiel 3-5, das<br />
kein solches Tag besitzt. Das ist nur eine Möglichkeit, URIs in eine XML-Repräsentation<br />
einzuführen. Wenn Ressourcen besser miteinander verbunden werden, werden<br />
auch die Beziehungen zwischen ihnen offensichtlicher (siehe Abbildung 4-4).<br />
Beispiel 4-1: Eine verbindungshaftige »Liste Ihrer Buckets«<br />
<br />
<br />
<br />
c0363f7260f2f5fcf38d48039f4fb5cab21b060577817310be5170e7774aad70<br />
leonardr28<br />
<br />
<br />
<br />
crummy.com<br />
https://s3.amazonaws.com/crummy.com<br />
2006-10-26T18:46:45.000Z<br />
<br />
<br />
<br />
Max.<br />
Linie<br />
a b c<br />
Alle drei Services bieten die gleiche Funktionalität an, aber ihr Nutzen steigert sich von links nach rechts.<br />
• Service A ist ein typischer Service im RPC-Stil, denn alles wird über eine einzelne URI angeboten.<br />
Er ist weder adressierbar noch verbunden.<br />
• Service B ist adressierbar, aber nicht verbunden: Es gibt keine Hinweise auf die Beziehungen zwischen<br />
den Ressourcen. Das kann ein REST-RPC-Hybrid sein oder ein REST-konformer Service wie Amazon S3.<br />
• Service C ist adressierbar und gut verbunden: Ressourcen sind (vermutlich) sinnvoll miteinander<br />
verknüpft. Das könnte ein vollständiger REST-konformer Service sein.<br />
Abbildung 4-4: Ein Service auf drei Wegen<br />
Max.<br />
Linie<br />
Verweise und Verbindungshaftigkeit<br />
This is the Title of the Book, eMatter Edition<br />
| 109<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Max.<br />
Linie<br />
<strong>Die</strong> einheitliche Schnittstelle<br />
Im ganzen Web gibt es nur ein paar Dinge, die Sie mit einer Ressource anstellen können.<br />
HTTP stellt vier grundlegende Methoden für die gebräuchlichsten Operationen<br />
bereit:<br />
• eine Repräsentation einer Ressource holen: HTTP GET<br />
• eine neue Ressource erstellen: HTTP PUT an einen neuen URI oder HTTP<br />
POST an eine bestehende (siehe den Abschnitt »POST« auf Seite 112)<br />
• eine bestehende Ressource verändern: HTTP PUT an einen bestehenden URI<br />
• eine bestehende Ressource löschen: HTTP DELETE<br />
Ich werde erläutern, wie diese vier Methoden verwendet werden, um jede Operation<br />
darzustellen, die Sie sich vorstellen können. Ich werde auch zwei HTTP-Methoden<br />
für weniger gebräuchliche Operationen vorstellen: HEAD und OPTIONS.<br />
GET, PUT und DELETE<br />
<strong>Die</strong>se drei sollten Ihnen noch vom S3-Beispiel in Kapitel 3 vertraut sein. Um eine<br />
Ressource zu holen oder zu löschen, schickt der Client einfach einen GET- oder<br />
DELETE-Request an den entsprechenden URI. Im Fall eines GET-Requests schickt<br />
der Server eine Repräsentation im Entity-Body der Response zurück. Bei einem<br />
DELETE-Request kann der Entity-Body eine Statusmitteilung oder auch gar nichts<br />
enthalten.<br />
Um eine Ressource zu erstellen oder zu verändern, schickt der Client einen PUT-<br />
Request, der normalerweise einen Entity-Body enthält. Dazu gehört die vom Client<br />
vorgeschlagene neue Repräsentation der Ressource. Welche Daten das sind und wie<br />
sie formatiert sind, hängt vom Service ab. Egal wie sie aussehen – dies ist die Stelle,<br />
an der der Anwendungszustand zum Server wandert und ein Ressourcen-Zustand<br />
wird.<br />
Schauen wir uns wieder den S3-Service an, in dem Sie zwei Arten von Ressourcen<br />
erstellen können: Buckets und Objekte. Um ein Objekt anzulegen, schicken Sie<br />
einen PUT-Request an seinen URI und übergeben den Inhalt des Objekts im Entity-<br />
Body Ihres Requests. Dasselbe machen Sie, um ein Objekt zu verändern: Der neue<br />
Inhalt überschreibt jeden vorhandenen alten.<br />
Das Erstellen eines Buckets läuft ein wenig anders ab, da Sie keinen Entity-Body im<br />
PUT-Request angeben müssen. Ein Bucket hat abgesehen von seinem Namen keinen<br />
Ressourcen-Zustand, und der Name ist Teil des URI. (Das ist nicht ganz korrekt. <strong>Die</strong><br />
Objekte in einem Bucket sind auch Elemente des Ressourcen-Zustands dieses Buckets,<br />
denn sie werden aufgelistet, wenn Sie die Repräsentation eines Buckets per GET<br />
holen. Aber jedes S3-Objekt ist eine Ressource für sich, daher gibt es keinen Grund,<br />
ein Objekt über sein Bucket zu verändern. Jedes Objekt bietet die einheitliche<br />
Links<br />
Max.<br />
Linie<br />
110 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Schnittstelle an, und sie können es separat anpassen.) Legen Sie denURI des Buckets<br />
fest, spezifizieren Sie damit auch seine Repräsentation. PUT-Requests enthalten für<br />
die meisten Ressourcen einen Entity-Body mit einer Repräsentation, aber wie Sie<br />
sehen, ist dies nicht zwingend erforderlich.<br />
HEAD und OPTIONS<br />
Es gibt drei andere HTTP-Methoden, die ich als Teil der einheitlichen Schnittstelle<br />
betrachte. Zwei davon sind einfache Hilfsmethoden, daher werde ich sie als Erstes<br />
behandeln.<br />
• nur die Repräsentation der Metadaten holen: HTTP HEAD<br />
• prüfen, welche HTTP-Methoden eine bestimmte Ressource unterstützt: HTTP<br />
OPTIONS<br />
Sie haben die Methode HEAD schon bei den S3-Service-Ressourcen in Kapitel 3 in<br />
Aktion gesehen. Ein S3-Client nutzt HEAD, um Metadaten zu einer Ressource zu<br />
holen, ohne den eventuell enorm großen Entity-Body laden zu müssen. Genau dafür<br />
ist HEAD gedacht. Ein Client kann HEAD verwenden, um zu prüfen, ob eine Ressource<br />
existiert, oder andere Informationen über sie erhalten, ohne ihre gesamte<br />
Repräsentation zu holen. HEAD gibt Ihnen genau das zurück, was auch GET liefern<br />
würde, aber ohne den Entity-Body.<br />
Es gibt zwei Standard-HTTP-Methoden, die ich in diesem Buch<br />
nicht behandeln werde: TRACE und CONNECT. TRACE wird<br />
genutzt, um Proxies zu debuggen, während man CONNECT verwendet,<br />
um ein anderes Protokoll über einen HTTP-Proxy weiterzuleiten.<br />
Max.<br />
Linie<br />
<strong>Die</strong> Methode OPTIONS ermöglicht dem Client herauszufinden, was man mit einer<br />
Ressource anstellen kann. <strong>Die</strong> Response auf einen OPTIONS-Request enthält den<br />
HTTP-Header Allow, der die Untermenge der einheitlichen Schnittstelle angibt, die<br />
von dieser Ressource unterstützt wird. Hier ein Beispiel-Header:<br />
Allow: GET, HEAD<br />
Aufgrund dieses Headers kann der Client davon ausgehen, dass der Server auf GEToder<br />
HEAD-Requests für diese Ressource sinnvoll reagiert, aber keine anderen<br />
HTTP-Methoden unterstützt werden. <strong>Die</strong>se Ressource ist also nur lesend ansprechbar.<br />
<strong>Die</strong> Header, die der Client im Request schickt, können eventuell den Header Allow<br />
verändern, den der Server als Reaktion zurückschickt. Wenn Sie zum Beispiel einen<br />
passenden Authorization-Header mit einem OPTIONS-Request senden, kann es<br />
sein, dass Sie GET-, HEAD-, PUT- und DELETE-Requests für einen bestimmten<br />
URI schicken dürfen. Senden Sie den gleichen OPTIONS-Request, lassen aber den<br />
Max.<br />
Linie<br />
<strong>Die</strong> einheitliche Schnittstelle<br />
This is the Title of the Book, eMatter Edition<br />
| 111<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Header Authorization weg, ist Ihnen vielleicht nur GET und HEAD gestattet. <strong>Die</strong><br />
Methode OPTIONS ermöglicht dem Client, einfache Zugriffskontrollprüfungen<br />
vorzunehmen.<br />
Theoretisch kann der Server zusätzliche Informationen als Response auf einen<br />
OPTIONS-Request schicken und der Client kann OPTIONS-Requests senden, die<br />
den Server zu spezifischen Möglichkeiten befragen. Schön und gut, nur leider kein<br />
akzeptierter Standard in Bezug auf das, was ein Client in einem OPTIONS-Request<br />
fragen darf. Neben dem Header Allow gibt es keine akzeptierten Standards, was ein<br />
Server als Response schicken könnte. <strong>Die</strong> meisten Web-Server und Frameworks<br />
unterstützen OPTIONS nur sehr eingeschränkt. Bisher ist OPTIONS nur eine vielversprechende<br />
Idee, die niemand verwendet.<br />
Links<br />
Max.<br />
Linie<br />
POST<br />
Nun kommen wir zur am meisten missverstandenen HTTP-Methode: POST. <strong>Die</strong>se<br />
Methode hat prinzipiell zwei Funktionen: eine, die innerhalb der Grenzen von REST<br />
liegt, und eine, die sich außerhalb befindet und ein Element im RPC-Stil einführt. In<br />
komplexen Fällen wie diesem ist es am besten, auf den Originaltext zurückzugreifen.<br />
Folgendes sagt RFC 2616, der HTTP-Standard, über POST (aus dem Abschnitt 9.5):<br />
POST wurde entworfen, um eine einheitliche Methode für folgende Funktionen zu<br />
bieten:<br />
• Kommentieren bestehender Ressourcen<br />
• Posten einer Nachricht an ein Bulletin Board, eine Newsgroup, eine Mailing-Liste<br />
oder ähnliche Artikelsammlungen<br />
• Bereitstellen von Daten wie zum Beispiel dem Ergebnis eines Formular-Submits an<br />
einen datenverarbeitenden Prozess<br />
• Erweitern einer Datenbank durch eine Append-Operation<br />
<strong>Die</strong> tatsächlich durch POST ausgeführte Funktion wird durch den Server bestimmt<br />
und hängt normalerweise von dem Request-URI ab. <strong>Die</strong> gepostete Entität ist diesem<br />
URI genauso untergeordnet, wie eine Datei einem Verzeichnis untergeordnet ist, in<br />
dem sie liegt, ein News-Artikel einer Newsgroup, in der er gepostet wurde, oder ein<br />
Datensatz einer Datenbank.<br />
Was bedeutet das im Kontext von REST und der ROA?<br />
Untergeordnete Ressourcen erstellen<br />
In einem REST-konformen Design wird POST häufig verwendet, um untergeordnete<br />
Ressourcen zu erzeugen, also solche, die in Beziehung zu anderen »Eltern«-Ressourcen<br />
stehen. Ein Weblog-Programm könnte zum Beispiel jedes Weblog als Ressource<br />
bereitstellen (/weblogs/myweblog) und die einzelnen Weblog-Einträge als untergeordnete<br />
Ressourcen (/weblogs/myweblog/entries/1). Eine Datenbank mit Web-<br />
Anschluss mag eine Tabelle als Ressource bereitstellen und die einzelnen Daten-<br />
Max.<br />
Linie<br />
112 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Max.<br />
Linie<br />
bankzeilen als deren untergeordnete Ressourcen. Um einen Weblog-Eintrag oder<br />
eine Datenbankzeile zu erzeugen, schicken Sie ein POST an das Eltern-Element: das<br />
Weblog oder die Datenbanktabelle. Was für Daten Sie posten, und in welchem Format,<br />
hängt vom Service ab, aber wie bei PUT ist dies der Moment, in dem ein<br />
Anwendungszustand ein Ressourcen-Zustand wird. Sie können diese Verwendung<br />
von POST als POST(a) bezeichnen, für »Anhängen«. Wenn ich in diesem Buch<br />
»POST« schreibe, meine ich so gut wie immer POST(a).<br />
Warum können Sie nicht einfach PUT verwenden, um untergeordnete Ressourcen<br />
zu erstellen? Nun, manchmal können Sie das. Ein S3-Objekt ist eine untergeordnete<br />
Ressource, denn jedes S3-Objekt ist in einem S3-Bucket enthalten. Aber wir erstellen<br />
kein S3-Objekt, indem wir einen POST-Request an das Bucket schicken. Wir senden<br />
ein PUT direkt an den URI des Objekts. Der Unterschied zwischen PUT und POST<br />
ist dieser: Der Client nutzt PUT, wenn er dafür verantwortlich ist zu entscheiden,<br />
welchen URI die neue Ressource bekommen soll. Er nutzt POST, wenn der Server<br />
die Entscheidung über den URI der neuen Ressource fällen soll.<br />
Der S3-Service erwartet, dass Clients S3-Objekte mit PUT anlegen, da der URI eines<br />
S3-Objekts vollständig durch seinen Namen und den des Buckets festgelegt wird.<br />
Wenn der Client genug darüber weiß, wie das Objekt anzulegen ist, weiß er auch,<br />
wie der URI lauten wird. Der offensichtliche URI, der als Ziel des PUT-Requests verwendet<br />
wird, ist der, der das Bucket nutzen wird, sobald er existiert.<br />
Aber stellen Sie sich eine Anwendung vor, in der der Server mehr Kontrolle über die<br />
URIs hat, zum Beispiel ein Weblog-Programm. Der Client kann alle Informationen<br />
sammeln, die notwendig sind, um einen Weblog-Eintrag zu erstellen, und trotzdem<br />
nicht wissen, welchen URI der Eintrag haben wird, nachdem er einmal angelegt<br />
wurde. Vielleicht basieren die vom Server erstellten URIs auf der Reihenfolge einer<br />
internen Datenbank-ID: Wird der fertige URI /weblogs/myweblog/entries/1 oder<br />
/weblogs/myweblog/entries/1000 lauten? Vielleicht basiert der endgültige URI auf<br />
dem Zeitpunkt der Veröffentlichung: Von welcher Zeit geht der Server aus? Der<br />
Client sollte solche Dinge nicht wissen müssen.<br />
<strong>Die</strong> POST-Methode ist eine Möglichkeit, neue Ressourcen zu erstellen, ohne dass<br />
der Client den genauen URI wissen muss. In den meisten Fällen benötigt der Client<br />
nur den URI einer »Eltern«- oder »Fabrik«-Ressource. Der Server holt sich die<br />
Repräsentation aus dem Entity-Body und verwendet sie, um eine neue Ressource<br />
»unterhalb« der »Eltern«-Ressource anzulegen (die Bedeutung von »unterhalb«<br />
hängt vom Kontext ab).<br />
<strong>Die</strong> Response auf diese Art von POST-Requests hat normalerweise einen HTTP-Statuscode<br />
201 (»Created«). Sein Header Location enthält den URI der neu erstellten<br />
untergeordneten Ressource. Nachdem die Ressource nun tatsächlich existiert und<br />
der Client ihren URI kennt, können zukünftige Requests die PUT-Methode ver-<br />
Max.<br />
Linie<br />
<strong>Die</strong> einheitliche Schnittstelle<br />
This is the Title of the Book, eMatter Edition<br />
| 113<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
wenden, um diese Ressource zu verändern, mit GET eine Repräsentation davon<br />
holen und sie mit DELETE löschen.<br />
Tabelle 4-1 zeigt, wie ein PUT-Request an einen URI die zugrundeliegende Ressource<br />
erstellen oder verändern kann, und wie ein POST-Request an denselben URI eine<br />
neue, untergeordnete Ressource erzeugen kann.<br />
Links<br />
Tabelle 4-1: PUT-Aktionen<br />
/weblogs<br />
PUT an eine neue<br />
Ressource<br />
– (Ressource besteht<br />
bereits)<br />
PUT an eine bestehende<br />
Ressource<br />
Kein Effekt<br />
/weblogs/myweblog Erstelle dieses Weblog Verändere die Einstellungen<br />
dieses Weblogs<br />
/weblogs/myweblog/<br />
entries/1<br />
– (wie würden Sie zu diesem<br />
URI kommen?)<br />
<strong>Die</strong>sen Weblog-Eintrag<br />
verändern<br />
POST<br />
Erstelle ein neues Weblog<br />
Erstelle einen neuen<br />
Weblog-Eintrag<br />
Einen Kommentar zu diesem<br />
Weblog-Eintrag<br />
posten<br />
Max.<br />
Linie<br />
An den Ressourcen-Zustand anhängen<br />
<strong>Die</strong> Informationen, die in einem POST an eine Ressource transportiert werden, müssen<br />
nicht zu einer komplett neuen, untergeordneten Ressource führen. Manchmal<br />
werden die Daten bei einem POST an eine Ressource an ihren eigenen Zustand angehängt,<br />
anstatt sie in eine neue Ressource zu stecken.<br />
Stellen Sie sich einen Ereignisprotokollservice vor, der eine einzige Ressource bereitstellt:<br />
das Log. Nehmen wir an, sein URI wäre /log. Um das Log zu holen, schicken<br />
Sie einen GET-Request an /log.<br />
Wie soll nun ein Client etwas an das Log anhängen? Er könnte einen PUT-Request<br />
an /log schicken, aber die PUT-Methode ist eigentlich dazu gedacht, eine neue Ressource<br />
zu erstellen oder alte Einstellungen durch neue zu überschreiben. Der Client<br />
will aber beides nicht, sondern nur Informationen an das Ende des Logs anhängen.<br />
<strong>Die</strong> POST-Methode passt hier, so als ob jeder Log-Eintrag als eigenständige Ressource<br />
bereitgestellt würde. <strong>Die</strong> Semantik von POST ist in beiden Fällen gleich: Der Client<br />
fügt einer bestehenden Ressource untergeordnete Informationen hinzu. Der einzige<br />
Unterschied liegt darin, dass <strong>beim</strong> Weblog und seinen Einträgen die untergeordneten<br />
Informationen als neue Ressourcen erscheinen. Hier taucht die untergeordnete<br />
Information als neues Datenelement in der Repräsentation des Eltern-Elements<br />
auf.<br />
Überladenes POST: <strong>Die</strong> nicht so einheitliche Schnittstelle<br />
<strong>Die</strong>se Art, die Sache zu betrachten, erklärt einen Großteil dessen, was der HTTP-<br />
Standard über POST sagt. Sie können es verwenden, um Ressourcen unterhalb einer<br />
Max.<br />
Linie<br />
114 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Max.<br />
Linie<br />
Eltern-Ressource zu erstellen oder um zusätzliche Daten an den aktuellen Zustand<br />
einer Ressource anzuhängen. <strong>Die</strong> eine Verwendung von POST, die ich bisher nicht<br />
erklärt habe, ist die, mit der Sie vermutlich am besten vertraut sind, da damit so gut<br />
wie alle Web-Anwendungen arbeiten: das Liefern von Daten, wie zum Beispiel dem<br />
Ergebnis eines abgeschickten Formulars, an einen datenverarbeitenden Prozess.<br />
Was ist ein »datenverarbeitender Prozess«? Das kling ziemlich vage. Und tatsächlich<br />
kann so gut wie alles ein datenverarbeitender Prozess sein. Verwendet man POST auf<br />
diese Art und Weise, verwandelt man eine Ressource in einen kleinen Nachrichtenprozessor,<br />
der sich wie ein XML-RPC-Server verhält. <strong>Die</strong> Ressource akzeptiert einen<br />
POST-Request, begutachtet ihn und entscheidet sich dazu, irgendetwas zu tun.<br />
Dann entscheidet er sich dazu, dem Client irgendwelche Daten zu liefern.<br />
Ich bezeichne diese Verwendung von POST als überladenes POST, in Analogie zum<br />
Überladen von Operatoren in einer Programmiersprache. Es ist überladen, weil eine<br />
einzelne HTTP-Methode verwendet wird, um für viele Nicht-HTTP-Methoden zu<br />
stehen. Es ist aus dem gleichen Grund verwirrend, wie das Überladen von Operatoren<br />
verwirrend sein kann: Sie dachten, Sie wüssten, was HTTP-POST tut, aber nun<br />
wird es verwendet, um einem unbekannten Zweck zu dienen. Sie könnten das überladene<br />
POST als POST(p) bezeichnet finden – für »prozessiert«.<br />
Wenn Ihr Service überladenes POST bereitstellt, kommt wieder die Frage auf:<br />
»Warum sollte der Server dies tun statt jenes?« Jeder HTTP-Request muss Methodeninformationen<br />
enthalten, und wenn Sie überladenes POST verwenden, kann dies<br />
nicht in der HTTP-Methode geschehen. <strong>Die</strong> POST-Methode ist nur eine Direktive an<br />
den Server, die sagt: »Schau in den HTTP-Request, um die eigentliche Methoden-<br />
Information zu erhalten.« <strong>Die</strong> eigentliche Information kann in dem URI, den HTTP-<br />
Headern oder dem Entity-Body enthalten sein. Wie auch immer die Sache vor sich<br />
geht – ein bisschen RPC-Stil ist auf jeden Fall in den Service gesickert.<br />
Wenn sich die Methoden-Information nicht in der HTTP-Methode befindet, ist die<br />
Schnittstelle nicht mehr einheitlich. <strong>Die</strong> eigentliche Methoden-Information kann<br />
sonstwo sein. Als REST-Partisane mag ich das nicht wirklich, aber manchmal lässt es<br />
sich nicht vermeiden. Bis Kapitel 9 werden Sie gesehen haben, wie so gut wie jedes<br />
denkbare Szenario über die einheitliche Schnittstelle von HTTP zu verwirklichen ist,<br />
aber manchmal ist der RPC-Stil der einfachste Weg, um komplexe Operationen auszudrücken,<br />
die mehrere Ressourcen umfassen.<br />
Eventuell müssen Sie überladenes POST bereitstellen, auch wenn Sie POST nur<br />
nutzen, um untergeordnete Ressourcen anzulegen oder an eine Repräsentation einer<br />
Ressource anzuhängen. Was sollte man zum Beispiel tun, wenn eine einzelne Ressource<br />
beide Arten von POST unterstützt? Woher weiß der Server, ob ein Client ein<br />
POST abschickt, um eine untergeordnete Ressource zu erzeugen oder um an die<br />
bestehende Repräsentation der Ressourcen anzuhängen? Sie müssen vielleicht<br />
irgendwo im HTTP-Request zusätzliche Methoden-Informationen angeben.<br />
Max.<br />
Linie<br />
<strong>Die</strong> einheitliche Schnittstelle<br />
This is the Title of the Book, eMatter Edition<br />
| 115<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Überladenes POST sollte nicht verwendet werden, um ein schlechtes Ressourcendesign<br />
zu verdecken. Denken Sie daran, dass eine Ressource so gut wie alles sein kann.<br />
Normalerweise ist es möglich, Ihr Ressourcendesign so zu verändern, dass die einheitliche<br />
Schnittstelle passt, anstatt den RPC-Stil in Ihren Service einzuführen.<br />
Links<br />
Max.<br />
Linie<br />
Sicherheit und Idempotenz<br />
Wenn Sie die uniforme Schnittstelle von HTTP so bereitstellen wollen, wie sie<br />
entworfen wurde, erhalten Sie zwei nützliche Eigenschaften kostenlos dazu. Verwendet<br />
man sie korrekt, sind GET- und HEAD-Requests sicher. Requests mit GET,<br />
HEAD, PUT und DELETE sind zudem idempotent.<br />
Sicherheit<br />
Ein GET- oder HEAD-Request ist eine Anfrage, um bestimmte Daten zu lesen, keine<br />
Anfrage, irgendwelche Serverzustände zu ändern. Der Client kann einen GET- oder<br />
HEAD-Request zehn Mal hintereinander ausführen und es wäre so, als ob er nur einmal<br />
oder niemals gesendet worden wäre. Wenn Sie per GET http://www.google.com/<br />
search?q=Quallen anfordern, ändern Sie nichts im Verzeichnis der Ressourcen über<br />
Quallen. Sie holen einfach nur eine Repräsentation davon ab. Ein Client sollte in der<br />
Lage sein, einen GET- oder HEAD-Request an einen unbekannten URI zu schicken,<br />
ohne sich Sorgen machen zu müssen, ob etwas zerstört wird.<br />
Das heißt nicht, dass GET- und HEAD-Requests keine Nebeneffekte haben können.<br />
Manche Ressourcen führen Zähler, die bei jedem Zugriff eines Clients per GET<br />
erhöht werden. <strong>Die</strong> meisten Web-Server protokollieren jeden eingehenden Request<br />
in einer Log-Datei. Das sind Nebeneffekte: Der Server-Zustand und sogar der Ressourcen-Zustand<br />
werden als Reaktion auf einen GET-Request geändert. Aber der<br />
Client hat nicht darum gebeten und ist dafür auch nicht verantwortlich. Ein Client<br />
sollte niemals einen GET- oder HEAD-Request nur aufgrund der Nebeneffekte ausführen,<br />
und die Nebeneffekte sollten auch niemals so stark sein, dass der Client sich<br />
wünschte, er hätte den Request niemals abgeschickt.<br />
Idempotenz<br />
Idempotenz ist etwas trickreicher. <strong>Die</strong> Idee kommt aus der Mathematik, und wenn<br />
Sie mit Idempotenz nicht vertraut sind, kann ein mathematisches Beispiel vielleicht<br />
helfen. Eine idempotente Operation in der Mathematik ist eine, die bei einmaliger<br />
Anwendung denselben Effekt hat wie bei mehrfacher. Das Multiplizieren einer Zahl<br />
mit Null ist idempotent: 4 × 0 × 0 × 0 ist das Gleiche wie 4 × 0. 6 Analog dazu ist eine<br />
Operation auf einer Ressource idempotent, wenn das Abschicken eines Requests das<br />
6 Das Multiplizieren einer Zahl mit 1 ist sowohl sicher als auch idempotent: 4 × 1 × 1 × 1 ist das Gleiche<br />
wie 4 ×1, ergibt nämlich 4. <strong>Die</strong> Multiplikation mit Null ist nicht sicher, da 4 × 0 nicht das Gleiche wie<br />
4 ist. Das Multiplizieren mit jeder anderen Zahl ist weder sicher noch idempotent.<br />
Max.<br />
Linie<br />
116 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Max.<br />
Linie<br />
Gleiche ist wie das Abschicken einer ganzen Serie identischer Requests. Der zweite<br />
und folgende Requests belassen den Ressourcen-Zustand in exakt dem gleichen<br />
Zustand wie er durch den ersten Request entstanden ist.<br />
PUT- und DELETE-Operationen sind idempotent. Wenn Sie eine Ressource per<br />
DELETE löschen, ist sie weg. Wenn Sie DELETE erneut abfeuern, bleibt sie verschwunden.<br />
Wenn Sie eine neue Ressource mit PUT anlegen und dann PUT nochmals<br />
abschicken, ist die Ressource immer noch da und hat auch die gleichen<br />
Eigenschaften wie nach dem ersten PUT. Wenn Sie PUT verwenden, um den<br />
Zustand einer Ressource zu ändern, können Sie den PUT-Request nochmals senden,<br />
ohne dass sich der Ressourcen-Zustand ändern wird.<br />
Ein zu beachtender Punkt ist daher, dass Sie Ihren Clients nicht erlauben sollten,<br />
Repräsentationen per PUT zu übermitteln, die einen Ressourcenstatus mit relativen<br />
Werten ändern. Wenn eine Ressource einen numerischen Wert als Teil ihres<br />
Zustands enthält, kann ein Client vielleicht PUT nutzen, um den Wert auf 4 oder 0<br />
oder -50 zu setzen, aber nicht, um den Wert um 1 zu erhöhen. Wenn der ursprüngliche<br />
Wert 0 ist und man zwei PUT-Requests schickt, die sagen: »Setze den Wert auf<br />
4«, bleibt der Wert auf 4. Wenn der Anfangswert 0 ist und man zwei PUT-Requests<br />
schickt, die sagen »Erhöhe den Wert um 1«, wird der Wert danach nicht 1, sondern<br />
2 sein. Das ist nicht idempotent.<br />
Warum Sicherheit und Idempotenz wichtig sind<br />
Sicherheit und Idempotenz ermöglichen einem Client, zuverlässige HTTP-Requests<br />
über ein unzuverlässiges Netzwerk zu versenden. Wenn Sie einen GET-Request<br />
abschicken und keine Response erhalten, feuern Sie ihn einfach nochmals ab. Er ist<br />
sicher: Selbst wenn Ihr erster Request angekommen war, hatte er keinen echten<br />
Effekt auf den Server. Wenn Sie einen PUT-Request machen und keine Response<br />
erhalten, schicken Sie ihn nochmals los. Wenn Ihr erster Request durchgekommen<br />
ist, wird ein zweiter keinen zusätzlichen Effekt haben.<br />
POST ist weder sicher noch idempotent. Das Abschicken zweier identischer POST-<br />
Requests an eine »Fabrik«-Ressource wird vermutlich in zwei untergeordneten Ressourcen<br />
enden, die beide die gleichen Informationen enthalten. Bei überladenem<br />
POST kann man gar nicht mehr sagen, was passieren wird.<br />
Der häufigste Missbrauch der einheitlichen Schnittstelle ist, unsichere Operationen<br />
per GET verfügbar zu machen. Sowohl del.icio.us als auch die Flickr-API tun dies.<br />
Wenn Sie per GET https://api.del.icio.us/posts/delete aufrufen, erhalten Sie keine<br />
Repräsentation – stattdessen verändern Sie den Datensatz bei del.icio.us.<br />
Warum ist das schlecht? Nun, dazu eine kleine Geschichte. Im Jahr 2005 veröffentlichte<br />
Google ein Caching-Tool für den Client namens Web Accelerator. Es lief<br />
zusammen mit dem Web-Browser und holte die Seiten im Voraus, die auf der aktuell<br />
betrachteten Seite einen Verweis hatten. Wenn man dann auf einen dieser Verweise<br />
Max.<br />
Linie<br />
<strong>Die</strong> einheitliche Schnittstelle<br />
This is the Title of the Book, eMatter Edition<br />
| 117<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Max.<br />
Linie<br />
klickte, wurde die entsprechende Seite schneller geladen, da der Computer sie schon<br />
empfangen hatte.<br />
Der Web Accelerator war ein Desaster. Nicht aufgrund eines Problems in der Software<br />
selbst, sondern weil das Web voll von Anwendungen ist, die GET missbrauchen.<br />
Der Web Accelerator nahm an, dass GET-Operationen sicher wären und<br />
Clients sie schon im Voraus laden konnten, falls jemand die entsprechende<br />
Repräsentation sehen wollte. Aber wenn diese GET-Anfragen an reale URIs<br />
geschickt wurden, änderten sich Datensätze. <strong>Die</strong> Leute verloren Daten.<br />
Man kann die Schuld hier großzügig verteilen: Programmierer sollten keine<br />
unsicheren Aktionen per GET ansprechbar machen, und Google hätte kein Tool für<br />
die reale Welt veröffentlichen sollen, das im realen WWW nicht funktioniert. <strong>Die</strong><br />
aktuelle Version des Web Accelerator ignoriert alle URIs, die Query-Variablen<br />
enthalten. Das löst einen Teil des Problems, verhindert aber auch, dass viele Ressourcen,<br />
die man per GET sicher laden könnte (wie zum Beispiel die Web-Suchen von<br />
Google), im Voraus geladen werden.<br />
Sie können noch viele Beispiele bekommen. Viele Web Services und Web-Anwendungen<br />
verwenden URIs als Eingabeparameter, und als Erstes schicken sie einen<br />
GET-Request, um eine Repräsentation einer Ressource zu erhalten. <strong>Die</strong>se Services<br />
wollen keine katastrophalen Nebeneffekte auslösen, aber sie haben es nicht in der<br />
Hand. Es ist Aufgabe des Service, einen GET-Request so zu handhaben, dass er mit<br />
dem HTTP-Standard konform ist.<br />
Warum die einheitliche Schnittstelle wichtig ist<br />
Wichtig an REST ist nicht, dass Sie die spezielle einheitliche Schnittstelle verwenden,<br />
die HTTP definiert. REST spezifiziert eine einheitliche Schnittstelle, sagt aber nicht,<br />
welche einheitliche Schnittstelle. GET, PUT und der Rest sind nicht für alle Zeiten<br />
die perfekte Schnittstelle. Wichtig ist die Einheitlichkeit: Jeder Service verwendet die<br />
HTTP-Schnittstelle auf die gleiche Art und Weise.<br />
Der Punkt ist nicht, dass GET der beste Name für eine lesende Operation ist,<br />
sondern dass GET im ganzen Web »Lesen« bedeutet – egal, welche Ressource Sie<br />
dabei ansprechen. Bei einem gegebenen URI einer Ressource ist es keine Frage, wie<br />
Sie eine Repräsentation erhalten: Sie schicken einen HTTP-GET-Request an diesen<br />
URI. <strong>Die</strong> einheitliche Schnittstelle lässt zwei Services sich so ähnlich werden wie zwei<br />
Web-Sites. Ohne diese Einheitlichkeit müssen Sie lernen, wie jeder Service Informationen<br />
erwartet und verschickt. <strong>Die</strong> Regeln könnten sich sogar von Ressource zu<br />
Ressource innerhalb eines Service unterscheiden.<br />
Sie können einem Computer beibringen zu verstehen, was GET bedeutet – dann gilt<br />
dieses Verständnis für jeden REST-konformen Web Service. Da gibt es auch nicht<br />
viel zu verstehen. Der für den Service spezifische Code kann sich dann um die Behand-<br />
Links<br />
Max.<br />
Linie<br />
118 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Rechts<br />
Max.<br />
Linie<br />
lung der Repräsentation kümmern. Ohne die einheitliche Schnittstelle erhalten Sie<br />
eine viel größere Anzahl an Methoden, die den Platz von GET einnehmen: doSearch<br />
und getPage und nextPrime. Jeder Service spricht eine andere Sprache. Das ist auch<br />
der Grund, warum ich überladenes POST nicht so sehr mag: Es verwandelt das einfache<br />
Esperanto der einheitlichen Schnittstelle in ein babylonisches Gewirr einmalig<br />
genutzter Untersprachen.<br />
Manche Anwendungen erweitern die einheitliche Schnittstelle von HTTP. Der offensichtlichste<br />
Fall ist da WebDAV, das acht neue HTTP-Methoden hinzufügt, unter<br />
anderem MOVE, COPY und SEARCH. <strong>Die</strong> Verwendung dieser Methoden in einem<br />
Web Service würde keine Regel von REST verletzen, da REST nicht aussagt, wie die<br />
einheitliche Schnittstelle aussehen soll. <strong>Die</strong> Nutzung dieser Methoden würde allerdings<br />
nicht in meine <strong>ressourcenorientierte</strong> <strong>Architektur</strong> passen (da ich die ROA<br />
explizit mit den Standard-HTTP-Methoden verbunden habe), wobei so ein Service<br />
trotzdem noch allgemein gesprochen ressourcenorientiert sein könnte.<br />
Der eigentliche Grund, warum man keine WebDAV-Methoden nutzen sollte, ist,<br />
dass Sie damit Ihren Service inkompatibel zu anderen REST-konformen Services<br />
machen. Ihr Service würde eine andere einheitliche Schnittstelle verwenden als die<br />
meisten anderen. Es gibt Web Services wie Subversion, die die WebDAV-Methoden<br />
nutzen, daher wäre Ihr Service nicht allein. Aber er wäre nur ein Teil eines weitaus<br />
kleineren Webs. Das ist der Grund dafür, dass das Entwickeln eigener HTTP-Methoden<br />
eine sehr, sehr schlechte Idee ist: Ihr eigenes Vokabular lässt die Community<br />
deutlich schrumpfen. Da können Sie auch gleich XML-RPC nutzen.<br />
Eine andere einheitliche Schnittstelle besteht einzig und allein aus HTTP GET und<br />
überladenem POST. Um eine Repräsentation einer Ressource zu erhalten, schicken<br />
Sie ein GET an ihren URI. Um eine Ressource zu erstellen, zu verändern oder zu<br />
löschen, schicken Sie ein POST. <strong>Die</strong>se Schnittstelle ist vollständig REST-konform,<br />
aber passt auch nicht zu meiner <strong>ressourcenorientierte</strong>n <strong>Architektur</strong>. <strong>Die</strong>se Schnittstelle<br />
ist gerade ausreichend, um zwischen sicheren und unsicheren Operationen zu<br />
unterscheiden. Eine <strong>ressourcenorientierte</strong> Web-Anwendung würde diese Schnittstelle<br />
nutzen, weil heutige HTML-Formulare nur GET und POST unterstützen.<br />
Das war’s!<br />
Das ist die <strong>ressourcenorientierte</strong> <strong>Architektur</strong>. Es gibt nur vier Konzepte:<br />
1. Ressourcen<br />
2. ihre Namen (URIs)<br />
3. ihre Repräsentationen<br />
4. die Verweise zwischen ihnen<br />
Max.<br />
Linie<br />
Das war’s! | 119<br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008
Und es gibt vier Eigenschaften:<br />
1. Adressierbarkeit<br />
2. Zustandslosigkeit<br />
3. Verbindungshaftigkeit<br />
4. eine einheitliche Schnittstelle<br />
Natürlich bleibt eine Reihe Fragen offen. Wie sollten reale Daten in Ressourcen aufgeteilt<br />
und wie sollten diese Ressourcen organisiert werden? Was sollte dann in den<br />
HTTP-Requests und -Responses stehen? Ich werde einen Großteil der verbleibenden<br />
Seiten dazu nutzen, solche Fragen anzusprechen.<br />
Links<br />
Max.<br />
Linie<br />
Max.<br />
Linie<br />
120 | Kapitel 4: <strong>Die</strong> <strong>ressourcenorientierte</strong> <strong>Architektur</strong><br />
This is the Title of the Book, eMatter Edition<br />
Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.<br />
<strong>Die</strong>s ist ein Auszug aus dem Buch „Web Services mit REST“, ISBN 978-3-89721-727-0<br />
http://www.oreilly.de/catalog/restfulwsger/<br />
<strong>Die</strong>ser Auszug unterliegt dem Urheberrecht. © <strong>O'Reilly</strong> <strong>Verlag</strong> 2008