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.