restclient — n_pbt_restclient #
← Komponentenreferenz · Inhalt des Handbuchs
Ein HTTPS-Client für PowerBuilder, Version 10 eingeschlossen: GET, POST, PUT, PATCH, DELETE, Header, ein JSON-Körper, ein Datei-Download. Nativ — TLS, Proxy und Dekompression des Systems, und keine CORS-Mauer, weil die Anfrage nicht von einer Seite ausgeht.
▶ Live ansehen — Demoanwendung, Kachel REST client: die Antworten, der Code, der sie holt, und diese Seite nebeneinander (Internetverbindung erforderlich).
Kurzüberblick #
| Nichtvisuelles Objekt | n_pbt_restclient |
| Wofür | Eine REST-API aus einer PowerBuilder-Anwendung aufrufen: lesen, anlegen, aktualisieren, herunterladen |
| Prinzip | Eine Anfrage ist ein Aufruf, der den HTTP-Status liefert; die Antwort wartet im Objekt, gelesen per of_response_text oder of_json_value |
| Abhängigkeit | WinHTTP in der DLL der Bibliothek — keine Seite, keine zusätzliche Runtime |
Schnellstart #
// Local variables
n_pbt_restclient lnv_rest
n_pbt_json lnv_j
long ll_status
// One client for the API : its address and the token it sends
lnv_rest = create n_pbt_restclient
lnv_rest.is_base_url = "https://api.example.com"
lnv_rest.of_set_bearer(/*token*/ ls_token)
// Read : the status comes back, the body waits in the object
ll_status = lnv_rest.of_get(/*url*/ "/orders/4152")
if ll_status = 200 then ls_customer = lnv_rest.of_json_value(/*path*/ "customer")
// Create : the body is built with n_pbt_json, never by hand
lnv_j.of_set_number(/*path*/ "order", /*value*/ 4152)
lnv_j.of_set_string(/*path*/ "status", /*value*/ "shipped")
ll_status = lnv_rest.of_post(/*url*/ "/shipments", /*body*/ lnv_j.of_text())
if ll_status < 0 then MessageBox("API", lnv_rest.is_last_error)
// The client is no longer needed
destroy lnv_rest
Jede HTTP-Methode liefert den Status, den der Server gewählt hat — ein 404 ist eine Antwort, kein Fehler — oder einen negativen Code, wenn die Anfrage nicht durchging: -5 ungültige URL oder ungültiger Header, Client-Zertifikat nicht gefunden, -4 Fehlschlag (kein Netz, unbekannter Name, Zeitüberschreitung, TLS, ein Textkörper über 64 MB — 16 MB in einem 32-Bit-Prozess; is_last_error sagt, welcher), -6 im Demomodus abgelehnt.
Warum nativ, und nicht die Seite #
Ein fetch() aus einer Seite der Bibliothek unterliegt CORS: jede API, die kein Access-Control-Allow-Origin sendet, ist ihm verschlossen — und Unternehmens-APIs senden es nicht. Die Anfrage geht daher von der DLL aus, über WinHTTP: das TLS des Systems mit seinen Zertifikaten, der konfigurierte Proxy, gzip. Was Sie verlieren: nichts; was Sie gewinnen: jede API.
Eigenschaften #
| Eigenschaft | Typ | Standard | Rolle |
|---|---|---|---|
is_base_url | string | "" | Vor eine relative URL gesetzt: is_base_url = "https://api.example.com", dann of_get("/orders/4152"). Eine absolute URL wird unverändert verwendet |
il_timeout_ms | long | 30000 | Wie lange jeder Schritt einer Anfrage dauern darf: Namensauflösung, Verbindung, Senden, dann das Warten auf jeden Block der Antwort. Ein großer Download, der vorankommt, wird nie abgebrochen; ein Server, der so lange schweigt, schon: -4 und „timed out“. 0 oder weniger bedeutet den Standard, 30 s: ein „kein Zeitlimit“ gibt es nicht |
is_last_error | string | "" | Warum die letzte synchrone Anfrage — oder ein sofort abgelehnter asynchroner Aufruf — einen negativen Code lieferte. Leer nach einer Anfrage, die den Server erreicht hat — ein 404 ist kein Fehler. Ein asynchroner Fehlschlag nennt seinen Grund in ue_failed |
il_status | long | 0 | Der HTTP-Status der letzten synchronen Anfrage oder ihr negativer Code; der Wert, den die Anfrage lieferte. Eine asynchrone Antwort hat ihren eigenen: of_status(id) |
ib_keep_cookies | boolean | true | Behält die Cookies zwischen Anfragen — synchronen und asynchronen, die eine Sitzung teilen: eine API, die beim Anmelden ein Cookie setzt, hält Sie angemeldet. Bei false wird kein Cookie mehr gesendet oder behalten, und die bisher behaltenen werden vergessen; sofort wirksam |
il_max_retries | long | 0 | Wie oft eine asynchrone Anfrage bei 429, 503 oder einem Netzfehler wiederholt wird. Ein POST, dessen Antwort verloren ging, wird nie wiederholt: er könnte verarbeitet worden sein. Ein Fehlschlag, der sich genauso wiederholen würde, wird nie wiederholt: zu viele Umleitungen, ungültige Umleitung, abgelehnte Umleitung HTTPS → HTTP, TLS-Fehler, nicht schreibbare Datei |
il_retry_backoff_ms | long | 500 | Die Wartezeit vor dem ersten Wiederholungsversuch in Millisekunden, bei jedem Versuch verdoppelt und auf 60 s begrenzt. Ein Retry-After-Header des Servers (Sekunden oder Datum) hat Vorrang |
ib_windows_auth | boolean | false | Integrierte Windows-Authentifizierung (Negotiate / NTLM): verlangt ein Server sie — eine IIS-API im Intranet —, antworten die Anmeldedaten der Windows-Sitzung, ohne Eingabe. Standardmäßig aus: ohne sie werden sie nie gesendet, an keinen Server. Bei jeder Anfrage gelesen |
is_client_certificate | string | "" | Ein Client-Zertifikat (gegenseitiges TLS): der SHA-1-Fingerabdruck eines Zertifikats aus dem persönlichen Speicher — dem des Benutzers, dann dem des Computers —, wie die Zertifikatverwaltung ihn anzeigt; Leerzeichen und Doppelpunkte werden ignoriert. Leer = keines. Ein nicht gefundener Fingerabdruck lässt jede Anfrage -5 liefern („client certificate not found“). Bei jeder Anfrage gelesen. Eine Option, einen Zertifikatfehler des Servers zu ignorieren, gibt es nicht |
ipo_owner | powerobject | null | Das visuelle Objekt, für das dieser Client arbeitet: die Lizenz wird an seiner Klasse geprüft. Nur in der Demoanwendung nötig; ein Entwicklungs- oder Laufzeitschlüssel schaltet den Client ohne es frei. Nicht freigeschaltet läuft der Client im Demomodus — Körper bei 4096 Zeichen abgeschnitten, weder Download noch Upload |
Konstanten: METHOD_GET, METHOD_POST, METHOD_PUT, METHOD_PATCH, METHOD_DELETE für of_request.
Methoden #
| Methode | Rolle |
|---|---|
of_set_header (string as_name, string as_value) → long | Ein Header, der ab jetzt mit jeder Anfrage gesendet wird; ein bereits gesetzter Name wird ersetzt, ein leerer Wert entfernt den Header. Content-Type wird von selbst ergänzt, wenn ein Körper ohne ihn gesendet wird (JSON, UTF-8); bei einem Upload wird der hier gesetzte ignoriert (multipart/form-data setzt die Bibliothek). Keiner dieser Header folgt einer Umleitung auf einen anderen Host. Liefert 0, oder -5 — nichts ändert sich — für einen leeren Namen, einen Namen mit Leerzeichen, Doppelpunkt oder Steuerzeichen, oder einen Wert mit Zeilenumbruch |
of_remove_header (string as_name) | Vergisst einen Header, nach Name (Groß-/Kleinschreibung egal) |
of_clear_headers ( ) | Vergisst alle Header, Authentifizierung eingeschlossen |
of_set_bearer (string as_token) → long | Authorization: Bearer bei jeder Anfrage. Eine Authentifizierung zur Zeit: es ersetzt eine Basic-Authentifizierung; ein leeres Token entfernt die Authentifizierung. Liefert 0, oder -5 für ein Token mit Zeilenumbruch — dann bleibt keine Authentifizierung, nie eine halbe |
of_set_basic (string as_user, string as_password) → long | Basic-Authentifizierung; die DLL kodiert das Base64 selbst — PowerBuilder 10 hat keines. Sie ersetzt ein Bearer-Token; ein leerer Benutzer entfernt die Authentifizierung. Liefert 0, oder -5 für einen Benutzer oder ein Kennwort mit Zeilenumbruch — dann bleibt keine Authentifizierung |
of_get (string as_url) → long | GET. Liefert den HTTP-Status, oder -5 ungültige URL oder ungültiger Header, Client-Zertifikat nicht gefunden, -4 Fehlschlag, -6 in der Demo abgelehnt. Das Fragment #… einer URL wird nie an den Server gesendet |
of_post (string as_url, string as_body) → long | POST mit einem Körper (standardmäßig JSON, mit n_pbt_json gebaut). Liefert den HTTP-Status oder -5 / -4 / -6 |
of_put (string as_url, string as_body) → long | PUT mit einem Körper. Liefert den HTTP-Status oder -5 / -4 / -6 |
of_patch (string as_url, string as_body) → long | PATCH mit einem Körper. Liefert den HTTP-Status oder -5 / -4 / -6 |
of_delete (string as_url) → long | DELETE. Liefert den HTTP-Status oder -5 / -4 / -6 |
of_request (string as_method, string as_url, string as_body) → long | Jede Methode (METHOD_* oder eine eigene), jeder Körper als UTF-8: was die fünf Kurzformen aufrufen. Liefert den HTTP-Status oder -5 / -4 / -6 |
of_download (string as_url, string as_path) → long | GET direkt in eine Datei, Bytes unverändert, unabhängig von der Größe. Liefert den HTTP-Status oder -5 URL oder Pfad leer, -4 Fehlschlag, -6 in der Demo verweigert. Ein relativer Pfad wird beim Aufruf im aktuellen Ordner der Anwendung beim Laden der Bibliothek aufgelöst — nie dort, wohin ein DirList oder ein Dateidialog ihn seitdem verschoben hat |
of_response_text ( ) → string | Der Körper der letzten synchronen Antwort dieses Objekts — ein anderer Client überschreibt ihn nicht —, als Text: dekodiert nach dem vom Server angekündigten charset (UTF-8 und die älteren Zeichensätze: windows-125x, iso-8859-x, shift_jis, gbk/gb2312, big5, euc-kr, koi8-r…), standardmäßig UTF-8 (ein ungültiges Byte wird zum Ersatzzeichen). Leer nach einem Fehlschlag und nach of_download: dieser Körper steht in der Datei. Ein Textkörper ist auf 64 MB begrenzt, 16 MB in einem 32-Bit-Prozess: darüber -4 „body too large“ — verwenden Sie of_download |
of_response_headers ( ) → string | Alle Header der letzten synchronen Antwort, einer pro Zeile |
of_response_header (string as_name) → string | Ein Header der letzten synchronen Antwort, nach Namen; leer, wenn er nicht gesendet wurde |
of_json_value (string as_path) → string | Ein Wert des JSON-Körpers nach seinem Pfad — Schlüssel durch / verbunden, Array-Positionen ab 1, die Schreibweise von n_pbt_json: "customer", "json/customer", "items/1/qty". Eine Zeichenkette kommt dekodiert zurück, eine Zahl oder true/false wie geschrieben ("4152"), null leer, ein Objekt oder Array als JSON; leer, wenn der Pfad nicht existiert. Für mehr als einen Wert laden Sie of_response_text in ein n_pbt_json. Der Körper wird pro Antwort nur einmal analysiert: zehn Werte zu lesen kostet eine einzige Analyse |
of_reset ( ) | Zurück zu den Standardwerten: kein Header, keine Basis-URL, die Standard-Zeitüberschreitung, keine Wiederholung, Cookies behalten; der Client wird geschlossen — seine Cookies gehen, seine laufenden Anfragen werden ohne Ereignis abgebrochen — und die letzte Antwort wird vergessen. Die Windows-Authentifizierung wird ausgeschaltet (ib_windows_auth = false) und das Client-Zertifikat vergessen (is_client_certificate = "") |
Beispiele #
Eine Liste lesen und durchgehen #
// Local variables
string ls_body, ls_id
n_pbt_json lnv_list
long ll_i
// One value : of_json_value("items/1/id"). The whole list : load the body into an
// n_pbt_json and walk it by path.
if lnv_rest.of_get(/*url*/ "/orders?status=open") = 200 then
ls_body = lnv_rest.of_response_text()
lnv_list.of_load(/*json*/ ls_body)
for ll_i = 1 to lnv_list.of_count(/*path*/ "items")
ls_id = lnv_list.of_get_string(/*path*/ "items/" + String(ll_i) + "/id")
next
end if
Ein Dokument herunterladen #
// Local variables
long ll_status
// Download the invoice to a file, then open it
ll_status = lnv_rest.of_download(/*url*/ "/orders/4152/invoice.pdf", /*path*/ "C:\temp\invoice-4152.pdf")
if ll_status = 200 then
Run("C:\temp\invoice-4152.pdf")
elseif ll_status < 0 then
MessageBox("Download", lnv_rest.is_last_error)
end if
Eine API, die mit einem Fehler antwortet #
// The status decides : 200 or 201 = created, 401 = the token expired,
// below 0 = the network failed
choose case lnv_rest.of_post(/*url*/ "/shipments", /*body*/ ls_body)
case 200, 201
case 401
MessageBox("API", "Token expired : " + lnv_rest.of_json_value(/*path*/ "message"))
case is < 0
MessageBox("Network", lnv_rest.is_last_error)
end choose
Eine Intranet-API mit Windows-Authentifizierung #
// Local variables
n_pbt_restclient lnv_rest
long ll_status
// An IIS API of the intranet : the Windows session answers the server's challenge,
// nothing is typed. Off by default : switch it on for this client only.
lnv_rest = create n_pbt_restclient
lnv_rest.is_base_url = "https://erp.intranet.local/api"
lnv_rest.ib_windows_auth = true
// A header refused (a line break in the value) returns -5 and is not set
if lnv_rest.of_set_header(/*name*/ "X-Client", /*value*/ "PowerBuilder") < 0 then return
// Read an order : 401 when the server refused the Windows account
ll_status = lnv_rest.of_get(/*url*/ "/orders/4152")
if ll_status = 401 then
MessageBox("ERP", "Access denied")
elseif ll_status < 0 then
MessageBox("ERP", lnv_rest.is_last_error)
end if
// The client is no longer needed
destroy lnv_rest
Asynchron (ohne die Oberfläche einzufrieren) #
Während eines synchronen Aufrufs ist die Oberfläche bis zur Antwort eingefroren: das Fenster zeichnet sich nicht mehr neu und reagiert nicht mehr auf Klicks. Bei einem kurzen Aufruf ist das folgenlos; für jeden Aufruf, der dauern kann — ein langsamer Server, ein großer Körper, ein unsicheres Netz —, nehmen Sie die asynchrone API: die Anfrage läuft in einem Arbeitsthread, und ihre Antwort kommt später als Ereignis zurück. Synchron und asynchron teilen sich dieselbe Sitzung: das Cookie einer synchronen Anmeldung dient den folgenden asynchronen Aufrufen und umgekehrt; ein synchroner Aufruf wartet nie hinter den asynchronen Anfragen desselben Objekts.
Einrichtung — nichts zu verdrahten: die Komponente liefert die Antwort selbst in ue_response. of_open / of_close öffnen und schließen den Client (optional: die erste Anfrage öffnet ihn), of_clear_cookies vergisst die zwischen Anfragen behaltenen Cookies. Intern ruft eine Pumpe der Komponente of_process_events auf, um die Antworten abzuholen — Sie rufen sie nie auf.
Senden — of_request_async(method, url, body) oder die Kurzformen of_get_async, of_post_async, of_put_async, of_patch_async, of_delete_async liefern sofort eine Anfrage-ID — oder -5 sofort, ohne nachfolgendes Ereignis, für eine ungültige URL oder einen ungültigen Header (is_last_error sagt warum, zum Beispiel „invalid URL: …“). Höchstens sechs Anfragen laufen gleichzeitig; die weiteren warten in einer Warteschlange. of_download_async(url, path) lädt in eine Datei herunter und of_upload(url, field, path) lädt eine Datei als multipart/form-data hoch — beide mit Fortschritt. of_cancel(id) stoppt eine Anfrage. Wiederholungen (il_max_retries, il_retry_backoff_ms) greifen bei 429/503/Netzausfall.
Empfangen — ue_response(al_id, al_status) (den Körper mit of_response_text(al_id) / of_status(al_id) IM Handler lesen), ue_failed(al_id, al_code, as_error), ue_progress(al_id, al_done, al_total). Eine ID gilt nur für das Objekt, das die Anfrage gesendet hat. Ein Laufzeitfehler in einem dieser Ereignisse wird nicht verschluckt: er erreicht das Ereignis SystemError der Anwendung wie jeder Skriptfehler, und die folgenden Antworten werden trotzdem geliefert.
| Methode | Rolle |
|---|---|
of_open ( ) → long | Öffnet den Client: seine Sitzung (Cookies, die synchrone und asynchrone Aufrufe teilen) und seinen nativen Ereigniskanal (kein WebView, kein CORS). Optional: die erste Anfrage öffnet ihn. Liefert die Client-ID (> 0) oder -2, wenn er nicht erzeugt werden konnte (is_last_error sagt, warum) |
of_close ( ) | Schließt den Client: seine Cookies (die Sitzung) gehen mit, und seine noch laufenden Anfragen werden ohne jedes Ereignis abgebrochen — kein ue_response, kein ue_failed. Die nächste Anfrage öffnet ihn wieder. Wird für Sie von of_reset und beim Zerstören erledigt. Die letzte synchrone Antwort des Objekts wird mit ihm vergessen |
of_process_events ( ) | Leert die asynchronen Antworten und löst ue_response / ue_failed / ue_progress aus. NUR öffentlich, weil der interne Pump der Komponente sie auf der PowerBuilder-Schleife aufruft, alle paar Millisekunden, solange eine Anfrage läuft — Sie rufen sie nie auf und verdrahten weder Empfänger noch Timer. Ein eigener Aufruf ist harmlos: sie leert nur, was bereits wartet |
of_clear_cookies ( ) | Vergisst die zwischen Anfragen behaltenen Cookies (eine Abmeldung). Ob danach Cookies behalten werden, bleibt Sache von ib_keep_cookies |
of_get_async (string as_url) → long | Asynchrones GET. Liefert sofort eine Anfrage-id; die Antwort kommt in ue_response(id, status). Liefert sofort -5 — und kein Ereignis folgt — für eine ungültige URL oder einen ungültigen Header (is_last_error sagt warum), -2, wenn sich der Client nicht öffnen lässt |
of_post_async (string as_url, string as_body) → long | Asynchrones POST mit Körper (standardmäßig JSON, mit n_pbt_json gebaut). Liefert sofort eine Anfrage-id; die Antwort kommt in ue_response. Liefert -5 / -2 wie of_get_async |
of_put_async (string as_url, string as_body) → long | Asynchrones PUT mit Körper. Liefert sofort eine Anfrage-id; die Antwort kommt in ue_response. Liefert -5 / -2 wie of_get_async |
of_patch_async (string as_url, string as_body) → long | Asynchrones PATCH mit Körper. Liefert sofort eine Anfrage-id; die Antwort kommt in ue_response. Liefert -5 / -2 wie of_get_async |
of_delete_async (string as_url) → long | Asynchrones DELETE. Liefert sofort eine Anfrage-id; die Antwort kommt in ue_response. Liefert -5 / -2 wie of_get_async |
of_request_async (string as_method, string as_url, string as_body) → long | Asynchrone Anfrage mit der HTTP-Methode Ihrer Wahl (of_get_async und seine Geschwister rufen sie auf). Liefert sofort eine Anfrage-id; die Antwort kommt in ue_response, ein Fehlschlag in ue_failed. Höchstens sechs Anfragen gleichzeitig, die weiteren warten. Liefert -2, wenn der Client sich nicht öffnen lässt, -4, wenn die Anfrage nicht eingereiht werden kann, sofort -5 — ohne Ereignis — für eine ungültige URL oder einen ungültigen Header |
of_download_async (string as_url, string as_path) → long | Asynchrones GET direkt in eine DATEI, mit ue_progress unterwegs. Liefert eine Anfrage-id, -5 bei leerem Pfad, -6 im Demomodus sofort abgelehnt, -2, wenn der Client sich nicht öffnen lässt. Ein relativer Pfad wird beim Aufruf aufgelöst, wie bei of_download |
of_upload (string as_url, string as_field, string as_path) → long | Lädt eine DATEI als multipart/form-data hoch (Formularfeld as_field), asynchron, mit ue_progress — immer ein POST mit genau diesem Feld. Liefert eine Anfrage-id, -5 bei leerem Pfad, -6 im Demomodus sofort abgelehnt, -2, wenn der Client sich nicht öffnen lässt. Eine relative Datei wird im aktuellen Ordner gesucht, dann im Ordner der Anwendung beim Laden der Bibliothek, dann neben der EXE. Der per of_set_header gesetzte Content-Type wird ignoriert: multipart/form-data setzt die Bibliothek |
of_cancel (long al_id) → long | Fordert eine Anfrage zum Anhalten auf; sie endet mit ue_failed(id, -4, "cancelled"), sofort, wenn sie noch auf ihren Platz wartete. Liefert 0, -5, wenn die ID unbekannt ist oder zu einem anderen Objekt gehört — nichts wird abgebrochen —, -4, wenn es zu spät ist: die Antwort ist da und kommt in ue_response |
of_status (long al_id) → long | Der HTTP-Status einer asynchronen Antwort, per Anfrage-ID — IM ue_response zu lesen. Liefert den Status (200, 404…); 0, solange die Anfrage läuft, für eine fehlgeschlagene Anfrage (in ue_failed), für eine unbekannte, bereits vergessene oder zu einem anderen Objekt gehörende ID |
of_response_text (long al_id) → string | Der Körper einer asynchronen Antwort, nach Anfrage-ID — IN ue_response zu lesen: die Anfrage wird vergessen, sobald das Ereignis zurückkehrt; leer, solange sie läuft; ebenfalls leer für die ID eines anderen Objekts |
of_response_headers (long al_id) → string | Alle Header einer asynchronen Antwort, einer pro Zeile |
of_response_header (long al_id, string as_name) → string | Ein Header einer asynchronen Antwort, nach Namen (Groß-/Kleinschreibung egal) |
of_json_value (long al_id, string as_path) → string | Ein Wert des JSON-Körpers einer asynchronen Antwort, nach Pfad — dieselbe Schreibweise wie of_json_value(as_path) |
| Ereignis | Rolle |
|---|---|
ue_response (long al_id, long al_status) | Eine asynchrone Anfrage ist beendet: al_id ist die beim Senden gelieferte id, al_status der HTTP-Status. Den Rumpf mit of_response_text(al_id) INNERHALB des Handlers lesen: die Anfrage ist nach dem Ereignis vergessen |
ue_failed (long al_id, long al_code, string as_error) | Eine asynchrone Anfrage ist fehlgeschlagen. al_code nennt die Art: -4 die Anfrage schlug fehl (kein Netz, Zeitüberschreitung, TLS, Körper zu groß, oder per of_cancel abgebrochen — as_error lautet dann cancelled), -5 ungültige Datei oder Client-Zertifikat nicht gefunden, -6 im Demomodus abgelehnt (eine Range-Anfrage); as_error sagt warum. of_status(al_id) liefert dort 0 |
ue_progress (long al_id, long al_done, long al_total) | Fortschritt eines asynchronen Downloads (of_download_async) oder Uploads (of_upload): al_done Bytes von al_total (0, wenn der Server die Größe nicht angekündigt hat). Über 2 GB passen die Byte-Zahlen nicht mehr in ein long |
// Async : the UI never freezes, and there is nothing to wire.
ll_id = uo_rest.of_get_async(/*url*/ "https://api.example.com/orders/4152")
// The answer arrives on its own in the ue_response event of uo_rest :
IF al_status >= 200 AND al_status < 300 THEN
ls_body = uo_rest.of_response_text(/*id*/ al_id)
END IF
Bewährte Praxis #
- Ein Client pro API, mit seinem
is_base_urlund seinen einmal gesetzten Headern: der Aufrufcode trägt nur noch Pfad und Körper. - Der Körper wird mit
n_pbt_jsongebaut, nie durch Verkettung: ein Anführungszeichen in einem Kundennamen zerstört nichts. - Prüfen Sie den Status, dann den negativen Code:
>= 200 und < 300ist gut,>= 400der Server hat abgelehnt,< 0die Anfrage ist nicht abgegangen —is_last_errorsagt warum. - Das Zeitlimit: standardmäßig 30 Sekunden; ein schwerer Bericht verdient mehr, eine Erreichbarkeitsprüfung weniger.
- Was dauern kann, läuft asynchron: ein synchroner Aufruf friert die Oberfläche bis zur Antwort ein.
- Eine Umleitung behält Ihre Anfrage: ein 301 oder 302 schreibt nur ein POST in ein GET um — ein PUT, PATCH oder DELETE wird unverändert erneut gesendet, Körper inklusive; ein 303 geht als GET ohne Körper weiter. Eine relative
Location(?page=2,../) wird aufgelöst, wie ein Browser es täte. - Eine Umleitung auf einen anderen Host nimmt nichts von Ihnen mit: keiner der per
of_set_headergesetzten Header (Token, API-Schlüssel) folgt ihr — nurContent-Typebleibt. Eine Umleitung HTTPS → HTTP wird abgelehnt. - Prüfen Sie die Rückgabe von
of_set_header,of_set_bearerundof_set_basic, wenn der Wert aus einer Eingabe oder einer Datei stammt: ein Zeilenumbruch wird dort abgelehnt (-5), und nichts wird gesetzt. Ein abgelehnter Header geht nie halb ab. - Windows-Anmeldedaten gehen nur ab, wenn Sie es verlangen:
ib_windows_auth = truefür eine Intranet-API mit Windows-Authentifizierung, nie bei einem Client, der mit dem Internet spricht. - Ein Textkörper ist auf 64 MB begrenzt, 16 MB in einer 32-Bit-Anwendung: ein großer Export wird mit
of_download/of_download_asyncgelesen, die ohne Grenze in eine Datei schreiben.