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 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 dem Kopf; 0 bei Transfer-Encoding: chunked — siehe Kasten
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 <token> hinzu; gibt neuen Header-String zurück
HTTPSetBasicAuth(hdrs: int64, user: int64, pass: int64): int64 pub Fügt Authorization: Basic <base64(user:pass)> 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


Weiterleitungen automatisch folgen

Signatur Beschreibung
HTTPGetWithRedirects(host: int64, path: int64): HTTPResponse GET, das Weiterleitungen selbständig verfolgt

Ein gewöhnliches HTTPGet liefert die Antwort so, wie sie kommt — bei 301 oder 302 also die Weiterleitung selbst, nicht das Ziel. Diese Fassung geht den Weg zu Ende.


Kopfzeilen lesen

Seit 1.0.20A liefert HTTPGetHeader nur noch den Wert der gesuchten Zeile (#1452). Vorher kam der Wert plus alle folgenden Kopfzeilen zurück, und gesucht wurde ohne Zeilenanker — ein Type traf damit auch mitten in einem fremden Wert. Ebenfalls neu: headerCount wird tatsächlich gesetzt (#1453); eine Schleife darüber lief bis dahin null Mal.

import std.net.http;

fn main(): int64 {
    var r: HTTPResponse := HTTPGet("example.com" as int64, "/" as int64);
    PrintLn("status        = ", IntToStr(r.statusCode));
    PrintLn("headerCount   = ", IntToStr(r.headerCount));
    PrintLn("contentLength = ", IntToStr(r.contentLength));
    PrintLn("bodySize      = ", IntToStr(r.bodySize));
    PrintLn("Content-Type  = '", HTTPGetHeader(r, "Content-Type" as int64) as pchar, "'");
    return 0;
}

status        = 200
headerCount   = 11
contentLength = 0
bodySize      = 571
Content-Type  = 'text/html'

<WRAP alert> contentLength und bodySize können auseinanderfallen. Im Lauf oben ist contentLength 0, obwohl 571 Byte ankamen — die Gegenstelle hat Transfer-Encoding: chunked benutzt und deshalb gar kein Content-Length geschickt.

Das ist sachlich richtig, am Feldnamen aber nicht zu erkennen. Für die tatsächliche Länge des Rumpfes ist bodySize zuständig, nicht contentLength. Wer über contentLength schleift, verarbeitet bei jeder chunked-Antwort null Bytes. </WRAP>