JSON API, fetch() API
This commit is contained in:
@@ -870,7 +870,7 @@ var HTML_CONTENT_DOM_MANIPULATION = """
|
|||||||
</body>
|
</body>
|
||||||
""".to_utf8_buffer()
|
""".to_utf8_buffer()
|
||||||
|
|
||||||
var HTML_CONTENT = """<head>
|
var HTML_CONTENTc = """<head>
|
||||||
<title>Input Events API Demo</title>
|
<title>Input Events API Demo</title>
|
||||||
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
|
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
|
||||||
<meta name="theme-color" content="#059669">
|
<meta name="theme-color" content="#059669">
|
||||||
@@ -1567,3 +1567,237 @@ var HTML_CONTENTa = """<head>
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
""".to_utf8_buffer()
|
""".to_utf8_buffer()
|
||||||
|
|
||||||
|
var HTML_CONTENT = """<head>
|
||||||
|
<title>Network & JSON API Demo</title>
|
||||||
|
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
|
||||||
|
<meta name="theme-color" content="#0891b2">
|
||||||
|
<meta name="description" content="Demonstrating Network fetch() and JSON APIs">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body { bg-[#ecfdf5] p-6 }
|
||||||
|
h1 { text-[#0891b2] text-3xl font-bold text-center }
|
||||||
|
h2 { text-[#0f766e] text-xl font-semibold }
|
||||||
|
.container { bg-[#ffffff] p-6 rounded-lg shadow-lg max-w-4xl mx-auto }
|
||||||
|
.button-group { flex gap-3 justify-center items-center flex-wrap }
|
||||||
|
.fetch-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#059669] text-white hover:bg-[#047857] }
|
||||||
|
.json-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#7c3aed] text-white hover:bg-[#6d28d9] }
|
||||||
|
.clear-button { px-4 py-2 rounded-lg font-medium cursor-pointer transition-colors bg-[#ef4444] text-white hover:bg-[#dc2626] }
|
||||||
|
.response-area { bg-[#f1f5f9] p-4 rounded-lg min-h-32 font-mono text-sm max-h-96 overflow-auto }
|
||||||
|
.info-box { bg-[#dbeafe] border border-[#3b82f6] p-4 rounded-lg }
|
||||||
|
.input-area { bg-[#f9fafb] p-4 rounded-lg border }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
-- Get UI elements
|
||||||
|
local responseArea = gurt.select('#response-area')
|
||||||
|
local fetchGetBtn = gurt.select('#fetch-get-btn')
|
||||||
|
local fetchPostBtn = gurt.select('#fetch-post-btn')
|
||||||
|
local jsonEncodeBtn = gurt.select('#json-encode-btn')
|
||||||
|
local jsonDecodeBtn = gurt.select('#json-decode-btn')
|
||||||
|
local clearLogBtn = gurt.select('#clear-log-btn')
|
||||||
|
local urlInput = gurt.select('#url-input')
|
||||||
|
local jsonInput = gurt.select('#json-input')
|
||||||
|
|
||||||
|
gurt.log('Network & JSON API demo script started.')
|
||||||
|
|
||||||
|
local logMessages = {}
|
||||||
|
|
||||||
|
-- Function to add message to log
|
||||||
|
local function addLog(message)
|
||||||
|
table.insert(logMessages, Time.format(Time.now(), '%H:%M:%S') .. ' - ' .. message)
|
||||||
|
if #logMessages > 50 then
|
||||||
|
table.remove(logMessages, 1)
|
||||||
|
end
|
||||||
|
responseArea.text = table.concat(logMessages, '\\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialize with default values
|
||||||
|
urlInput.text = 'https://jsonplaceholder.typicode.com/posts/1'
|
||||||
|
jsonInput.text = JSON.stringify({
|
||||||
|
name = 'Alice Johnson',
|
||||||
|
age = 28,
|
||||||
|
hobbies = {'reading', 'coding', 'gaming'},
|
||||||
|
active = true,
|
||||||
|
score = 95.5
|
||||||
|
})
|
||||||
|
|
||||||
|
-- GET Request Test
|
||||||
|
fetchGetBtn:on('click', function()
|
||||||
|
local url = urlInput.text
|
||||||
|
addLog('Making GET request to: ' .. url)
|
||||||
|
|
||||||
|
local response = fetch(url)
|
||||||
|
|
||||||
|
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
|
||||||
|
addLog('Response Headers: ' .. JSON.stringify(response.headers))
|
||||||
|
|
||||||
|
if response:ok() then
|
||||||
|
local responseText = response:text()
|
||||||
|
addLog('Response Body: ' .. responseText:sub(1, 200) .. (responseText:len() > 200 and '...' or ''))
|
||||||
|
|
||||||
|
-- Try to parse as JSON
|
||||||
|
local jsonData = response:json()
|
||||||
|
if jsonData then
|
||||||
|
addLog('Parsed JSON successfully')
|
||||||
|
end
|
||||||
|
else
|
||||||
|
addLog('Request failed with status: ' .. response.status)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- POST Request Test
|
||||||
|
fetchPostBtn:on('click', function()
|
||||||
|
local url = 'https://jsonplaceholder.typicode.com/posts'
|
||||||
|
local postData = {
|
||||||
|
title = 'Test Post from GURT',
|
||||||
|
body = 'This is a test post created using the GURT Network API',
|
||||||
|
userId = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
addLog('Making POST request to: ' .. url)
|
||||||
|
addLog('POST Data: ' .. JSON.stringify(postData))
|
||||||
|
|
||||||
|
local response = fetch(url, {
|
||||||
|
method = 'POST',
|
||||||
|
headers = {
|
||||||
|
['Content-Type'] = 'application/json'
|
||||||
|
},
|
||||||
|
body = JSON.stringify(postData)
|
||||||
|
})
|
||||||
|
|
||||||
|
addLog('Response Status: ' .. response.status .. ' ' .. response.statusText)
|
||||||
|
|
||||||
|
if response:ok() then
|
||||||
|
local responseText = response:text()
|
||||||
|
addLog('Created Resource: ' .. responseText)
|
||||||
|
else
|
||||||
|
addLog('POST request failed with status: ' .. response.status)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- JSON Encode Test
|
||||||
|
jsonEncodeBtn:on('click', function()
|
||||||
|
local inputText = jsonInput.text
|
||||||
|
addLog('Encoding text to JSON: ' .. inputText:sub(1, 100) .. (inputText:len() > 100 and '...' or ''))
|
||||||
|
|
||||||
|
-- Try to parse the input as Lua data first
|
||||||
|
local success, data = pcall(function()
|
||||||
|
-- Simple data structure for demo
|
||||||
|
return {
|
||||||
|
message = inputText,
|
||||||
|
timestamp = Time.now(),
|
||||||
|
random = math.random(1, 100),
|
||||||
|
nested = {
|
||||||
|
array = {1, 2, 3},
|
||||||
|
bool = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
if success then
|
||||||
|
local jsonString = JSON.stringify(data)
|
||||||
|
addLog('JSON Encoded: ' .. jsonString)
|
||||||
|
else
|
||||||
|
addLog('Error creating test data for encoding')
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- JSON Decode Test
|
||||||
|
jsonDecodeBtn:on('click', function()
|
||||||
|
local jsonText = jsonInput.text
|
||||||
|
addLog('Decoding JSON: ' .. jsonText:sub(1, 100) .. (jsonText:len() > 100 and '...' or ''))
|
||||||
|
|
||||||
|
local data, error = JSON.parse(jsonText)
|
||||||
|
|
||||||
|
if data then
|
||||||
|
addLog('JSON Decoded successfully!')
|
||||||
|
addLog('Data type: ' .. type(data))
|
||||||
|
if type(data) == 'table' then
|
||||||
|
local keys = {}
|
||||||
|
for k, v in pairs(data) do
|
||||||
|
table.insert(keys, k .. ':' .. type(v))
|
||||||
|
end
|
||||||
|
addLog('Keys: ' .. table.concat(keys, ', '))
|
||||||
|
end
|
||||||
|
addLog('Stringified back: ' .. JSON.stringify(data))
|
||||||
|
else
|
||||||
|
addLog('JSON Decode Error: ' .. (error or 'Unknown error'))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Clear log button
|
||||||
|
clearLogBtn:on('click', function()
|
||||||
|
logMessages = {}
|
||||||
|
responseArea.text = 'Log cleared.'
|
||||||
|
addLog('Network & JSON API demo ready')
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Initialize
|
||||||
|
addLog('Network & JSON API demo ready')
|
||||||
|
addLog('Try the buttons above to test network requests and JSON operations!')
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>🌐 Network & JSON API Demo</h1>
|
||||||
|
|
||||||
|
<div style="container mt-6">
|
||||||
|
<div style="info-box mb-6">
|
||||||
|
<h3 style="text-[#1e40af] font-semibold mb-2">API Examples:</h3>
|
||||||
|
<p><strong>Network:</strong> <code>fetch(url, {method: "POST", headers: {...}, body: "..."})</code></p>
|
||||||
|
<p><strong>JSON:</strong> <code>JSON.stringify(data)</code> and <code>JSON.parse(jsonString)</code></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Input Controls</h2>
|
||||||
|
<div style="input-area mb-6">
|
||||||
|
<div style="flex flex-col gap-3">
|
||||||
|
<div>
|
||||||
|
<label style="block text-sm font-medium mb-1">Test URL:</label>
|
||||||
|
<input id="url-input" type="text" style="w-full p-2 border border-gray-300 rounded-md" placeholder="Enter API URL..." />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label style="block text-sm font-medium mb-1">JSON Data:</label>
|
||||||
|
<textarea id="json-input" style="w-full p-2 border border-gray-300 rounded-md" rows="3" placeholder="Enter JSON data..."></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Network Tests</h2>
|
||||||
|
<div style="button-group mb-6">
|
||||||
|
<button id="fetch-get-btn" style="fetch-button">🔍 GET Request</button>
|
||||||
|
<button id="fetch-post-btn" style="fetch-button">📤 POST Request</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>JSON Tests</h2>
|
||||||
|
<div style="button-group mb-6">
|
||||||
|
<button id="json-encode-btn" style="json-button">📝 JSON Encode</button>
|
||||||
|
<button id="json-decode-btn" style="json-button">📖 JSON Decode</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="button-group mb-6">
|
||||||
|
<button id="clear-log-btn" style="clear-button">🧹 Clear Log</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Response Log</h2>
|
||||||
|
<div style="response-area mb-6">
|
||||||
|
<pre id="response-area">Initializing...</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="bg-[#f0f9ff] p-4 rounded-lg">
|
||||||
|
<h3 style="text-[#0369a1] font-semibold mb-2">Network API Features:</h3>
|
||||||
|
<ul style="text-[#075985] space-y-1 text-sm">
|
||||||
|
<li><strong>fetch(url, options):</strong> Makes HTTP requests with support for all methods</li>
|
||||||
|
<li><strong>Response methods:</strong> text(), json(), ok() for processing responses</li>
|
||||||
|
<li><strong>Headers & Body:</strong> Full control over request headers and body content</li>
|
||||||
|
<li><strong>Status & StatusText:</strong> Access to HTTP response status information</li>
|
||||||
|
</ul>
|
||||||
|
<h3 style="text-[#0369a1] font-semibold mt-4 mb-2">JSON API Features:</h3>
|
||||||
|
<ul style="text-[#075985] space-y-1 text-sm">
|
||||||
|
<li><strong>JSON.stringify():</strong> Alias for encode (browser compatibility)</li>
|
||||||
|
<li><strong>JSON.parse():</strong> Alias for decode (browser compatibility)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
""".to_utf8_buffer()
|
||||||
|
|||||||
37
flumi/Scripts/Utils/Lua/JSON.gd
Normal file
37
flumi/Scripts/Utils/Lua/JSON.gd
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
class_name LuaJSONUtils
|
||||||
|
extends RefCounted
|
||||||
|
|
||||||
|
static func setup_json_api(vm: LuauVM):
|
||||||
|
vm.lua_newtable()
|
||||||
|
|
||||||
|
vm.lua_pushcallable(_lua_json_parse_handler, "JSON.parse")
|
||||||
|
vm.lua_setfield(-2, "parse")
|
||||||
|
|
||||||
|
vm.lua_pushcallable(_lua_json_stringify_handler, "JSON.stringify")
|
||||||
|
vm.lua_setfield(-2, "stringify")
|
||||||
|
|
||||||
|
vm.lua_setglobal("JSON")
|
||||||
|
|
||||||
|
static func _lua_json_parse_handler(vm: LuauVM) -> int:
|
||||||
|
var json_string: String = vm.luaL_checkstring(1)
|
||||||
|
|
||||||
|
var json = JSON.new()
|
||||||
|
var parse_result = json.parse(json_string)
|
||||||
|
|
||||||
|
if parse_result == OK:
|
||||||
|
vm.lua_pushvariant(json.data)
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
# Return nil and error message
|
||||||
|
vm.lua_pushnil()
|
||||||
|
vm.lua_pushstring("JSON parse error: " + json.get_error_message())
|
||||||
|
return 2
|
||||||
|
|
||||||
|
static func _lua_json_stringify_handler(vm: LuauVM) -> int:
|
||||||
|
var value = vm.lua_tovariant(1)
|
||||||
|
|
||||||
|
var json = JSON.new()
|
||||||
|
var json_string = json.stringify(value)
|
||||||
|
|
||||||
|
vm.lua_pushstring(json_string)
|
||||||
|
return 1
|
||||||
1
flumi/Scripts/Utils/Lua/JSON.gd.uid
Normal file
1
flumi/Scripts/Utils/Lua/JSON.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://caxwx127g48l3
|
||||||
240
flumi/Scripts/Utils/Lua/Network.gd
Normal file
240
flumi/Scripts/Utils/Lua/Network.gd
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
class_name LuaNetworkUtils
|
||||||
|
extends RefCounted
|
||||||
|
|
||||||
|
static func setup_network_api(vm: LuauVM):
|
||||||
|
vm.lua_pushcallable(_lua_fetch_handler, "fetch")
|
||||||
|
vm.lua_setglobal("fetch")
|
||||||
|
|
||||||
|
static func _lua_fetch_handler(vm: LuauVM) -> int:
|
||||||
|
var url: String = vm.luaL_checkstring(1)
|
||||||
|
var options: Dictionary = {}
|
||||||
|
|
||||||
|
if vm.lua_gettop() >= 2 and vm.lua_istable(2):
|
||||||
|
options = vm.lua_todictionary(2)
|
||||||
|
|
||||||
|
# Default options
|
||||||
|
var method = options.get("method", "GET").to_upper()
|
||||||
|
var headers = options.get("headers", {})
|
||||||
|
var body = options.get("body", "")
|
||||||
|
|
||||||
|
# Set request options
|
||||||
|
var headers_array: PackedStringArray = []
|
||||||
|
for header_name in headers:
|
||||||
|
headers_array.append(str(header_name) + ": " + str(headers[header_name]))
|
||||||
|
|
||||||
|
var response_data = make_http_request(url, method, headers_array, body)
|
||||||
|
|
||||||
|
# Create response object with actual data
|
||||||
|
vm.lua_newtable()
|
||||||
|
|
||||||
|
# Add response properties
|
||||||
|
vm.lua_pushinteger(response_data.status)
|
||||||
|
vm.lua_setfield(-2, "status")
|
||||||
|
|
||||||
|
vm.lua_pushstring(response_data.status_text)
|
||||||
|
vm.lua_setfield(-2, "statusText")
|
||||||
|
|
||||||
|
# Convert response headers to table
|
||||||
|
vm.lua_newtable()
|
||||||
|
for header_name in response_data.headers:
|
||||||
|
vm.lua_pushstring(response_data.headers[header_name])
|
||||||
|
vm.lua_setfield(-2, header_name.to_lower())
|
||||||
|
vm.lua_setfield(-2, "headers")
|
||||||
|
|
||||||
|
# Store response body
|
||||||
|
vm.lua_pushstring(response_data.body)
|
||||||
|
vm.lua_setfield(-2, "_response_body")
|
||||||
|
|
||||||
|
# Add response methods
|
||||||
|
vm.lua_pushcallable(_response_text_handler, "response.text")
|
||||||
|
vm.lua_setfield(-2, "text")
|
||||||
|
|
||||||
|
vm.lua_pushcallable(_response_json_handler, "response.json")
|
||||||
|
vm.lua_setfield(-2, "json")
|
||||||
|
|
||||||
|
vm.lua_pushcallable(_response_ok_handler, "response.ok")
|
||||||
|
vm.lua_setfield(-2, "ok")
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
static func _response_text_handler(vm: LuauVM) -> int:
|
||||||
|
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||||
|
|
||||||
|
vm.lua_getfield(1, "_response_body")
|
||||||
|
var response_text = vm.lua_tostring(-1)
|
||||||
|
vm.lua_pop(1)
|
||||||
|
|
||||||
|
vm.lua_pushstring(response_text)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
static func _response_json_handler(vm: LuauVM) -> int:
|
||||||
|
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||||
|
|
||||||
|
vm.lua_getfield(1, "_response_body")
|
||||||
|
var response_text = vm.lua_tostring(-1)
|
||||||
|
vm.lua_pop(1)
|
||||||
|
|
||||||
|
var json = JSON.new()
|
||||||
|
var parse_result = json.parse(response_text)
|
||||||
|
|
||||||
|
if parse_result == OK:
|
||||||
|
vm.lua_pushvariant(json.data)
|
||||||
|
else:
|
||||||
|
vm.luaL_error("Invalid JSON in response")
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
static func _response_ok_handler(vm: LuauVM) -> int:
|
||||||
|
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||||
|
|
||||||
|
vm.lua_getfield(1, "status")
|
||||||
|
var status = vm.lua_tointeger(-1)
|
||||||
|
vm.lua_pop(1)
|
||||||
|
|
||||||
|
vm.lua_pushboolean(status >= 200 and status < 300)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
static func make_http_request(url: String, method: String, headers: PackedStringArray, body: String) -> Dictionary:
|
||||||
|
var http_client = HTTPClient.new()
|
||||||
|
var response_data = {
|
||||||
|
"status": 0,
|
||||||
|
"status_text": "Network Error",
|
||||||
|
"headers": {},
|
||||||
|
"body": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse URL
|
||||||
|
var url_parts = url.split("://")
|
||||||
|
if url_parts.size() < 2:
|
||||||
|
response_data.status = 400
|
||||||
|
response_data.status_text = "Bad Request - Invalid URL"
|
||||||
|
return response_data
|
||||||
|
|
||||||
|
var protocol = url_parts[0].to_lower()
|
||||||
|
var use_ssl = (protocol == "https" or protocol == "gurt+ssl")
|
||||||
|
var remaining_url = url_parts[1]
|
||||||
|
|
||||||
|
var host_path = remaining_url.split("/", false, 1)
|
||||||
|
var host = host_path[0]
|
||||||
|
var path = "/" + (host_path[1] if host_path.size() > 1 else "")
|
||||||
|
|
||||||
|
# Extract port if specified
|
||||||
|
var port = 80
|
||||||
|
if use_ssl:
|
||||||
|
port = 443
|
||||||
|
|
||||||
|
var host_parts = host.split(":")
|
||||||
|
if host_parts.size() > 1:
|
||||||
|
host = host_parts[0]
|
||||||
|
port = host_parts[1].to_int()
|
||||||
|
|
||||||
|
# Connect to host
|
||||||
|
var error: Error
|
||||||
|
if use_ssl:
|
||||||
|
var tls_options = TLSOptions.client()
|
||||||
|
error = http_client.connect_to_host(host, port, tls_options)
|
||||||
|
else:
|
||||||
|
error = http_client.connect_to_host(host, port)
|
||||||
|
if error != OK:
|
||||||
|
response_data.status = 0
|
||||||
|
response_data.status_text = "Connection Failed"
|
||||||
|
return response_data
|
||||||
|
|
||||||
|
# Wait for connection
|
||||||
|
var timeout_count = 0
|
||||||
|
while http_client.get_status() == HTTPClient.STATUS_CONNECTING or http_client.get_status() == HTTPClient.STATUS_RESOLVING:
|
||||||
|
http_client.poll()
|
||||||
|
OS.delay_msec(10)
|
||||||
|
timeout_count += 1
|
||||||
|
if timeout_count > 300: # 3 second timeout
|
||||||
|
response_data.status = 0
|
||||||
|
response_data.status_text = "Connection Timeout"
|
||||||
|
return response_data
|
||||||
|
|
||||||
|
if http_client.get_status() != HTTPClient.STATUS_CONNECTED:
|
||||||
|
response_data.status = 0
|
||||||
|
response_data.status_text = "Connection Failed"
|
||||||
|
return response_data
|
||||||
|
|
||||||
|
# Convert method string to HTTPClient.Method enum
|
||||||
|
var http_method: HTTPClient.Method
|
||||||
|
match method:
|
||||||
|
"GET":
|
||||||
|
http_method = HTTPClient.METHOD_GET
|
||||||
|
"POST":
|
||||||
|
http_method = HTTPClient.METHOD_POST
|
||||||
|
"PUT":
|
||||||
|
http_method = HTTPClient.METHOD_PUT
|
||||||
|
"DELETE":
|
||||||
|
http_method = HTTPClient.METHOD_DELETE
|
||||||
|
"HEAD":
|
||||||
|
http_method = HTTPClient.METHOD_HEAD
|
||||||
|
"OPTIONS":
|
||||||
|
http_method = HTTPClient.METHOD_OPTIONS
|
||||||
|
"PATCH":
|
||||||
|
http_method = HTTPClient.METHOD_PATCH
|
||||||
|
_:
|
||||||
|
http_method = HTTPClient.METHOD_GET
|
||||||
|
|
||||||
|
# Make request
|
||||||
|
error = http_client.request(http_method, path, headers, body)
|
||||||
|
if error != OK:
|
||||||
|
response_data.status = 0
|
||||||
|
response_data.status_text = "Request Failed"
|
||||||
|
return response_data
|
||||||
|
|
||||||
|
# Wait for response
|
||||||
|
timeout_count = 0
|
||||||
|
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
|
||||||
|
http_client.poll()
|
||||||
|
OS.delay_msec(10)
|
||||||
|
timeout_count += 1
|
||||||
|
if timeout_count > 1000: # 10 second timeout
|
||||||
|
response_data.status = 0
|
||||||
|
response_data.status_text = "Request Timeout"
|
||||||
|
return response_data
|
||||||
|
|
||||||
|
if http_client.get_status() != HTTPClient.STATUS_BODY and http_client.get_status() != HTTPClient.STATUS_CONNECTED:
|
||||||
|
response_data.status = 0
|
||||||
|
response_data.status_text = "Request Failed"
|
||||||
|
return response_data
|
||||||
|
|
||||||
|
# Get response
|
||||||
|
if http_client.has_response():
|
||||||
|
response_data.status = http_client.get_response_code()
|
||||||
|
|
||||||
|
# Get status text
|
||||||
|
match response_data.status:
|
||||||
|
200: response_data.status_text = "OK"
|
||||||
|
201: response_data.status_text = "Created"
|
||||||
|
204: response_data.status_text = "No Content"
|
||||||
|
400: response_data.status_text = "Bad Request"
|
||||||
|
401: response_data.status_text = "Unauthorized"
|
||||||
|
403: response_data.status_text = "Forbidden"
|
||||||
|
404: response_data.status_text = "Not Found"
|
||||||
|
500: response_data.status_text = "Internal Server Error"
|
||||||
|
_: response_data.status_text = "Unknown"
|
||||||
|
|
||||||
|
# Get response headers
|
||||||
|
var response_headers = http_client.get_response_headers_as_dictionary()
|
||||||
|
response_data.headers = response_headers
|
||||||
|
|
||||||
|
# Get response body
|
||||||
|
var body_bytes = PackedByteArray()
|
||||||
|
timeout_count = 0
|
||||||
|
while http_client.get_status() == HTTPClient.STATUS_BODY:
|
||||||
|
http_client.poll()
|
||||||
|
var chunk = http_client.read_response_body_chunk()
|
||||||
|
if chunk.size() > 0:
|
||||||
|
body_bytes.append_array(chunk)
|
||||||
|
timeout_count = 0
|
||||||
|
else:
|
||||||
|
OS.delay_msec(10)
|
||||||
|
timeout_count += 1
|
||||||
|
if timeout_count > 1000: # 10 second timeout for body
|
||||||
|
break
|
||||||
|
|
||||||
|
response_data.body = body_bytes.get_string_from_utf8()
|
||||||
|
|
||||||
|
http_client.close()
|
||||||
|
return response_data
|
||||||
1
flumi/Scripts/Utils/Lua/Network.gd.uid
Normal file
1
flumi/Scripts/Utils/Lua/Network.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://ffy8hyqtivhg
|
||||||
@@ -325,6 +325,12 @@ func _setup_additional_lua_apis():
|
|||||||
|
|
||||||
# Setup Clipboard API for threaded execution
|
# Setup Clipboard API for threaded execution
|
||||||
LuaClipboardUtils.setup_clipboard_api(lua_vm)
|
LuaClipboardUtils.setup_clipboard_api(lua_vm)
|
||||||
|
|
||||||
|
# Setup Network API for threaded execution
|
||||||
|
LuaNetworkUtils.setup_network_api(lua_vm)
|
||||||
|
|
||||||
|
# Setup JSON API for threaded execution
|
||||||
|
LuaJSONUtils.setup_json_api(lua_vm)
|
||||||
|
|
||||||
func _threaded_table_tostring_handler(vm: LuauVM) -> int:
|
func _threaded_table_tostring_handler(vm: LuauVM) -> int:
|
||||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||||
|
|||||||
Reference in New Issue
Block a user