PBToolboxAI v3 ← Site

restclient — n_pbt_restclient #

← Riferimento dei componenti · Sommario della guida

Un client HTTPS per PowerBuilder, versione 10 compresa: GET, POST, PUT, PATCH, DELETE, intestazioni, un corpo JSON, il download di un file. Nativo — TLS, proxy e decompressione del sistema, e nessun muro CORS, perché la richiesta non parte da una pagina.

▶ Vederlo dal vivo — Applicazione dimostrativa, riquadro REST client: le risposte, il codice che le ottiene e questa pagina, fianco a fianco (connessione Internet richiesta).


In breve #

Oggetto non visualen_pbt_restclient
Serve aChiamare un'API REST da un'applicazione PowerBuilder: leggere, creare, aggiornare, scaricare
PrincipioUna richiesta è una chiamata che restituisce lo stato HTTP; la risposta attende nell'oggetto, letta con of_response_text o of_json_value
DipendenzaWinHTTP, nella DLL della libreria — nessuna pagina, nessun runtime aggiuntivo

Avvio rapido #

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

Ogni metodo HTTP restituisce lo stato scelto dal server — un 404 è una risposta, non un errore — o un codice negativo quando la richiesta non è andata a buon fine: -5 URL non valido, -4 fallimento (niente rete, nome sconosciuto, timeout, TLS; is_last_error dice quale), -6 rifiutato in modalità demo.


Perché nativo, e non la pagina #

Un fetch() lanciato da una pagina della libreria è soggetto a CORS: ogni API che non invia Access-Control-Allow-Origin gli è chiusa, e le API aziendali non lo inviano. La richiesta parte quindi dalla DLL, tramite WinHTTP: il TLS del sistema con i suoi certificati, il proxy configurato, gzip. Ciò che perdi: nulla; ciò che guadagni: tutte le API.


Proprietà #

ProprietàTipoPredefinitoRuolo
is_base_urlstring""Messo davanti a un URL relativo: is_base_url = "https://api.example.com" poi of_get("/orders/4152"). Un URL assoluto è usato così com'è
il_timeout_mslong30000Durata massima di una richiesta, connessione e risposta comprese. Oltre: -4 e «timed out»
is_last_errorstring""Perché l'ultima richiesta ha restituito un codice negativo. Vuoto dopo una richiesta arrivata al server — un 404 non è un errore
il_statuslong0Lo stato HTTP dell'ultima richiesta, o il suo codice negativo; il valore restituito dalla richiesta

Costanti: METHOD_GET, METHOD_POST, METHOD_PUT, METHOD_PATCH, METHOD_DELETE per of_request.


Metodi #

MetodoRuolo
of_set_header (string as_name, string as_value)Un'intestazione inviata con ogni richiesta d'ora in poi; un nome già impostato è sostituito. Content-Type è aggiunto da solo quando un corpo parte senza (JSON, UTF-8)
of_remove_header (string as_name)Dimentica un'intestazione, per nome (maiuscole indifferenti)
of_clear_headers ( )Dimentica tutte le intestazioni, autenticazione compresa
of_set_bearer (string as_token)Authorization: Bearer su ogni richiesta; un token vuoto lo rimuove
of_set_basic (string as_user, string as_password)Autenticazione Basic; la DLL codifica da sola il base64 — PowerBuilder 10 non ce l'ha
of_get (string as_url) → longGET. Restituisce lo stato HTTP, o -5 URL non valido, -4 fallimento, -6 rifiutato in demo
of_post (string as_url, string as_body) → longPOST con un corpo (JSON per impostazione predefinita, costruito con n_pbt_json). Restituisce lo stato HTTP, o -5 / -4 / -6
of_put (string as_url, string as_body) → longPUT con un corpo. Restituisce lo stato HTTP, o -5 / -4 / -6
of_patch (string as_url, string as_body) → longPATCH con un corpo. Restituisce lo stato HTTP, o -5 / -4 / -6
of_delete (string as_url) → longDELETE. Restituisce lo stato HTTP, o -5 / -4 / -6
of_request (string as_method, string as_url, string as_body) → longQualsiasi metodo (METHOD_*, o il tuo), qualsiasi corpo inviato in UTF-8: ciò che le cinque scorciatoie chiamano. Restituisce lo stato HTTP, o -5 / -4 / -6
of_download (string as_url, string as_path) → longGET direttamente in un file, byte intatti, di qualsiasi dimensione. Restituisce lo stato HTTP, o -5 URL o percorso vuoto, -4 fallimento, -6 rifiutato in demo
of_response_text ( ) → stringIl corpo dell'ultima risposta, come testo (UTF-8 decodificato)
of_response_headers ( ) → stringTutte le intestazioni dell'ultima risposta, una per riga
of_response_header (string as_name) → stringUn'intestazione dell'ultima risposta, per nome; vuota se non è stata inviata
of_json_value (string as_key) → stringUn valore del corpo JSON per la sua chiave, la prima occorrenza a qualsiasi profondità. Per più valori, leggi of_response_text e n_pbt_utils.of_json_get_*
of_reset ( )Ritorno ai valori predefiniti: nessuna intestazione, nessun URL di base, il timeout predefinito, l'ultima risposta dimenticata

Esempi #

Leggere un elenco e scorrerlo #

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

Scaricare un documento #

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

Un'API che risponde con un errore #

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

Asincrono (nessun blocco dell'interfaccia) #

Le chiamate sincrone qui sopra bloccano lo script (l'interfaccia resta viva ma la riga attende). L'API asincrona non blocca nemmeno lo script: la richiesta parte su un thread di lavoro e la risposta torna più tardi come evento.

Impostazione — niente da collegare: il componente consegna la risposta da solo in ue_response. of_open / of_close aprono e chiudono il client (facoltativo: la prima chiamata async lo apre), of_clear_cookies dimentica i cookie tenuti tra le richieste. Internamente il pump del componente chiama of_process_events per distribuire le risposte — non lo chiami mai.

Inviare — of_request_async(method, url, body), o le scorciatoie of_get_async, of_post_async, of_put_async, of_patch_async, of_delete_async, restituiscono subito un id di richiesta. of_download_async(url, path) scarica in un file e of_upload(url, field, path) carica un file come multipart/form-data — entrambi con progresso. of_cancel(id) ferma una richiesta in volo. I tentativi (il_max_retries, il_retry_backoff_ms) rigiocano su 429/503/errore di rete.

Ricevere — ue_response(al_id, al_status) (leggere il corpo con of_response_text(al_id) / of_status(al_id) DENTRO il gestore), ue_failed(al_id, as_error), ue_progress(al_id, al_done, al_total).

MetodoRuolo
of_open ( ) → longApre il client asincrono, un canale di eventi nativo (niente WebView, niente CORS). Facoltativo: la prima chiamata async lo apre. Restituisce l'id del client (> 0), o un codice negativo
of_close ( )Chiude il client asincrono: i suoi cookie (la sessione) se ne vanno con lui. La prossima chiamata async lo riapre. Fatto per te da of_reset e alla distruzione
of_process_events ( )Distribuisce le risposte asincrone e solleva ue_response / ue_failed / ue_progress. Pubblica SOLO perché il pump interno del componente la chiama sul ciclo PowerBuilder, ogni pochi millisecondi finché una richiesta è in volo — non la chiami mai, e non colleghi né ricevitore né timer. Chiamarla tu stesso è innocuo: svuota solo ciò che già attende
of_clear_cookies ( )Dimentica i cookie tenuti tra le richieste (un logout). L'impostazione ib_keep_cookies non cambia
of_get_async (string as_url) → longGET asincrono. Restituisce subito un id di richiesta; la risposta arriva in ue_response(id, status). Restituisce -5 su URL non valido, -2 se il client non può aprirsi
of_post_async (string as_url, string as_body) → longPOST asincrono con un corpo (JSON per impostazione predefinita, costruito con n_pbt_json). Restituisce subito un id di richiesta; la risposta arriva in ue_response. Restituisce -5 / -2 come of_get_async
of_put_async (string as_url, string as_body) → longPUT asincrono con un corpo. Restituisce subito un id di richiesta; la risposta arriva in ue_response. Restituisce -5 / -2 come of_get_async
of_patch_async (string as_url, string as_body) → longPATCH asincrono con un corpo. Restituisce subito un id di richiesta; la risposta arriva in ue_response. Restituisce -5 / -2 come of_get_async
of_delete_async (string as_url) → longDELETE asincrono. Restituisce subito un id di richiesta; la risposta arriva in ue_response. Restituisce -5 / -2 come of_get_async
of_request_async (string as_method, string as_url, string as_body) → longRichiesta asincrona con il metodo HTTP di vostra scelta (of_get_async e i suoi fratelli la chiamano). Restituisce subito un id di richiesta; la risposta arriva in ue_response, un errore in ue_failed. Restituisce -2 se il client non si apre
of_download_async (string as_url, string as_path) → longGET asincrono direttamente in un FILE, con ue_progress lungo il percorso. Restituisce un id di richiesta, -5 su un percorso vuoto, -2 se il client non si apre
of_upload (string as_url, string as_field, string as_path) → longInvia un FILE come multipart/form-data (campo del modulo as_field), in modo asincrono, con ue_progress. Restituisce un id di richiesta, -5 su un percorso vuoto, -2 se il client non si apre, -6 in modalità demo
of_cancel (long al_id) → longChiede a una richiesta in corso di fermarsi; termina con ue_failed(id, "cancelled"). Restituisce 0, oppure -1 se l'id è sconosciuto
of_status (long al_id) → longLo stato HTTP di una risposta asincrona, per id di richiesta - da leggere DENTRO ue_response. Restituisce lo stato (200, 404...), 0 se la richiesta è sconosciuta o già dimenticata
EventoRuolo
ue_response (long al_id, long al_status)Una richiesta asincrona è terminata: al_id è l'id restituito all'invio, al_status lo stato HTTP. Leggere il corpo con of_response_text(al_id) DENTRO il gestore: la richiesta è dimenticata all'uscita dell'evento
ue_failed (long al_id, string as_error)Una richiesta asincrona è fallita: nessuna rete, timeout, TLS, o annullata da of_cancel (as_error vale allora cancelled)
ue_progress (long al_id, long al_done, long al_total)Avanzamento di un download (of_download_async) o di un upload (of_upload) asincrono: al_done byte su 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

Buone pratiche #

← Riferimento dei componenti · Sommario della guida