====== std.net.http ====== HTTP/1.1-Client für GET, POST, PUT, DELETE, PATCH und HEAD ohne TLS. Baut auf ''std.net.socket'' und ''std.net.dns'' auf. Unterstützt Header-Builder (''HTTPSetHeader''), Bearer- und Basic-Auth (RFC 7617), automatisches Chunked-Transfer-Decoding, 3×x-Redirects (HTTP→HTTP und HTTP→HTTPS, bis 10 Hops) sowie case-insensitives Header-Lesen. Für HTTPS-Verbindungen ''[[lyx_-_programmiersprache:units:net:https|std.net.https]]'' verwenden. import std.net.http; var hdrs: int64 := HTTPSetBearerToken(0, "my-token"); var req: HTTPRequest; req.method := HTTP_GET; req.host := "api.example.com" as int64; req.path := "/v1/items" as int64; req.port := HTTP_PORT; req.headers := hdrs; var resp: HTTPResponse := HTTPSendWithRedirects(req); if (resp.statusCode = HTTP_OK) { PrintLn("OK"); } HTTPResponseFree(resp); HTTPHeadersFree(hdrs); ---- ===== Imports ===== * ''std.net.socket'' * ''std.net.dns'' * ''std.net.types'' * ''std.string'' * ''std.base64'' ---- ===== Konstanten ===== ^ Name ^ Typ ^ Wert ^ Sichtbarkeit ^ | ''HTTP_PORT'' | ''int64'' | ''80'' | pub | | ''HTTPS_PORT'' | ''int64'' | ''443'' | pub | | ''HTTP_RECV_TIMEOUT_MS'' | ''int64'' | ''30000'' | pub | | ''HTTP_MAX_REDIRECTS'' | ''int64'' | ''10'' | pub | | ''HTTP_GET'' | ''int64'' | ''1'' | pub | | ''HTTP_POST'' | ''int64'' | ''2'' | pub | | ''HTTP_PUT'' | ''int64'' | ''3'' | pub | | ''HTTP_DELETE'' | ''int64'' | ''4'' | pub | | ''HTTP_PATCH'' | ''int64'' | ''5'' | pub | | ''HTTP_HEAD'' | ''int64'' | ''6'' | pub | | ''HTTP_OK'' | ''int64'' | ''200'' | pub | | ''HTTP_CREATED'' | ''int64'' | ''201'' | pub | | ''HTTP_NO_CONTENT'' | ''int64'' | ''204'' | pub | | ''HTTP_BAD_REQUEST'' | ''int64'' | ''400'' | pub | | ''HTTP_UNAUTHORIZED'' | ''int64'' | ''401'' | pub | | ''HTTP_FORBIDDEN'' | ''int64'' | ''403'' | pub | | ''HTTP_NOT_FOUND'' | ''int64'' | ''404'' | pub | | ''HTTP_SERVER_ERROR'' | ''int64'' | ''500'' | pub | ---- ===== Typen ===== ==== HTTPResponse (struct) ==== ^ Feld ^ Typ ^ Beschreibung ^ | ''statusCode'' | ''int64'' | HTTP-Statuscode (z. B. 200, 404) | | ''statusText'' | ''int64'' | Zeiger auf Statustext-String (z. B. "OK") | | ''headerCount'' | ''int64'' | Anzahl der geparsten Response-Header | | ''contentLength'' | ''int64'' | Content-Length aus Header (−1 wenn nicht vorhanden) | | ''bodyPtr'' | ''int64'' | Zeiger auf Response-Body (heap-alloc'd) | | ''bodySize'' | ''int64'' | Tatsächliche Größe des Body in Bytes | | ''headersRaw'' | ''int64'' | Zeiger auf rohe Response-Header (null-terminiert, heap-alloc'd) | | ''headersSize'' | ''int64'' | Byte-Anzahl der rohen Header | ==== HTTPRequest (struct) ==== ^ Feld ^ Typ ^ Beschreibung ^ | ''method'' | ''int64'' | HTTP-Methode (''HTTP_GET'', ''HTTP_POST'' …) | | ''host'' | ''int64'' | Zeiger auf Hostname-String | | ''path'' | ''int64'' | Zeiger auf Pfad-String (inkl. führendem ''/'' und Query) | | ''port'' | ''int64'' | TCP-Port (''HTTP_PORT'' = 80) | | ''headers'' | ''int64'' | Zeiger auf Header-String (aus ''HTTPSetHeader'') oder ''0'' | | ''body'' | ''int64'' | Zeiger auf Request-Body oder ''0'' | | ''bodySize'' | ''int64'' | Länge des Request-Body in Bytes | ---- ===== Funktionen ===== ==== Einfache Convenience-Funktionen ==== ^ Signatur ^ Sichtbarkeit ^ Beschreibung ^ | ''HTTPGet(host: int64, path: int64): HTTPResponse'' | pub | HTTP-GET an Host senden | | ''HTTPPost(host: int64, path: int64, body: int64, bodySize: int64): HTTPResponse'' | pub | HTTP-POST mit Body senden | | ''HTTPPut(host: int64, path: int64, body: int64, bodySize: int64): HTTPResponse'' | pub | HTTP-PUT mit Body senden | | ''HTTPDelete(host: int64, path: int64): HTTPResponse'' | pub | HTTP-DELETE senden | | ''HTTPPatch(host: int64, path: int64, body: int64, bodySize: int64): HTTPResponse'' | pub | HTTP-PATCH mit Body senden | | ''HTTPHead(host: int64, path: int64): HTTPResponse'' | pub | HTTP-HEAD senden (kein Body in Antwort) | ==== Header-Varianten (mit vorgebautem Header-String) ==== ^ Signatur ^ Sichtbarkeit ^ Beschreibung ^ | ''HTTPGetH(host: int64, path: int64, headers: int64): HTTPResponse'' | pub | HTTP-GET mit zusätzlichen Headern | | ''HTTPPostH(host: int64, path: int64, body: int64, bodySize: int64, headers: int64): HTTPResponse'' | pub | HTTP-POST mit Body und Headern | | ''HTTPDeleteH(host: int64, path: int64, headers: int64): HTTPResponse'' | pub | HTTP-DELETE mit Headern | ==== Request-Builder und Low-Level-API ==== ^ Signatur ^ Sichtbarkeit ^ Beschreibung ^ | ''HTTPRequestBuild(req: HTTPRequest): int64'' | pub | HTTP-Anfrage-Puffer aus Struct aufbauen; gibt Zeiger auf Puffer zurück | | ''HTTPSend(request: HTTPRequest): HTTPResponse'' | pub | HTTP-Anfrage senden; dekodiert automatisch Chunked Transfer-Encoding | | ''HTTPSendWithRedirects(request: HTTPRequest): HTTPResponse'' | pub | Wie ''HTTPSend'', folgt aber automatisch 3×x-Redirects (bis ''HTTP_MAX_REDIRECTS'' = 10); HTTP→HTTPS via TLS | ==== Header-Builder ==== ^ Signatur ^ Sichtbarkeit ^ Beschreibung ^ | ''HTTPSetHeader(hdrs: int64, name: int64, value: int64): int64'' | pub | Fügt Header-Zeile zu vorhandenem Header-String hinzu (oder legt neuen an wenn ''hdrs=0''); gibt neuen heap-alloc'd String zurück | | ''HTTPHeadersFree(hdrs: int64)'' | pub | Gibt einen per ''HTTPSetHeader'' aufgebauten Header-String frei | | ''HTTPSetBearerToken(hdrs: int64, token: int64): int64'' | pub | Fügt ''Authorization: Bearer '' hinzu; gibt neuen Header-String zurück | | ''HTTPSetBasicAuth(hdrs: int64, user: int64, pass: int64): int64'' | pub | Fügt ''Authorization: Basic '' hinzu (RFC 7617); gibt neuen Header-String zurück | ==== Response-Zugriff ==== ^ Signatur ^ Sichtbarkeit ^ Beschreibung ^ | ''HTTPGetHeader(resp: HTTPResponse, name: int64): int64'' | pub | Sucht Header ''name'' im ''headersRaw''-Puffer; **case-insensitiv**; gibt Zeiger auf Header-Wert zurück oder ''0'' wenn nicht gefunden | | ''HTTPResponseFree(response: HTTPResponse)'' | pub | Gibt Body-Puffer **und** ''headersRaw'' frei | ---- ===== Codebeispiele ===== ==== PUT mit Bearer-Token ==== var hdrs: int64 := HTTPSetBearerToken(0, "eyJhbGci..."); var body: pchar := "{\"status\":\"active\"}"; var resp: HTTPResponse := HTTPPostH( "api.example.com" as int64, "/v1/item/42" as int64, body as int64, StrLen(body), hdrs); if (resp.statusCode = HTTP_OK) { PrintLn("Aktualisiert"); } HTTPResponseFree(resp); HTTPHeadersFree(hdrs); ==== Response-Header lesen ==== var resp: HTTPResponse := HTTPGet("api.example.com" as int64, "/" as int64); var ct: int64 := HTTPGetHeader(resp, "Content-Type" as int64); if (ct != 0) { PrintLn(ct as pchar); } HTTPResponseFree(resp); ==== Redirect-Folgen (HTTP → HTTPS) ==== var req: HTTPRequest; req.method := HTTP_GET; req.host := "example.com" as int64; req.path := "/" as int64; req.port := HTTP_PORT; req.headers := 0; req.body := 0; req.bodySize := 0; // Folgt automatisch: HTTP 301 → https://example.com/ var resp: HTTPResponse := HTTPSendWithRedirects(req); HTTPResponseFree(resp); ---- ===== Hinweise ===== * **Chunked Transfer-Encoding**: ''HTTPSend'' und alle darauf aufbauenden Funktionen dekodieren ''Transfer-Encoding: chunked'' automatisch — kein manuelles Chunk-Parsing nötig. * **Redirects**: ''HTTPSendWithRedirects'' folgt 3×x-Antworten bis zu ''HTTP_MAX_REDIRECTS'' (10) Hops. Ein Wechsel von HTTP auf HTTPS (''Location: https://...'') wird transparent über TLS abgewickelt. * **''HTTPSetHeader'' ist funktional**: Jeder Aufruf gibt einen **neuen** heap-alloc'd String zurück. Der alte Wert (Eingabe ''hdrs'') wird intern freigegeben — den Rückgabewert immer verwenden, nicht den alten ''hdrs''-Wert weiterverwenden. * **''HTTPGetHeader'' ist case-insensitiv**: ''Content-Type'', ''content-type'' und ''CONTENT-TYPE'' liefern denselben Treffer. * **''HTTPResponseFree'' gibt ''headersRaw'' frei**: Kein separates Freigeben nötig — ein Aufruf reicht für alle alloc'd Felder der Response. * **Basic Auth (RFC 7617)**: ''HTTPSetBasicAuth'' berechnet ''base64(user:pass)'' intern — keine externe Base64-Funktion nötig. * **TLS-Redirects**: Für den HTTPS-Hop im Redirect-Pfad muss ''std.net.tls'' verfügbar sein. Letzte Aktualisierung: 2026-06-06