Http (Lua API)
Async HTTP/HTTPS client. Available globally as Http. All callbacks fire on the main thread, so you can touch any engine state — node properties, asset references, UI widgets — directly from inside without locking.
For architecture, platform support, and the C++ surface, see Networking → HTTP Client.
Http.Get("https://api.example.com/status", function(r)
if r:IsSuccess() then
print("OK", r:GetStatus(), #r:GetBody(), "bytes")
else
print("Error", r:GetStatus(), r:GetError())
end
end)
Top-level functions
Http.Get(url, callback) → handle
Performs a GET. The callback fires on the main thread when the response arrives.
Http.Get("https://example.com/foo", function(r) print(r:GetStatus()) end)
Http.Post(url, body, callback) → handle
Performs a POST with body as raw bytes. Set Content-Type via the Request builder if needed.
Http.Post("https://example.com/items", "name=test&count=3", function(r) ... end)
Http.Put(url, body, callback) → handle
Http.Patch(url, body, callback) → handle
Http.Delete(url, callback) → handle
Same shapes as Post (DELETE has no body).
Http.Request(verb, url) → request
Returns a chainable request builder. Use this when you need headers, body content-type control, custom timeout, or SSL toggle.
verb is "GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", or "OPTIONS" (case-insensitive).
Http.Request("POST", "https://example.com/api")
:Header("Content-Type", "application/json")
:Body('{"foo":"bar"}')
:Send(function(r) print(r:GetStatus()) end)
Http.IsAvailable() → bool
Returns false on platforms without HTTP support (Android), or on Linux when libcurl4 isn't installed. Always true on Windows / 3DS / Wii / GCN with the standard build.
Http.GetMissingDependencyMessage() → string
Diagnostic string when IsAvailable() is false. Empty string otherwise.
if not Http.IsAvailable() then
Log.Warning("HTTP unavailable: " .. Http.GetMissingDependencyMessage())
end
Request builder
Returned by Http.Request(verb, url). Every method except :Send returns the same request, so they chain.
| Method | Purpose |
|---|---|
:Header(name, value) |
Add (or replace) a request header. Names are case-insensitive. |
:Body(string) |
Set the request body. Raw bytes — set Content-Type separately if needed. |
:Timeout(ms) |
Per-request timeout in milliseconds. Default 10000. |
:VerifySsl(bool) |
Toggle TLS certificate verification. Default true. |
:Send(callback) |
Sends the request and returns a handle. Callback fires on main thread on completion. |
local req = Http.Request("POST", "https://api.example.com/login")
:Header("Content-Type", "application/json")
:Header("Accept", "application/json")
:Body('{"user":"alice","password":"hunter2"}')
:Timeout(3000)
local handle = req:Send(function(r)
if r:IsSuccess() then
local data = r:GetJson()
SaveToken(data.token)
else
print("Login failed:", r:GetStatus(), r:GetError())
end
end)
Response object
Passed to your callback. Every method below is non-blocking and safe to call multiple times.
| Method | Returns |
|---|---|
:IsSuccess() |
true when status is in [200, 300) and there was no transport / TLS / cancel / parse error. |
:GetStatus() |
HTTP status code as integer (200, 404, 500, …). 0 when the request never reached the server. |
:GetError() |
Error string ("Cancelled", "Timeout", "Network", …) or nil when none. |
:GetBody() |
Response body as a Lua string (raw bytes — may contain nulls). |
:GetHeader(name) |
Header value (case-insensitive lookup), or nil if absent. |
:GetHeaders() |
Lua table of all response headers, name → value. |
:GetFinalUrl() |
URL after following any redirects. |
:GetJson() |
Lua table parsed from a JSON body. Returns nil, errMessage on parse failure. |
:GetTexture() |
New Texture asset decoded from a PNG/JPG body. nil on failure (incl. non-power-of-two dimensions). |
:GetSoundWave() |
New SoundWave asset decoded from a WAV body. nil on failure. (OGG support is planned.) |
:GetJson() shapes
JSON values map to Lua as follows:
| JSON | Lua |
|---|---|
null |
nil |
true / false |
true / false |
| number (integer) | integer |
| number (float) | number |
| string | string |
array [a, b, c] |
table with integer keys 1..n |
object {"k": v} |
table with string keys |
Nested structures recurse. JSON booleans / nulls round-trip cleanly; numeric precision matches Polyphase's Lua build (single-precision float on console builds).
Http.Get("https://api.example.com/scores", function(r)
local data, err = r:GetJson()
if data == nil then
Log.Error("JSON parse failed: " .. tostring(err))
return
end
-- e.g. data = { scores = { { name="alice", value=1200 }, ... } }
for i, entry in ipairs(data.scores) do
print(i, entry.name, entry.value)
end
end)
Request handle
Returned by every send variant. Lets you cancel an in-flight request and check whether it was cancelled.
| Method | Purpose |
|---|---|
:Cancel() |
Mark the request for cancellation. Safe to call from anywhere, multiple times. The callback still fires with IsSuccess() false and GetError() set. |
:IsCancelled() |
true if :Cancel() has been called. |
local handle = Http.Get("https://example.com/slow-endpoint", onResponse)
-- Later, when the player abandons the operation:
handle:Cancel()
Defaults
| Field | Default |
|---|---|
| Timeout | 10000 ms (10s) |
| Max redirects | 5 |
| Max body size | 64 MiB |
| SSL verify | on |
| User-Agent | Polyphase/1.0 |
Override via the request builder.
Worked examples
Fetch JSON and update a node
Http.Get("https://api.example.com/status", function(r)
if not r:IsSuccess() then return end
local data = r:GetJson()
if data and data.online then
statusLabel:SetText("Server online")
else
statusLabel:SetText("Server down")
end
end)
Send a JSON body
Most APIs that take JSON expect a Content-Type: application/json header. Use the builder so you can set it.
local payload = '{"event":"player_died","level":3}'
Http.Request("POST", "https://api.example.com/telemetry")
:Header("Content-Type", "application/json")
:Body(payload)
:Send(function(r)
if not r:IsSuccess() then
Log.Warning("Telemetry failed: " .. r:GetStatus())
end
end)
Download an avatar texture
Http.Get(player.avatarUrl, function(r)
local tex = r:GetTexture()
if tex == nil then
Log.Warning("Avatar decode failed for " .. player.name)
return
end
avatarWidget:SetTexture(tex)
end)
Texture decode requires power-of-two image dimensions. For arbitrary user uploads, host them as 64×64, 128×128, 256×256, etc., or run them through a resize pipeline before serving.
Stream a sound effect
Http.Get("https://cdn.example.com/sfx/bell.wav", function(r)
local snd = r:GetSoundWave()
if snd then Audio.PlaySound2D(snd, 1.0, 1.0) end
end)
WAV decode supports 8/16-bit PCM, mono and stereo, any sample rate. OGG runtime decode is planned.
Cancel on scene change
local MyScript = {}
function MyScript:Start()
self.handle = Http.Get(longPollUrl, function(r)
if r:IsSuccess() and r:GetError() ~= "Cancelled" then
self:OnDataReceived(r:GetJson())
end
end)
end
function MyScript:Destroy()
if self.handle then self.handle:Cancel() end
end
return MyScript
Custom timeout for a slow endpoint
Http.Request("GET", "https://api.example.com/heavy-report")
:Timeout(60000) -- 60 seconds
:Send(function(r)
if r:GetError() == "Timeout" then
print("Report took too long, giving up")
return
end
ProcessReport(r:GetBody())
end)
Check that HTTP is wired up before kicking off a flow
if not Http.IsAvailable() then
Log.Error("HTTP unavailable: " .. Http.GetMissingDependencyMessage())
return
end
Common pitfalls
- Capturing
selfin callbacks. Define your callback as a closure that capturesselffrom the enclosing function — Lua doesn't auto-bind methods, so passingself.OnReplydirectly drops theselfargument.
lua
function MyScript:Fetch()
Http.Get(url, function(r) self:OnReply(r) end) -- ✅
Http.Get(url, self.OnReply) -- ❌ self lost
end
-
Using the response after the callback returns. The response object is alive as long as your Lua state holds a reference. If you stash
rinself.lastResponse, that's fine. If you let the callback exit and the local goes out of scope, the response is GC'd. -
Forgetting
Content-Typeon POST. Many APIs return 415 (Unsupported Media Type) without it. Use the builder and:Header("Content-Type", "application/json"). -
Treating cancelled callbacks as failures. A cancelled request still calls your callback. Check
r:GetError() == "Cancelled"before logging or retrying — it's not a real failure. -
Power-of-two textures.
GetTexture()rejects non-PoT dimensions for runtime safety on consoles. Pre-resize content to PoT or use square 256/512/1024 source images.
See also
- Networking → HTTP Client — architecture, C++ API, platform / TLS details, JSON helpers.
- Lua Audio API — pair
:GetSoundWave()withAudio.PlaySound2D(). - Texture Lua API — what you can do with the
Texturereturned by:GetTexture(). Polyphase-Examples/HTTP-Client-Demo/Scripts/— runnable verification tests for every feature documented here.