Skip to end of metadata
Go to start of metadata


Mit dem APICall Step kann man auf HTTP-basierte APIs und Schnittstellen zugreifen und die Antwort direkt in eine Spreadsheet einlesen. Dabei unterstützt der Step die Verarbeitung von XML und JSON Antworten. 

Die Besonderheiten dieses Steps sind:

  • Antworten im XML bzw. JSON Format können direkt im Step verarbeitet werden
  • Unterstützung für Pagination (das sog. "Weiterblättern", falls es weitere Ergebnisse für die Abfrage gibt)


Tutorial: REST-API Anbindung

Lernen Sie in unserem Tutorial REST API Anbindung mit Synesty, wie man jede beliebige HTTP-API mit JSON oder XML anbinden kann - auch ohne Add-Ons von Synesty und ohne Programmierung in PHP, Java oder Javascript.

Unterschied zwischen APICall, SpreadsheetURLDownload und URLDownload

Dieses Cookbook beschreibt den Unterschied der drei Steps.

HTTP Request und Response-Verarbeitung in einem

Der APICall Step vereint im Grunde genommen den URLDownload und den JSON2Spreadsheet bzw. XML2Spreadsheet in einem Step. 
D.h. man kann HTTP-Requests ausführen und gleich die Antwort verarbeiten - in einem einzigen Step. 

Oben drauf kann man den Step auch noch anweisen, weitere Requests (Calls) auszuführen, um sich z.B. durch ein API-Suchergebnis zu "blättern". Das wird unter Pagination beschrieben. 

D.h. umgangssprachlich kann man damit Szenarien wie diese Realisieren:

  1. Rufe 1. Seite mit Produkten ab
  2. Gibt es noch weitere Ergebnisse auf der nächsten Seite?
  3. Wenn ja: Rufe 2. Seite mit Produkten ab.
  4. Gibt es noch weitere Ergebnisse auf der nächsten Seite?
  5. Wenn ja: Rufe 3. Seite mit Produkten ab.
  6. Gibt es noch weitere Ergebnisse auf der nächsten Seite?
  7. Nein. Ende der Verarbeitung.


Aufbau


Die Screenshots zeigen die elementaren Felder:

  • host - die Aufzurufende initiale URL
  • method - die HTTP Methode (GET, POST, PUT...)
  • responseFormat - Das Format der Response. JSON oder XML.  Damit wird im Hintergrund der zu verwendende Parser definiert. 
  • parsingTemplate - der Parsing Code analog zum Step JSON2Spreadsheet oder XML2Spreadsheet, je nach gewähltem responseFormat. Mit diesem Script wird die Response in ein Spreadsheet umgewandelt. 


Pagination

Die APICall Step kann im Vergleich zum URLDownload Step auch mehrere URLs hintereinander aufrufen, also das Weiterblättern und Aufrufen der nächsten Seite, so lange, bis das Ende der Ergebnisse erreicht ist. Dafür dient die Funktion nextUrl(), die im parsingTemplate verwendet werden kann, z.B.

1. Call: http://api.myshop.com/getproducts
2. Call: http://api.myshop.com/getproducts?page=2
3. Call: http://api.myshop.com/getproducts?page=3

etc.


Beispiel parsingTemplate

Dieses Beispiel, welches immer wieder die initiale URL (host) aufruft und einen page= Parameter mit einer hochzählenden Zahl anhängt, damit die nächste Seite aufgerufen wird. 

Beispiel parsingTemplate
<#assign row = target.addRow()>
 
<#assign numRows = 0 />
 
<#list json as p>
 <#assign row = target.addRow()>
    ${addColumns(row, p['product'])}
    <#assign numRows = numRows + 1 />
</#list>
 
 
<#if (numRows > 0 && callcounter < callLimit)>
    <#assign nextPageNumber = (callcounter + 1)>
    ${nextUrl(initialUrl+"&page="+nextPageNumber)}
</#if>

Es wird die Variable callcounter verwendet, welche die bisher gemacht Anzahl Calls enthält.
D.h. beim ersten erreichen der nextUrl() Funktion, ist callcounter=1. Deshalb wird nextPageNumber = callcounter + 1 gesetzt, der nächste Seitenaufruf page=2 ist.

Die umschließende IF-Bedingung <#if (numRows > 0 && callcounter < callLimit)> ist notwendige Abbruchbedingung, damit keine Endlosschleife entsteht und die nextURL unendlich oft aufgerufen wird. 
Sie bedeutet ungefähr: "wenn der erste Call Zeilen im Ergebnis hatte (numRows > 0), und wir noch innerhalb des CallLimits sind (callcounter < callLimit) dann mache weiter und rufe die nextUrl() auf. 



Beispiel 2:
Hier ein Beispiel für den Inhalt des parsingTemplates. Im Bespiel liefert die Antwort der API eine Liste von Produkten zurück. Durch erneuten Aufruf der URL mit einem zusätzlichen offset Parameter, kann man die nächsten Produkte des Ergebnis abrufen - immer in Blöcken von 150 Produkten.  

<#assign row = target.addRow()>
 
<#assign numRows = 0 />
 
<#list json as p>
 <#assign row = target.addRow()>
    ${addColumns(row, p['product'])}
    <#assign numRows = numRows + 1 />
</#list>
 
<#if (numRows > 0 && callcounter < callLimit)>
    <#assign offset = ((callcounter) * 150)>
    ${nextUrl(initialUrl+"&offset="+offset)}
</#if>
 

Der Unterschied zum obigen Beispiel ist, dass der offset Parameter etwas anders berechnet werden muss. Wir gehen hier davon aus, dass 150 Produkte pro Seite kommen und die API statt Seitenzahl (page) den Versatz (offset) bekommen möchte. D.h.
statt page=2 wird offset=150 geschickt (callcounter * 150  = 1 * 150 = 150). Damit weiss die API, dass sie die ersten 150 Produkte überspringen soll. page=3 würde dann mit offset=300 aufgerufen. 



Variablen: Folgende Variablen sind vom Step immer verfügbar


  • initialUrl - die initiale URL, also das was in host steht
  • callcounter - ein Zähler für die Anzahl calls, die schon gemacht wurden. startet bei 0
  • callLimit - entspricht der limit-Variable des APICall Steps und gibt die max. Anzahl auszuführender Calls an. Bitte beim Testen auf kleine Werte z.B. 5 setzen um zu vermeiden.

 Die Variablen und Funktionen können durch das Plus-Zeichen am parsingTemplate angezeigt werden.


Angenommen die erste URL wäre http://api.myshop.com/getproducts, dann würde obiges Script zum Aufruf folgender URLs führen:


1. http://api.myshop.com/getproducts
2. http://api.myshop.com/getproducts&offset=150
3. http://api.myshop.com/getproducts&offset=300
4. http://api.myshop.com/getproducts&offset=450

etc.


In der Programmierung würde das vermutlich einer do-while Schleife entsprechen. D.h. der APICall step versucht immer die von nextUrl() gesetzte URL aufzurufen. Wird nextUrl() nicht aufgerufen, dann wird auch kein weiterer Call gemacht. D.h. die Endbedingung ist hier:

<#if (numRows > 0 && callcounter < callLimit)>

D.h. es muss noch Produkte in der Response geben, und es dürfen nur max. 5-Calls gemacht werden. 


Variablen für nächsten Call setzen

Es gibt Fälle, da will man eine Variable setzen, die aber erst im nächsten Call z.B. requestBody gebraucht wird. 
Das kann man mit der Funktion setVariable() erreichen. 

${setVariable("myvar", "myvalue")}

Diese Variable ist dann im nächsten Call in allen Freemarker-fähigen Feldern wie requestBody, requestHeaders oder parsingTemplate als ${myvar} verfügbar. 

Beispiel:

Angenommen die Response des 1. Calls liefert einen Token zurück, der im 2. Call per requestBody oder requestHeader übergeben werden muss.

D.h. man muss sich diesen Token im parsingTemplate aus der response extrahieren und mit setVariable("mytoken", token) merken. Der nächste Call (definiert durch nextUrl()) hat dann diese Variable als normale Freemarker Variable ${mytoken} verfügbar.


HTTP Error Codes

Im Feld errorStatusCodes können sie konfigurieren welche HTTP Status als Fehler gewertet werden. Standardmäßig (leeres Feld) sind Antworten mit einem HTTP-Statuscode größer oder gleich 300 ein Fehler. Im Falle einer Weiterleitung (Status 3xx) bei einem GET Request wird der Status Code zur weitergeleiteten URL ausgewertet.

Sie können auch individuelle Status als Komma-separierte Liste im Feld angeben. Es ist auch möglich die Status in Form von Regulären Ausdrücken anzugegeben.

Beispiele:

  • leer -> Fehler bei Status >= 300
  • 401,407 -> Fehler bei Status Code 401 & 407
  • 40[0-7],5[0-9][0-9] -> Fehler bei Status Code 400 bis 407 und 500 bis 599
  • 40[135] -> Fehler bei Status Code 401, 403 und 405
  • 3.*,4.*,5.* -> Fehler bei 300 – 599


HTTP Multipart Requests

Eine spezielle Form von Request stellen sog. Multipart Requests (siehe hier). Dabei werden mehrere verschiedene Daten in einem Request kombiniert gesendet (z.B. eine Datei zusammen mit einem JSON-Body). Ein typisches Beispiel sind Webformulare im Browser, wo mehrere Formularfelder und ein Datei-Upload übertragen werden (z.B. Kontaktformular mit Dateiupload). Diese werden in der Regel als Multipart-Request realisiert.
Einige APIs, die man anbindet verlangen manchmal auch den ContenType=multipart/form-data; charset=ISO-8859-1

Alle HTTP-Steps APICall, SpreadsheetURLDownload und URLDownload unterstützen HTTP Multipart-Requests.

Dazu muss die Option bodyContentType auf multipart/form-data gestellt werden. 

Bei bodyContentType=multipart/form-data kann man die Form-Parameter übermitteln z.B. &param1=value1&param2=value2 (wenn die URL/host keine Parameter hat, dann ohne das erste &-Zeichen). Es ist auch für bessere Lesbarkeit möglich, pro Zeile einen Parameter zu verwenden. Wichtig ist, dass der Wert keine Zeilenumbrüche beinhaltet. Für mehrzeilige Werte sollte die Freemarker <#compress> function probiert werden.

Ergebnis:

Ein POST-Request z.B. an ein Tool wie RequestBin sähe damit aus wie folgt:

RequestBody bei Multipart

Das man bei bodyContentType=multipart/form-data das Feld requestBody auf diese Art mit mehreren Parametern befüllen kann ist eine Besonderheit von Multipart Requests. Für alle anderen Werte bei bodyContentType wird der RequestBody nicht derart interpretiert sondern so übermittelt wie er ist. D.h. will man z.B. ein JSON-Dokument als ganzes übermitteln (wie es bei 90% aller REST-APIs der Fall ist), dann beinhaltet der requestBody nur das JSON.



Unterschied zum SpreadsheetURLDownload

Auch der SpreadsheetURLDownload ist in der Lage mehrere URLs aufzurufen. Der Unterschied ist, dass die URLs beim SpreadsheetURLDownload da schon vorher feststehen und als Spreadsheet hinein gegeben werden - mit einer URL pro Zeile.

Der APICall ist dahingehend dynamisch. Es ist vorher nicht bekannt, wieviele URLs / Calls aufgerufen werden, da es von der Antwort abhängt, ob der Aufruf der nächsten URL (nextUrl()) stattfindet oder nicht. 


  • No labels