digitalisiertes Bild aus dem Rijksmuseum abzurufen und lokal zu speichern. In diesem nächsten Teil werden wir diese Integration erweitern, indem wir es an die Meural API senden, um das Bild auf unserer digitalen Leinwand anzuzeigen.
Um den Blog in einer vernünftigen Größe zu halten, implementiere ich nicht alles, was normalerweise erforderlich wäre, wenn man dies in der Realität tun würde.
Konkret implementiere ich nicht den Aufruf zum Abrufen eines Tokens, das benötigt wird, wenn man etwas auf seine eigene Meural hochlädt. Ich implementiere auch nicht alle zusätzlichen Funktionen, die die API bietet, wie z.B. das Erstellen von Sammlungen und ähnliches.
Was ich jedoch tue, ist die Kunstwerke hochzuladen, damit sie auf dem mobilen Gerät verfügbar sind. Vom mobilen Gerät aus wähle ich dann die Bilder aus und sende sie auf die Leinwand.
Ich kann mir vorstellen, dass du kein Meural Canvas 2 hast. In diesem Fall wäre es schwer, mitzumachen, aber im Allgemeinen gibt es auch Wert darin zu wissen, wie man eine Nachrichten-Payload ändert, um eine Verbindung zu einer API wie der von Meural herzustellen.
Die Vorbereitung
Um dies selbst auszuprobieren, benötigst du Folgendes
- Eine Version des Micro Integrator (Ich verwende Version 4.2.0)
- Integration Studio um die Artefakte zu entwickeln, die wir bereitstellen werden (Ich verwende Version 8.2)
- Einen API-Schlüssel vom Rijksmuseum, um ihre API nutzen zu können
- Eine Meural-Leinwand, wenn du den vollständigen Ablauf haben möchtest. Andernfalls kannst du das Bild lokal speichern
Was haben wir?
Was wir derzeit haben, ist eine API, die in der Lage ist, eine Reihe von Objektnummern zu empfangen, die mit einem digitalen Kunstwerk wie einem Gemälde oder einer Zeichnung aus der Rijksstudio übereinstimmen. Die API iteriert durch die wiederkehrenden Elemente der Payload (in diesem Fall die Objektnummern). Für jede dieser Nummern wird versucht, Informationen über das Objekt abzurufen und eine Download-URL, über die wir die Datei tatsächlich herunterladen können. Diese Datei wird dann lokal auf unserem Laufwerk gespeichert, und im letzten Schritt werden wir diese Datei an die Meural API senden.
Ich habe einige der Mediation herausgeschnitten, die ich in den vorherigen Blogs behandelt habe, da sich daran nichts geändert hat. Du wirst die drei Punkte <…> </…> im Code sehen, wo ich Teile weggelassen habe. Ich habe auch Änderungen an der Einrückung vorgenommen, um mehr auf eine Zeile zu passen, und den Token entfernt, der verwendet wurde, sowie den Schlüssel, um die ursprünglichen Informationen vom Rijksmuseum abzurufen.
Was ist neu?
Was ich getan habe, ist eine neue Eigenschaft eingeführt, die die Anzahl der Elemente im Array zählt. Diese Eigenschaft json-eval($.object.length()) speichert den Wert in einer Eigenschaft namens „totalobjects“, und dieser Wert wird nach der Iteration in einer benutzerdefinierten Payload zurückgegeben, die die Anzahl der verarbeiteten Objekte angibt.
<?xml version="1.0" encoding="UTF-8"?>
<api context="/art" name="Meural" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<property expression="json-eval($.object.length())" name="totalobjects" scope="default" type="STRING"/>
<iterate attachPath="json-eval($.object)" continueParent="true" expression="json-eval($.object)" id="it1" preservePayload="true" sequential="true">
<target>
<sequence>
<...> </...>
<property expression="fn:concat('/opt/wso2/Downloads/',get-property('objectnr'),'.jpg')" name="fp" scope="default" type="STRING"/>
<enrich>
<source clone="false" type="body"/>
<target property="ORIGINAL_PAYLOAD" type="property"/>
</enrich>
<file.write configKey="FC1">
<...> </...>
</file.write>
<enrich>
<source clone="false" property="ORIGINAL_PAYLOAD" type="property"/>
<target type="body"/>
</enrich>
<property name="DECODE_MULTIPART_DATA" scope="axis2" type="BOOLEAN" value="true"/>
<property expression="//ns:binary" name="Message" scope="default" type="STRING" xmlns:ns="http://ws.apache.org/commons/ns/payload"/>
<payloadFactory media-type="xml">
<format>
<root xmlns="">
<file Content-Type="image/jpeg" filename="$1" name="image" xmlns="http://org.apache.axis2/xsd/form-data">$2</file>
</root>
</format>
<args>
<arg evaluator="xml" expression="$ctx:fp"/>
<arg evaluator="xml" expression="get-property('Message')"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="multipart/form-data"/>
<header name="Content-Type" scope="transport" value="multipart/form-data"/
<property name="DISABLE_CHUNKING" scope="axis2" type="STRING" value="true"/>
<header name="Authorization" scope="transport" value="Token {TOKEN]"/>
<call blocking="true">
<endpoint>
<http method="post" uri-template="https://api.meural.com/v0/items">
<...> </...>
</http>
</endpoint>
</call>
<drop/>
</sequence>
</target>
</iterate>
<property expression="count(//retrieve/object)" name="TotalElements" scope="default" type="STRING"/>
<payloadFactory media-type="json">
<format>{"Message" : "$1 Images uploaded"}</format>
<args>
<arg evaluator="xml" expression="get-property('totalobjects')" literal="true"/>
</args>
</payloadFactory>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
/resource>
</api>
Ich habe einen neuen Mediator namens „enrich“ eingeführt, um die ursprüngliche Payload beim Abrufen des Bildes vom Rijksmuseum zu speichern. Ich tue dies, weil ich die Payload nicht verlieren möchte, wenn der Dateikonnektor sie mit seiner Antwort überschreibt. Daher speichert der „enrich“ Mediator die Payload in einer Eigenschaft. Wir setzen die Mediation fort, und wenn wir fertig sind und in diesem Fall nichts mit der Payload machen müssen, die möglicherweise vom Dateikonnektor erstellt wurde, stellen wir die ursprüngliche Payload aus der Eigenschaft wieder her, um sie zu verwenden.
Die folgende Mediationssequenz wird zum Teil durch die Erwartungen der Meural API und zum Teil durch die Funktionsweise des Micro Integrator bestimmt.
Mit dem „property“ Mediator setze ich zwei Werte, die benötigt werden. Ich setze DECODE_MULTIPART_DATA auf true, damit wir die Nachricht nicht codieren, und setze die Eigenschaft Message auf „binary“.
Der nächste Schritt verwendet den „payloadFactory“ Mediator, um eine Nachricht zu erstellen, die von der Meural API benötigt wird.
In diesem „payloadFactory“ Mediator siehst du zwei Werte, die mit dem $-Zeichen beginnen, $1 und $2. Diese werden mit den Argumenten gefüllt, die du unterhalb des „format“-Abschnitts findest. Der erste ist der Dateiname und der zweite ist der Nachrichtentyp.
Es folgen drei weitere Mediationszeilen, in denen der Inhaltstyp auf multipart/form-data gesetzt wird, DISABLE_CHUNKING auf true gesetzt wird und schließlich der Token zum Header hinzugefügt wird, um diesen API-Aufruf zu authentifizieren.
Ich habe den Token entfernt, da es sich um sensible Informationen handelt, die niemals geteilt werden sollten, auch nicht, wenn er abgelaufen ist. Ein abgelaufener Token kann nicht verwendet werden, aber im Allgemeinen ist es eine gute Idee, niemals Tokens, Client-Schlüssel, Client-Geheimnisse oder API-Schlüssel zu teilen. Indem du sie zu keinem Zeitpunkt teilst, reduzierst du das Risiko von Fehlern, versehentlichem Teilen usw.
Lösche die Nachricht
Am Ende der Iteration-Mediation siehst du, dass wir die Nachricht tatsächlich abgebrochen haben, weil wir nicht am Ergebnis der Meural API interessiert sind. Wir gehen davon aus, dass alles korrekt ist, und wir unternehmen nichts im Bereich der Fehlerbehandlung.
In der realen Welt solltest du das natürlich berücksichtigen und sicherstellen, dass du die Fehlerbehandlung auf angemessene Weise durchführst.
Aber das Schöne am Schreiben eines Blogs ist, dass wir es ein wenig abstrahieren können und uns keine Sorgen um jedes denkbare Szenario machen müssen.
Wenn wir die Iteration durch das JSON-Array abgeschlossen haben, wird die Mediation mit der nächsten Zeile fortgesetzt, die uns die Gesamtzahl der abgerufenen Objekte liefert und sie an die Meural API übermittelt.
Dies ist der Wert, mit dem wir gestartet sind, als die Nachricht in die API kam, wo wir die Anzahl der Elemente gezählt haben.
In meiner Meural-App habe ich jetzt eine große Anzahl von Kunstwerken, die ich nun auf die Leinwand schieben kann. Dies könnte ich auch automatisieren, aber für diesen Blog behalte ich es als manuelle Aufgabe bei. Ansonsten würde ich, wenn ich nicht vorsichtig bin, mit Teilen 4 und 5 enden. Du findest die s mit den Kunstwerken auf Yenlo Bitbucket.
Du kannst sehen, dass Integration nicht nur für Künstler, sondern für nahezu jeden Entwickler ist. Du kannst die erforderliche Integration entwickeln, um die Rijksstudio mit Meural zu verbinden, aber andere können das auch tun.
Für Meural kann dies Teil ihres Abonnements für kuratierte Kunst sein, das sie gegen eine monatliche oder jährliche Gebühr anbieten. Es gibt also einen Vorteil für Meural/Netgear, solche Verbindungen zu Museumsressourcen direkt zu entwickeln. Für das Rijksmuseum ermöglicht es das Definieren einer Schaltfläche auf der Website, um direkt an einen Benutzer Meural zu senden, dass Menschen Kunst mit nahezu keiner Arbeit mehr genießen können. Es wird die Beteiligung an der Rijksstudio steigern. Sie können digitalisierte Bilder von Ausstellungen, die Menschen besucht haben, auf die Meural zu Hause schicken. Der Himmel ist die Grenze. Das ist es, was ich „Digitale Vorstellungskraft“ nenne.
Digitale Vorstellungskraft
Ich werde auch untersuchen, was du mit einer API wie dieser tun kannst, wenn man bedenkt, dass viele Ressourcen eine API-Schnittstelle haben und es tatsächlich ziemlich einfach ist, eine Verbindung herzustellen.
Ich spreche nicht nur von Museen und ihrer Kunstsammlung, sondern auch von der Google Photos API, in der du vielleicht all deine Urlaubsfotos speicherst.
Die Mechanismen, die ich in diesen Blogs in den Teilen 1,2 und 3 zeige, können auch auf die Google API angewendet werden.
Natürlich gibt es Änderungen, die du vornehmen musst, da nicht jede API gleich ist.
Im Gegenteil, Organisationen haben viele Freiheiten, APIs in beliebiger Form zu erstellen. Natürlich gibt es Puristen, die eine sehr enge Sichtweise darauf haben, was eine API ist, aber letztendlich liegt es nicht bei den Puristen. Es liegt an der Organisation, den Architekten und den Entwicklern, festzulegen, wie sie die APIs aufbauen, Benennungsrichtlinien und andere Richtlinien festzulegen.
Sicherheit
Was die Sicherheit betrifft, denke ich, dass wir noch viel tun können, um APIs sicherer zu machen, denn APIs sind die Tür zu den von einer Organisation angebotenen Diensten, und wenn es eine Sache gibt, auf die man sich verlassen kann, dann ist es, dass deine API angegriffen wird. Eine API-Management-Lösung in Kombination mit Schema-Validierung unter Verwendung von OpenAPI 3.0-Beschreibungen macht deine APIs sicherer. Aber es geht auch darum, sicherzustellen, dass alle Systeme auf dem neuesten Stand sind, damit es keine nicht behobenen Schwachstellen gibt, aber auch dass der Transport zwischen der Person, die die API aufruft, und dem Backend sicher ist.
In Bezug darauf, aus der Sicht des Backends, schau dir die Liste der Sicherheitslücken von OWASP 2023 an. Sie zeigt dir die häufigsten Fehler, die Menschen machen, wenn sie eine API in Bezug auf das Frontend erstellen. Eine API-Management-Lösung ist meiner Meinung nach ein Muss für jede Organisation, die APIs und sich selbst ernst nimmt. Schließlich ist Sicherheit keine nachträgliche Überlegung, sondern ein Prinzip, das von Anfang an angewendet werden sollte.