PBToolboxAI v3 ← Site

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 Objektn_pbt_restclient
WofürEine REST-API aus einer PowerBuilder-Anwendung aufrufen: lesen, anlegen, aktualisieren, herunterladen
PrinzipEine Anfrage ist ein Aufruf, der den HTTP-Status liefert; die Antwort wartet im Objekt, gelesen per of_response_text oder of_json_value
AbhängigkeitWinHTTP in der DLL der Bibliothek — keine Seite, keine zusätzliche Runtime

Schnellstart #

n_pbt_restclient lnv_rest
n_pbt_json lnv_j
long ll_status

lnv_rest = create n_pbt_restclient
lnv_rest.is_base_url = "https://api.example.com"
lnv_rest.of_set_bearer(ls_token)

// Read : the status comes back, the body waits in the object
ll_status = lnv_rest.of_get("/orders/4152")
if ll_status = 200 then ls_customer = lnv_rest.of_json_value("customer")

// Create : the body is built with n_pbt_json, never by hand
lnv_j.of_set_number("order", 4152)
lnv_j.of_set_string("status", "shipped")
ll_status = lnv_rest.of_post("/shipments", lnv_j.of_text())
if ll_status < 0 then MessageBox("API", lnv_rest.is_last_error)

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 durchkam: -5 ungültige URL, -4 Fehlschlag (kein Netz, unbekannter Name, Zeitüberschreitung, TLS; is_last_error sagt welcher), -6 im Demomodus verweigert.


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 #

EigenschaftTypStandardRolle
is_base_urlstring""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_mslong30000Maximale Dauer einer Anfrage, Verbindung und Antwort eingeschlossen. Danach: -4 und „timed out“
is_last_errorstring""Warum die letzte Anfrage einen negativen Code lieferte. Leer nach einer Anfrage, die den Server erreicht hat — ein 404 ist kein Fehler
il_statuslong0Der HTTP-Status der letzten Anfrage oder ihr negativer Code; der Wert, den die Anfrage lieferte

Konstanten: METHOD_GET, METHOD_POST, METHOD_PUT, METHOD_PATCH, METHOD_DELETE für of_request.


Methoden #

MethodeRolle
of_set_header (string as_name, string as_value)Ein Header, der ab jetzt mit jeder Anfrage gesendet wird; ein bereits gesetzter Name wird ersetzt. Content-Type wird automatisch ergänzt, wenn ein Körper ohne ihn gesendet wird (JSON, UTF-8)
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)Authorization: Bearer bei jeder Anfrage; ein leeres Token entfernt ihn
of_set_basic (string as_user, string as_password)Basic-Authentifizierung; die DLL kodiert Base64 selbst — PowerBuilder 10 hat keines
of_get (string as_url) → longGET. Liefert den HTTP-Status oder -5 ungültige URL, -4 Fehlschlag, -6 in der Demo verweigert
of_post (string as_url, string as_body) → longPOST 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) → longPUT mit einem Körper. Liefert den HTTP-Status oder -5 / -4 / -6
of_patch (string as_url, string as_body) → longPATCH mit einem Körper. Liefert den HTTP-Status oder -5 / -4 / -6
of_delete (string as_url) → longDELETE. Liefert den HTTP-Status oder -5 / -4 / -6
of_request (string as_method, string as_url, string as_body) → longJede 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) → longGET 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
of_response_text ( ) → stringDer Körper der letzten Antwort als Text (UTF-8 dekodiert)
of_response_headers ( ) → stringAlle Header der letzten Antwort, einer pro Zeile
of_response_header (string as_name) → stringEin Header der letzten Antwort, nach Name; leer, wenn er nicht gesendet wurde
of_json_value (string as_key) → stringEin Wert des JSON-Körpers nach seinem Schlüssel, das erste Vorkommen in beliebiger Tiefe. Für mehr als einen Wert of_response_text und n_pbt_utils.of_json_get_* lesen
of_reset ( )Zurück zu den Standardwerten: keine Header, keine Basis-URL, Standard-Timeout, letzte Antwort vergessen

Beispiele #

Eine Liste lesen und durchgehen #

string ls_body
if lnv_rest.of_get("/orders?status=open") = 200 then
	ls_body = lnv_rest.of_response_text()
	// One value : of_json_value. The whole list : n_pbt_utils.of_json_get_payload and
	// of_json_get_str on each object, or your own parser on ls_body.
end if

Ein Dokument herunterladen #

long ll_status
ll_status = lnv_rest.of_download("/orders/4152/invoice.pdf", "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 #

choose case lnv_rest.of_post("/shipments", ls_body)
	case 200, 201
		// created
	case 401
		MessageBox("API", "Token expired : " + lnv_rest.of_json_value("message"))
	case is < 0
		MessageBox("Network", lnv_rest.is_last_error)
end choose

Asynchron (kein UI-Einfrieren) #

Die synchronen Aufrufe oben blockieren das Skript (die UI bleibt lebendig, aber die Zeile wartet). Die asynchrone API blockiert nicht einmal das Skript: die Anfrage läuft auf einem Arbeitsthread und ihre Antwort kommt später als Ereignis.

Einrichtung — nichts zu verdrahten: die Komponente liefert die Antwort selbst in ue_response. of_open / of_close öffnen und schließen den Client (optional: der erste async-Aufruf öffnet ihn), of_clear_cookies vergisst die zwischen Anfragen gehaltenen Cookies. Intern ruft der Pump der Komponente of_process_events auf, um die Antworten zu leeren — Sie rufen es 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. of_download_async(url, path) lädt in eine Datei, of_upload(url, field, path) lädt eine Datei als multipart/form-data hoch — beide mit Fortschritt. of_cancel(id) stoppt eine laufende Anfrage. Wiederholungen (il_max_retries, il_retry_backoff_ms) bei 429/503/Netzfehler.

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, as_error), ue_progress(al_id, al_done, al_total).

MethodeRolle
of_open ( ) → longÖffnet den asynchronen Client, einen nativen Ereigniskanal (kein WebView, kein CORS). Optional: der erste async-Aufruf öffnet ihn. Liefert die Client-Id (> 0) oder einen negativen Code
of_close ( )Schließt den asynchronen Client: seine Cookies (die Sitzung) gehen mit ihm. Der nächste async-Aufruf öffnet ihn wieder. Von of_reset und bei der Zerstörung für Sie erledigt
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 gehaltenen Cookies (ein Logout). Die Einstellung ib_keep_cookies bleibt unverändert
of_get_async (string as_url) → longAsynchrones GET. Liefert sofort eine Anfrage-id; die Antwort kommt in ue_response(id, status). Liefert -5 bei ungültiger URL, -2 wenn der Client nicht öffnen kann
of_post_async (string as_url, string as_body) → longAsynchrones 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) → longAsynchrones 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) → longAsynchrones 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) → longAsynchrones 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) → longAsynchrone 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. Liefert -2, wenn der Client nicht geöffnet werden kann
of_download_async (string as_url, string as_path) → longAsynchrones GET direkt in eine DATEI, mit ue_progress unterwegs. Liefert eine Anfrage-id, -5 bei leerem Pfad, -2, wenn der Client nicht geöffnet werden kann
of_upload (string as_url, string as_field, string as_path) → longLädt eine DATEI als multipart/form-data hoch (Formularfeld as_field), asynchron, mit ue_progress. Liefert eine Anfrage-id, -5 bei leerem Pfad, -2, wenn der Client nicht geöffnet werden kann, -6 im Demomodus
of_cancel (long al_id) → longBittet eine laufende Anfrage anzuhalten; sie endet mit ue_failed(id, "cancelled"). Liefert 0, oder -1, wenn die id unbekannt ist
of_status (long al_id) → longDer HTTP-Status einer asynchronen Antwort, nach Anfrage-id - INNERHALB von ue_response lesen. Liefert den Status (200, 404...), 0, wenn die Anfrage unbekannt oder schon vergessen ist
EreignisRolle
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, string as_error)Eine asynchrone Anfrage ist fehlgeschlagen: kein Netz, Zeitüberschreitung, TLS, oder durch of_cancel abgebrochen (as_error ist dann cancelled)
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
// Async : the UI never freezes, and there is nothing to wire.
ll_id = uo_rest.of_get_async("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(al_id)
END IF

Bewährte Praxis #

← Komponentenreferenz · Inhalt des Handbuchs