# Rest - Bilder mit Metadaten modellieren



## mrBrown (26. Okt 2018)

Ich bin aktuell dabei, eine REST-Schnittstelle zu modellieren, über die auch (u.a.) Bilder inklusive Metadaten abfragen lassen. Metadaten (zB Titel, Beschreibung, ...) und Bilder gehören dabei immer zu einer übergeordneten Resource

Bisher hab ich mehrere mögliche Varianten, wie man das modellieren könnte, aber sicher, welche am sinnvollsten ist, bin ich mir noch nicht...

Variante 1:
Bilddaten als Resource, Metadaten als Unterresource davon.
`GET /context/images/42` -> liefert PNG
`GET /context/images/42/info` -> liefert JSON

Variante 2:
Variante 1 umgedreht, Metadaten als Resource, Bild als Unterresource.
`GET /context/images/42` -> liefert JSON
`GET /context/images/42/data` -> liefert PNG

Variante 3:
Beide als eine Resource, je nach gewünschten Content-Type wird dann zB PNG oder JSON ausgeliefert.
`GET "Accept: application/json"  /context/images/42` -> liefert JSON
`GET "Accept: image/png" /context/images/42` -> liefert PNG

Variante 4:
Eine Resource, die dann zB JSON ausliefert, wobei das Bild dann Base64-codiert eingebettet wird.
`GET  /context/images/42` -> liefert `{data:"UG9seWZvbiB6...", name: "Blub"}`

Variante 5:
Bilddaten als völlig eigene Resource, Metadaten verweisen dann auf die Bilddaten
`GET  /context/images/42` -> liefert `{image:"/images/xyz", name: "Blub"}`
`GET  /images/xyz` -> liefert PNG



Irgendwer eine Meinung dazu, irgendwelche besonderen Vor-/Nachteile der einzelnen Varianten? Oder vielleicht sogar noch eine weitere (bessere) Variante?


----------



## Xyz1 (26. Okt 2018)

Wieso lässt die nicht in den Bildern? Was Du mit "übergeordneter Ressource" meinst erschließt sich mir nicht.


----------



## mrBrown (26. Okt 2018)

DerWissende hat gesagt.:


> Wieso lässt die nicht in den Bildern?


Metadaten sind in dem Fall nicht die üblichen Metadaten (sowas wie exif), sondern Daten die der Nutzer zusätzlich hinzufügen kann.



DerWissende hat gesagt.:


> Was Du mit "übergeordneter Ressource" meinst erschließt sich mir nicht.


Naja, das Gegenteil von Subresource.
`/a/b` -> b ist Unter/Subresource von a, a ist also die übergeordnete Resource von b.


----------



## sascha-sphw (26. Okt 2018)

Ich persönlich würde Variante 5 präferieren. Ich mag einfach die Trennung und mich würde es verwirren, wenn bei einem REST call auf einmal das Image zurück kommt.


----------



## mrBrown (26. Okt 2018)

sascha-sphw hat gesagt.:


> Ich persönlich würde Variante 5 präferieren. Ich mag einfach die Trennung


Führt halt dazu, das das Bild plötzlich keine Unter-Resource mehr ist, der Kontext verloren geht, und man immer den Weg über die Metadaten nehmen muss :/ 



sascha-sphw hat gesagt.:


> mich würde es verwirren, wenn bei einem REST call auf einmal das Image zurück kommt.


Kommt es doch in jedem Fall, nur die Location ist unterschiedlich?


----------



## AndiE (26. Okt 2018)

Ich könnte mir vorstellen, dass es eine übergeordnete Ressource A gibt, die zwei Unterressourcen hat: Einmal die Metadaten B und die Bilddatei C. 

Begründung: 
In der Tierdatenbank eines Tierparks hat man bestimmte Daten, die fest sind, wie Name, Geburtsdatum, Chipnummer und bestimmte Daten, die man immer nutzt, wie Fütterung usw. Das alles wäre A. Wer Vater und Mutter ist, und die Krankenakte wäre in meinem Fall B. Die Bilddatei, die ein Foto des Tieres enthält wäre dann C.


----------



## mrBrown (26. Okt 2018)

AndiE hat gesagt.:


> In der Tierdatenbank eines Tierparks hat man bestimmte Daten, die fest sind, wie Name, Geburtsdatum, Chipnummer und bestimmte Daten, die man immer nutzt, wie Fütterung usw. Das alles wäre A. Wer Vater und Mutter ist, und die Krankenakte wäre in meinem Fall B. Die Bilddatei, die ein Foto des Tieres enthält wäre dann C.


In diesem Fall ist B allerdings eine Beschreibung, was auf Bild C zu sehen ist, zb ein Bild, welches ein Männchen und ein Weibchen zeigt, und die Beschreibung enthält dann, welches davon was ist und worin die sich unterscheiden  (und von B+c gibt es jeweils n Stück)

Davon gänzlich getrennte Resource gibt es natürlich auch noch, aber bei denen ist es jeweils ziemlich klar, wie man die modelliert.


----------



## mihe7 (26. Okt 2018)

mrBrown hat gesagt.:


> Führt halt dazu, das das Bild plötzlich keine Unter-Resource mehr ist, der Kontext verloren geht


Warum willst Du die ID in Form von Unter-Ressourcen konstruieren, wozu brauchst Du den Kontext?


----------



## mrBrown (26. Okt 2018)

mihe7 hat gesagt.:


> Warum willst Du die ID in Form von Unter-Ressourcen konstruieren, wozu brauchst Du den Kontext?


Brauchen ist vielleicht falsch gesagt, aber ohne Kontext haben sie einfach keine Bedeutung.
In DDD-Sprech: Kontext ist Aggregat, Bilder eine Entität dadrin.

Und fühlt sich irgendwie "RESTful-iger" an


----------



## mihe7 (26. Okt 2018)

mrBrown hat gesagt.:


> Brauchen ist vielleicht falsch gesagt, aber ohne Kontext haben sie einfach keine Bedeutung.


Naja, die IDs sollen auch keine Bedeutung haben. Die bekommst Du doch ebenfalls über die REST-Schnittstelle.


----------



## mrBrown (26. Okt 2018)

Bevor ich dich missverstehe, was meinst du mit ID?


----------



## mihe7 (26. Okt 2018)

Die URI ist eine ID.


----------



## mihe7 (26. Okt 2018)

Hat ein wenig gedauert, aber jetzt habe ich den Talk gefunden, den ich gesucht habe 

https://youtu.be/pspy1H6A3FM?t=1023


----------



## Xyz1 (26. Okt 2018)

Schau hier





https://stackoverflow.com/a/26410745

Es hat einer aufgemalt - und die Begrifflichkeiten sollte man auch wahren....
Unter Ressource verstehe ich nach dem Hashtag den Sprung....

Auf stack overflow steht auch iiiirgendwo das "RESTful" von Facebook erklärt.....

Eigentlich kannste machen was de willst.... nenne die Route doch nach einer Hashsum des Bilds....

BEARBEITUNG: Suche nach Rest routes best practices ---- tonnenweise wissenschaftliche Artikel und anderes!!


----------



## mrBrown (26. Okt 2018)

mihe7 hat gesagt.:


> Hat ein wenig gedauert, aber jetzt habe ich den Talk gefunden, den ich gesucht habe


Der ist ziemlich gut, danke!




mihe7 hat gesagt.:


> Naja, die IDs sollen auch keine Bedeutung haben. Die bekommst Du doch ebenfalls über die REST-Schnittstelle.


Ja, Bedeutung ist in dem Fall hauptsächlich für Menschen gedacht.
Wobei: Kann man ohne Kontext in der URL bei einem POST zwei Resourcen einander zuordnen, ohne zwei Requests absetzen zu müssen?



Das eigentlich Problem verschiebt man so aber auch nur: Sind Bilddaten und Metadaten eine Resource und nur unterschiedliche Ansichten davon? Oder eher zwei getrennte, in Verbindung stehende?


----------



## mrBrown (26. Okt 2018)

DerWissende hat gesagt.:


> Schau hier
> 
> 
> 
> ...


Von dort: "This is just plain wrong".


----------



## mihe7 (26. Okt 2018)

mrBrown hat gesagt.:


> Kann man ohne Kontext in der URL bei einem POST zwei Resourcen einander zuordnen, ohne zwei Requests absetzen zu müssen?


Ja. Zum Beispiel ein Archiv mit Metadaten und Bild rüber, der Server erzeugt dann die IDs und die Zuordnung untereinander. 



mrBrown hat gesagt.:


> Sind Bilddaten und Metadaten eine Resource und nur unterschiedliche Ansichten davon?


Das ist die große Frage. Im Semantic Web/Linked Data hat man ein ähnliches Problem. Hat man eine URI für ein Objekt, dann darf diese URI nur für dieses Objekt stehen. Hat man eine URL als URI, will man aber gleichzeitig Informationen über das Objekt abrufen. Gelöst wird dies dort z. B. per Content Negotiation. 

Sprich: habe ich z. B. eine ID für mein Handy in Form einer HTTP-URL http://xyz/Mihe7sHandy, steht diese URL nur für dieses Handy. Kontaktiere ich die URL nun via Browser bekomme ich erst einmal einen Location-Header, der mir z. B. sagt: Infos via HTML unter http://xyz/Mihe7sHandy.html, will ich die RDF-Darstellung (Accept-Header), bekomme ich dagegen einen Location-Header gegen http://xyz/Mihe7sHandy.rdf (oder was auch immer).


----------



## AndiE (26. Okt 2018)

Ich habe den Eindruck, dass ich euch nicht folgen kann. Ich habe REST immer für eine Übertragung gehalten, wo statt der RPC auf Anforderung ein Objekt zurückgegeben wird, im allgemeinen ein XML-Objekt. Die Anwendung selbst zeigt mir nicht, dass sie Daten aus dem Netz holt. Damit ruft die Anwendung mit einem Request den Server auf, und erhält als Responce ein XML-Objekt, das dann analysiert wird.  Ungefähr so:


```
<person>
  <data>
    <name>Meier </name>
  </date>
  <pic>
  </Binärdaten />
  </pic>
</person>
```

Daraus kann dann die Anwendung das Bild mit Beschreibung herstellen.

Das wäre dann so, dass ich im Gegensatz zum RPC(Remote Procedure Call)  mir gleich das Ergebnis als Objekt hole.


----------



## mrBrown (26. Okt 2018)

mihe7 hat gesagt.:


> Ja. Zum Beispiel ein Archiv mit Metadaten und Bild rüber, der Server erzeugt dann die IDs und die Zuordnung untereinander.


Meinte nicht die Zuordnung zueinander, sondern die Zuordnung zum Kontext  Üblicherweise wird das ja mit 'nem POST auf den Kontext gelöst.

IDs lassen sich in diesem Fall auch vom Client generieren, werden wohl sowieso UUIDs und sollte auch Offline-Fähig sein.



mihe7 hat gesagt.:


> Das ist die große Frage. Im Semantic Web/Linked Data hat man ein ähnliches Problem. Hat man eine URI für ein Objekt, dann darf diese URI nur für dieses Objekt stehen. Hat man eine URL als URI, will man aber gleichzeitig Informationen über das Objekt abrufen. Gelöst wird dies dort z. B. per Content Negotiation.
> 
> Sprich: habe ich z. B. eine ID für mein Handy in Form einer HTTP-URL http://xyz/Mihe7sHandy, steht diese URL nur für dieses Handy. Kontaktiere ich die URL nun via Browser bekomme ich erst einmal einen Location-Header, der mir z. B. sagt: Infos via HTML unter http://xyz/Mihe7sHandy.html, will ich die RDF-Darstellung (Accept-Header), bekomme ich dagegen einen Location-Header gegen http://xyz/Mihe7sHandy.rdf (oder was auch immer).


Das wäre ja im wesentlichen Variante 3, bis auf das setzen des Location-Headers und zeige auf entsprechende URLs (mit Status 300?)

Wäre mir bisher die liebste Variante...





AndiE hat gesagt.:


> Ich habe REST immer für eine Übertragung gehalten, wo statt der RPC auf Anforderung ein Objekt zurückgegeben wird, im allgemeinen ein XML-Objekt



So ganz grob: Ja.
Der Rest deiner Antwort ist aber viel zu highlevel'ig gedacht. Mir gehts nicht um das wie und was die Anwendung draus macht, sondern wie ich die Schnittstelle designe.


----------



## mihe7 (27. Okt 2018)

mrBrown hat gesagt.:


> Meinte nicht die Zuordnung zueinander, sondern die Zuordnung zum Kontext  Üblicherweise wird das ja mit 'nem POST auf den Kontext gelöst.


Dann verstehe ich die Frage nicht: "Kann man ohne Kontext in der URL bei einem POST zwei Resourcen einander zuordnen, ohne zwei Requests absetzen zu müssen?"



mrBrown hat gesagt.:


> IDs lassen sich in diesem Fall auch vom Client generieren, werden wohl sowieso UUIDs und sollte auch Offline-Fähig sein.


Klar kannst Du die UUIDs clientseitig generieren, Du weißt aber nicht, welche URL der Server daraus macht.



mrBrown hat gesagt.:


> Das wäre ja im wesentlichen Variante 3, bis auf das setzen des Location-Headers und zeige auf entsprechende URLs (mit Status 300?)


Nein. Variante 3 bedeutet eine URL, die zwei verschiedene Ressourcen identifiziert -> darf nicht sein. 

Anderes Beispiel: Die ISBN 978-3-608-96376-2 ist eine ID für ein Buch. Diese kann man auch als URI urn:isbn:978-3-608-96376-2 darstellen und anhand dieser URI z. B. mit RDF Aussagen über dieses Buch treffen:

```
<urn:isbn:978-3-608-96376-2> <http://purl.org/dc/elements/1.1/title> "Kurze Antworten auf große Fragen"
```
Ob die URI nun als urn:isbn oder HTTP-URL angegeben wird, spielt dabei zunächst mal keine Rolle: es ist einfach eine ID, die nicht z. B. via Internet abrufbar sein muss (ähnlich wie bei vielen XML-Namespaces).

Nehmen wir mal an, ich würde statt der URN die URL http://example.com/9783608963762 verwenden. Dann liegt es nahe, unter dieser URL entsprechende Informationen zur Verfügung zu stellen. 

Würde man aber einfach z. B. eine HTML-Seite als Antwort bekommen, hat man das Problem, dass ein und dieselbe URL einerseits das Buch und andererseits die HTML-Seite identifiziert. Da dies der Natur eines Identifikators widerspricht, hat man (denke, es war Tim Berners-Lee) sich überlegt, dass der Server nicht mit Inhalten antworten darf, sondern auf entsprechende URLs verweist (303 See Other). 

Beispielabrufe:

```
# curl -I https://www.wikidata.org/wiki/Special:EntityData/Q341
HTTP/1.1 303 See Other
Location: https://www.wikidata.org/wiki/Special:EntityData/Q341.json

# curl -I "Accept: text/html" https://www.wikidata.org/wiki/Special:EntityData/Q341
HTTP/1.1 303 See Other
Location: https://www.wikidata.org/wiki/Q341
```


----------



## mrBrown (27. Okt 2018)

mihe7 hat gesagt.:


> Dann verstehe ich die Frage nicht: "Kann man ohne Kontext in der URL bei einem POST zwei Resourcen einander zuordnen, ohne zwei Requests absetzen zu müssen?"


zB, das Bild soll dem Nutzer /user/42 zugeordnet werden.
Üblich wäre meistens dann ein POST /user/42/images. Wenn man den Kontext aus der Url weglässt, muss man entweder wieder zwei Requests absetzen, oder /user/42 in Body oder Header mitgegeben, oder nicht?



mihe7 hat gesagt.:


> Klar kannst Du die UUIDs clientseitig generieren, Du weißt aber nicht, welche URL der Server daraus macht.


Der kann die ja als "templated Url" vorgeben.



mihe7 hat gesagt.:


> Nein. Variante 3 bedeutet eine URL, die zwei verschiedene Ressourcen identifiziert -> darf nicht sein.


Ja, wie gesagt bis auf den Unterschied 

Gibts nen sinnvollsten Weg, wie man POST da umsetzt?


----------



## mihe7 (27. Okt 2018)

mrBrown hat gesagt.:


> B, das Bild soll dem Nutzer /user/42 zugeordnet werden.
> Üblich wäre meistens dann ein POST /user/42/images. Wenn man den Kontext aus der Url weglässt, muss man entweder wieder zwei Requests absetzen, oder /user/42 in Body oder Header mitgegeben, oder nicht?



Du bekommst vom Server z. B. für einen Benutzer eine URI mitgeteilt, mit der die "Menge seiner Bilder"  identifiziert wird.

Ob und falls ja, dass in der URI "zufällig" die Benutzer-ID auftaucht, spielt auf Clientseite keine Rolle. Wenn der Server Dir für "die Menge der Bilder des Benutzers 42" die URI /fsda/xsj2904s statt /usr/42/images zurückgibt, und Du den POST ausführst, ist mit der URI trotzdem die "Menge der Bilder des Benutzers 42" identifiziert. 



mrBrown hat gesagt.:


> Der kann die ja als "templated Url" vorgeben.



Schon, aber wozu?


----------



## mrBrown (27. Okt 2018)

mihe7 hat gesagt.:


> Schon, aber wozu?


Die ID/URI ist direkt auf Client-Seite bekannt, ohne Roundtrip zum Server.

Dürfte sowas wie Offline-Fähigkeit leichter machen, oder siehst du das anders?


----------



## mihe7 (27. Okt 2018)

Hm... ich frage mich gerade: kann der Server heute wissen, unter welcher URL er morgen/nächste Woche eine Ressource bereitstellt? Theoretisch sollte das funktionieren.


----------



## mrBrown (27. Okt 2018)

mihe7 hat gesagt.:


> Hm... ich frage mich gerade: kann der Server heute wissen, unter welcher URL er morgen/nächste Woche eine Ressource bereitstellt?


Hm, das Problem hat man aber dann bei jedem PUT, wenn Zeit zwischen GET und PUT vergeht?


----------

