Files
leonwww/flumi/Scripts/NetworkRequest.gd

208 lines
5.5 KiB
GDScript3
Raw Normal View History

2025-09-05 19:07:21 +03:00
class_name NetworkRequest
extends RefCounted
enum RequestType {
FETCH,
DOC,
CSS,
LUA,
FONT,
IMG,
SOCKET,
OTHER
}
enum RequestStatus {
PENDING,
SUCCESS,
ERROR,
CANCELLED
}
var id: String
var name: String
var url: String
var method: String
var type: RequestType
var status: RequestStatus
var status_code: int
var status_text: String
var size: int
var time_ms: float
var start_time: float
var end_time: float
var request_headers: Dictionary = {}
var response_headers: Dictionary = {}
var request_body: String = ""
var response_body: String = ""
var response_body_bytes: PackedByteArray = []
var mime_type: String = ""
var is_from_lua: bool = false
func _init(request_url: String = "", request_method: String = "GET"):
id = generate_id()
url = request_url
method = request_method.to_upper()
name = extract_name_from_url(url)
type = determine_type_from_url(url)
status = RequestStatus.PENDING
status_code = 0
status_text = ""
size = 0
time_ms = 0.0
start_time = Time.get_ticks_msec()
end_time = 0.0
func generate_id() -> String:
return str(Time.get_ticks_msec()) + "_" + str(randi())
func extract_name_from_url(request_url: String) -> String:
if request_url.is_empty():
return "Unknown"
var parts = request_url.split("/")
if parts.size() > 0:
var filename = parts[-1]
if filename.is_empty() and parts.size() > 1:
filename = parts[-2]
if "?" in filename:
filename = filename.split("?")[0]
if "#" in filename:
filename = filename.split("#")[0]
return filename if not filename.is_empty() else "/"
return request_url
func determine_type_from_url(request_url: String) -> RequestType:
var lower_url = request_url.to_lower()
if lower_url.ends_with(".html") or lower_url.ends_with(".htm"):
return RequestType.DOC
elif lower_url.ends_with(".css"):
return RequestType.CSS
elif lower_url.ends_with(".lua") or lower_url.ends_with(".luau"):
return RequestType.LUA
elif lower_url.ends_with(".woff") or lower_url.ends_with(".woff2") or lower_url.ends_with(".ttf") or lower_url.ends_with(".otf"):
return RequestType.FONT
elif lower_url.ends_with(".png") or lower_url.ends_with(".jpg") or lower_url.ends_with(".jpeg") or lower_url.ends_with(".gif") or lower_url.ends_with(".webp") or lower_url.ends_with(".svg") or lower_url.ends_with(".bmp"):
return RequestType.IMG
elif lower_url.begins_with("ws://") or lower_url.begins_with("wss://"):
return RequestType.SOCKET
if not mime_type.is_empty():
var lower_mime = mime_type.to_lower()
if lower_mime.begins_with("text/html"):
return RequestType.DOC
elif lower_mime.begins_with("text/css"):
return RequestType.CSS
elif lower_mime.begins_with("image/"):
return RequestType.IMG
elif lower_mime.begins_with("font/") or lower_mime == "application/font-woff" or lower_mime == "application/font-woff2":
return RequestType.FONT
if is_from_lua:
return RequestType.FETCH
return RequestType.OTHER
func set_response(response_status_code: int, response_status_text: String, response_headers_dict: Dictionary, response_body_content: String, body_bytes: PackedByteArray = []):
end_time = Time.get_ticks_msec()
time_ms = end_time - start_time
status_code = response_status_code
status_text = response_status_text
response_headers = response_headers_dict
response_body = response_body_content
response_body_bytes = body_bytes if not body_bytes.is_empty() else response_body_content.to_utf8_buffer()
size = response_body_bytes.size()
for header_name in response_headers:
if header_name.to_lower() == "content-type":
mime_type = response_headers[header_name].split(";")[0].strip_edges()
break
type = determine_type_from_url(url)
if response_status_code >= 200 and response_status_code < 300:
status = RequestStatus.SUCCESS
else:
status = RequestStatus.ERROR
func set_error(error_message: String):
end_time = Time.get_ticks_msec()
time_ms = end_time - start_time
status = RequestStatus.ERROR
status_text = error_message
func get_status_display() -> String:
match status:
RequestStatus.PENDING:
return "Pending"
RequestStatus.SUCCESS:
return str(status_code)
RequestStatus.ERROR:
return str(status_code) if status_code > 0 else "Failed"
RequestStatus.CANCELLED:
return "Cancelled"
_:
return "Unknown"
func get_type_display() -> String:
match type:
RequestType.FETCH:
return "Fetch"
RequestType.DOC:
return "Doc"
RequestType.CSS:
return "CSS"
RequestType.LUA:
return "Lua"
RequestType.FONT:
return "Font"
RequestType.IMG:
return "Img"
RequestType.SOCKET:
return "Socket"
RequestType.OTHER:
return "Other"
_:
return "Unknown"
static func format_bytes(given_size: int) -> String:
if given_size < 1024:
return str(given_size) + " B"
elif given_size < 1024 * 1024:
return str(given_size / 1024) + " KB"
else:
return str(given_size / (1024 * 1024)) + " MB"
func get_time_display() -> String:
if status == RequestStatus.PENDING:
return "Pending"
if time_ms < 1000:
return str(int(time_ms)) + " ms"
else:
return "%.1f s" % (time_ms / 1000.0)
func get_icon_texture() -> Texture2D:
match type:
RequestType.FETCH:
return load("res://Assets/Icons/download.svg")
RequestType.DOC:
return load("res://Assets/Icons/file-text.svg")
RequestType.CSS:
return load("res://Assets/Icons/palette.svg")
RequestType.LUA:
return load("res://Assets/Icons/braces.svg")
RequestType.FONT:
return load("res://Assets/Icons/braces.svg")
RequestType.IMG:
return load("res://Assets/Icons/image.svg")
RequestType.SOCKET:
return load("res://Assets/Icons/arrow-down-up.svg")
_:
return load("res://Assets/Icons/search.svg")