HTTP-Client

Führen Sie HTTP-Anfragen an externe Services durch. Unterstützt alle HTTP-Methoden, Header, Query-Parameter, Formulardaten, Datei-Uploads, Streaming-Responses und gleichzeitige Batch-Anfragen.

Laden

local http_client = require("http_client")

HTTP-Methoden

Alle Methoden teilen dieselbe Signatur: method(url, options?) gibt Response, error zurück.

GET-Anfrage

local resp, err = http_client.get("https://api.example.com/users")
if err then
    return nil, err
end

print(resp.status_code)  -- 200
print(resp.body)         -- Response-Body

POST-Anfrage

local resp, err = http_client.post("https://api.example.com/users", {
    headers = {["Content-Type"] = "application/json"},
    body = json.encode({name = "Alice", email = "alice@example.com"})
})

PUT-Anfrage

local resp, err = http_client.put("https://api.example.com/users/123", {
    headers = {["Content-Type"] = "application/json"},
    body = json.encode({name = "Alice Smith"})
})

PATCH-Anfrage

local resp, err = http_client.patch("https://api.example.com/users/123", {
    body = json.encode({status = "active"})
})

DELETE-Anfrage

local resp, err = http_client.delete("https://api.example.com/users/123", {
    headers = {["Authorization"] = "Bearer " .. token}
})

HEAD-Anfrage

Gibt nur Header zurück, keinen Body.

local resp, err = http_client.head("https://cdn.example.com/file.zip")
local size = resp.headers["Content-Length"]

Benutzerdefinierte Methode

local resp, err = http_client.request("PROPFIND", "https://dav.example.com/folder", {
    headers = {["Depth"] = "1"}
})
Parameter Typ Beschreibung
method string HTTP-Methode
url string Anfrage-URL
options table Anfrageoptionen (optional)

Anfrageoptionen

Feld Typ Beschreibung
headers table Anfrage-Header {["Name"] = "value"}
body string Anfrage-Body
query table Query-Parameter {key = "value"}
form table Formulardaten (setzt Content-Type automatisch)
files table Datei-Uploads (Array von Dateidefinitionen)
cookies table Anfrage-Cookies {name = "value"}
auth table Basic Auth {user = "name", pass = "secret"}
timeout number/string Timeout: Zahl in Sekunden oder String wie "30s", "1m"
stream boolean Response-Body streamen statt puffern
max_response_body number Max. Response-Größe in Bytes (0 = Standard)
unix_socket string Über Unix-Socket-Pfad verbinden
tls table TLS-Konfiguration pro Anfrage (siehe TLS-Optionen)

Query-Parameter

local resp, err = http_client.get("https://api.example.com/search", {
    query = {
        q = "lua programming",
        page = "1",
        limit = "20"
    }
})

Header und Authentifizierung

local resp, err = http_client.get("https://api.example.com/data", {
    headers = {
        ["Authorization"] = "Bearer " .. token,
        ["Accept"] = "application/json"
    }
})

-- Oder Basic Auth verwenden
local resp, err = http_client.get("https://api.example.com/data", {
    auth = {user = "admin", pass = "secret"}
})

Formulardaten

local resp, err = http_client.post("https://api.example.com/login", {
    form = {
        username = "alice",
        password = "secret123"
    }
})

Datei-Upload

local resp, err = http_client.post("https://api.example.com/upload", {
    form = {title = "My Document"},
    files = {
        {
            name = "attachment",      -- Formularfeldname
            filename = "report.pdf",  -- Originaler Dateiname
            content = pdf_data,       -- Dateiinhalt
            content_type = "application/pdf"
        }
    }
})
Dateifeld Typ Erforderlich Beschreibung
name string ja Formularfeldname
filename string nein Originaler Dateiname
content string ja* Dateiinhalt
reader userdata ja* Alternative: io.Reader für Inhalt
content_type string nein MIME-Typ (Standard: application/octet-stream)

*Entweder content oder reader ist erforderlich.

Timeout

-- Zahl: Sekunden
local resp, err = http_client.get(url, {timeout = 30})

-- String: Go-Dauerformat
local resp, err = http_client.get(url, {timeout = "30s"})
local resp, err = http_client.get(url, {timeout = "1m30s"})
local resp, err = http_client.get(url, {timeout = "1h"})

TLS-Optionen

Konfigurieren Sie TLS-Einstellungen pro Anfrage für mTLS (Mutual TLS) und benutzerdefinierte CA-Zertifikate.

Feld Typ Beschreibung
cert string Client-Zertifikat im PEM-Format
key string Privater Schlüssel des Clients im PEM-Format
ca string Benutzerdefiniertes CA-Zertifikat im PEM-Format
server_name string Servername für SNI-Verifizierung
insecure_skip_verify boolean TLS-Zertifikatsverifizierung überspringen

cert und key müssen für mTLS zusammen angegeben werden. Das Feld ca ersetzt den System-Zertifikatspool durch eine benutzerdefinierte CA.

mTLS-Authentifizierung

local cert_pem = fs.read("/certs/client.crt")
local key_pem = fs.read("/certs/client.key")

local resp, err = http_client.get("https://secure.example.com/api", {
    tls = {
        cert = cert_pem,
        key = key_pem,
    }
})

Benutzerdefinierte CA

local ca_pem = fs.read("/certs/internal-ca.crt")

local resp, err = http_client.get("https://internal.example.com/api", {
    tls = {
        ca = ca_pem,
        server_name = "internal.example.com",
    }
})

Unsichere Verifizierung überspringen

TLS-Verifizierung für Entwicklungsumgebungen überspringen. Erfordert die Sicherheitsberechtigung http_client.insecure_tls.

local resp, err = http_client.get("https://localhost:8443/api", {
    tls = {
        insecure_skip_verify = true,
    }
})

Response-Objekt

Feld Typ Beschreibung
status_code number HTTP-Statuscode
body string Response-Body (wenn nicht streaming)
body_size number Body-Größe in Bytes (-1 wenn streaming)
headers table Response-Header
cookies table Response-Cookies
url string Finale URL (nach Weiterleitungen)
stream Stream Stream-Objekt (wenn stream = true)
local resp, err = http_client.get("https://api.example.com/data")
if err then
    return nil, err
end

if resp.status_code == 200 then
    local data = json.decode(resp.body)
    print("Content-Type:", resp.headers["Content-Type"])
end

Streaming-Responses

Für große Responses verwenden Sie Streaming, um zu vermeiden, dass der gesamte Body in den Speicher geladen wird.

local resp, err = http_client.get("https://cdn.example.com/large-file.zip", {
    stream = true
})
if err then
    return nil, err
end

-- In Chunks verarbeiten
while true do
    local chunk, err = resp.stream:read(65536)
    if err or not chunk then break end
    -- chunk verarbeiten
end
resp.stream:close()
Stream-Methode Gibt zurück Beschreibung
read(size) string, error Bis zu size Bytes lesen
close() - Stream schließen

Batch-Anfragen

Führen Sie mehrere Anfragen gleichzeitig aus.

local responses, errors = http_client.request_batch({
    {"GET", "https://api.example.com/users"},
    {"GET", "https://api.example.com/products"},
    {"POST", "https://api.example.com/log", {body = "event"}}
})

if errors then
    for i, err in ipairs(errors) do
        if err then
            print("Request " .. i .. " failed:", err)
        end
    end
else
    -- Alle erfolgreich
    for i, resp in ipairs(responses) do
        print("Response " .. i .. ":", resp.status_code)
    end
end
Parameter Typ Beschreibung
requests table Array von {method, url, options?}

Gibt zurück: responses, errors - Arrays indiziert nach Anfrageposition

Hinweise:

  • Anfragen werden gleichzeitig ausgeführt
  • Streaming (stream = true) wird in Batch nicht unterstützt
  • Ergebnis-Arrays entsprechen der Anfragereihenfolge (1-indiziert)

URL-Kodierung

Kodieren

local encoded = http_client.encode_uri("hello world")
-- "hello+world"

local url = "https://api.example.com/search?q=" .. http_client.encode_uri(query)

Dekodieren

local decoded, err = http_client.decode_uri("hello+world")
-- "hello world"

Berechtigungen

HTTP-Anfragen unterliegen der Sicherheitsrichtlinienauswertung.

Sicherheitsaktionen

Aktion Ressource Beschreibung
http_client.request URL Anfragen an bestimmte URLs erlauben/verweigern
http_client.unix_socket Socket-Pfad Unix-Socket-Verbindungen erlauben/verweigern
http_client.private_ip IP-Adresse Zugriff auf private IP-Bereiche erlauben/verweigern
http_client.insecure_tls URL Unsichere TLS-Verbindungen erlauben/verweigern (Verifizierung überspringen)

Zugriff prüfen

local security = require("security")

if security.can("http_client.request", "https://api.example.com/users") then
    local resp = http_client.get("https://api.example.com/users")
end

SSRF-Schutz

Private IP-Bereiche (10.x, 192.168.x, 172.16-31.x, localhost) sind standardmäßig blockiert. Zugriff erfordert die http_client.private_ip-Berechtigung.

local resp, err = http_client.get("http://192.168.1.1/admin")
-- Error: not allowed: private IP 192.168.1.1

Siehe Sicherheitsmodell für Richtlinienkonfiguration.

Fehler

Bedingung Art Wiederholbar
Sicherheitsrichtlinie verweigert errors.PERMISSION_DENIED nein
Private IP blockiert errors.PERMISSION_DENIED nein
Unix-Socket verweigert errors.PERMISSION_DENIED nein
Unsichere TLS verweigert errors.PERMISSION_DENIED nein
Ungültige URL oder Optionen errors.INVALID nein
Kein Kontext errors.INTERNAL nein
Netzwerkfehler errors.INTERNAL ja
Timeout errors.INTERNAL ja
local resp, err = http_client.get(url)
if err then
    if errors.is(err, errors.PERMISSION_DENIED) then
        print("Access denied:", err:message())
    elseif err:retryable() then
        print("Temporary error:", err:message())
    end
    return nil, err
end

Siehe Fehlerbehandlung für die Arbeit mit Fehlern.