Compare commits

...

7 Commits

5 changed files with 82 additions and 54 deletions

3
.gitignore vendored
View File

@ -9,3 +9,6 @@ export_presets.cfg
# Mono-specific ignores
.mono/
data_*/
# VSCode config folder
.vscode/

49
Main.gd
View File

@ -17,26 +17,7 @@ func _start_server(port: int = 3001) -> void:
return
_server = HTTPServer.new()
var dir := Directory.new()
if dir.open(server_dir) == OK:
if dir.list_dir_begin() != OK:
# TODO: show error to user here
return
var file_name := dir.get_next()
while file_name != "":
if !dir.current_is_dir():
if file_name.get_extension() == "import":
file_name = dir.get_next()
continue
print(file_name)
_server.endpoint(HTTPServer.Method.GET, "/%s" % file_name, funcref(self, "_serve_file"), [file_name])
file_name = dir.get_next()
_server.endpoint(HTTPServer.Method.GET, "/", funcref(self, "_serve_file"), ["index.html"])
_server.endpoint(HTTPServer.Method.GET, "/", funcref(self, "_serve_file"))
if _server.listen(port) != OK:
# TODO: show error to user here
@ -62,27 +43,25 @@ func _process(_delta: float) -> void:
return
func _serve_file(_request: HTTPServer.Request, response: HTTPServer.Response, binds: Array) -> void:
var file_name: String = binds[0] as String
print(file_name)
func _serve_file(request: HTTPServer.Request, response: HTTPServer.Response) -> void:
var file_name: String = request.endpoint()
if file_name == "/": # if the request is for root, serve index
file_name = "index.html"
var f := File.new()
var success = f.open("res://server_files/%s" % file_name, File.READ)
if success == OK:
var success = f.open(server_dir.plus_file(file_name), File.READ)
if success == OK: # TODO: handle other errors like file not found
var mime := mime_types.get(file_name)
response.header("content-type", mime.full_type)
response.type(mime)
# variant
# warning-ignore:incompatible_ternary
var data = f.get_as_text() if mime.type == 'text' else f.get_buffer(f.get_len())
var data = f.get_buffer(f.get_len())
response.data(data)
else:
response.header("content-type", "text/plain")
response.data("500 - Read Error")
response.type(mime_types.get("txt"))
response.status(500)
response.data("Internal Server Error")
func _on_ServerUI_start_server_button_pressed(port: int, new_dir: String) -> void:
@ -92,3 +71,7 @@ func _on_ServerUI_start_server_button_pressed(port: int, new_dir: String) -> voi
func _on_ServerUI_stop_server_button_pressed() -> void:
_stop_server()
func _on_ServerUI_server_folder_changed(new_path: String) -> void:
server_dir = new_path

View File

@ -10,5 +10,6 @@ script = ExtResource( 1 )
[node name="ServerUI" parent="." instance=ExtResource( 2 )]
[connection signal="server_folder_changed" from="ServerUI" to="." method="_on_ServerUI_server_folder_changed"]
[connection signal="start_server_button_pressed" from="ServerUI" to="." method="_on_ServerUI_start_server_button_pressed"]
[connection signal="stop_server_button_pressed" from="ServerUI" to="." method="_on_ServerUI_stop_server_button_pressed"]

View File

@ -13,7 +13,7 @@ const Status = preload("res://addons/http_server/status.gd")
var __endpoints: Dictionary = {
# key: [Int, String], array with 0 index representing method, 1 index representing endpoint
# value: [FuncRef, Array], index 0 = reference to function to call, index 1 = binds to pass to func
# value: FuncRef, reference to function to call
}
var __fallback: FuncRef = null
var __server: TCP_Server = null
@ -32,7 +32,7 @@ func endpoint(type: int, endpoint: String, function: FuncRef, binds: Array = [])
)
return
__endpoints[endpoint_hash] = [function, binds]
__endpoints[endpoint_hash] = function
func fallback(function: FuncRef) -> void:
@ -106,7 +106,7 @@ func __process_connection(connection: StreamPeerTCP) -> void:
body = PoolStringArray(body_parts).join("\r\n")
var response: Response = __process_request(method, endpoint, headers, body)
connection.put_data(response.to_utf8())
connection.put_data(response.get_data())
func __process_request(method: String, endpoint: String, headers: Dictionary, body: String) -> Response:
@ -121,20 +121,13 @@ func __process_request(method: String, endpoint: String, headers: Dictionary, bo
var endpoint_func: FuncRef = null
var endpoint_parts: PoolStringArray = endpoint.split("/", false)
var binds
# special case for if endpoint is just root
if endpoint == "/":
var endpoint_hash: Array = [type, "/"]
if __endpoints.has(endpoint_hash):
endpoint_func = __endpoints[endpoint_hash][0]
binds = __endpoints[endpoint_hash][1]
else:
while (!endpoint_func && !endpoint_parts.empty()):
while !endpoint_func:
var endpoint_hash: Array = [type, "/" + endpoint_parts.join("/")]
if __endpoints.has(endpoint_hash):
endpoint_func = __endpoints[endpoint_hash][0]
binds = __endpoints[endpoint_hash][1]
endpoint_func = __endpoints[endpoint_hash]
elif endpoint_parts.empty():
break
else:
endpoint_parts.remove(endpoint_parts.size() - 1)
@ -160,10 +153,7 @@ func __process_request(method: String, endpoint: String, headers: Dictionary, bo
"[INF] Recieved request method: %s, endpoint: %s" % [method, endpoint]
)
if !binds:
endpoint_func.call_func(request, response)
else:
endpoint_func.call_func(request, response, binds)
return response

View File

@ -11,6 +11,7 @@ var __headers: Dictionary = {
# value: Variant, header value
}
var __status: int = 200
var __type: MimeTypeHelper.MimeType
# Public methods
@ -32,6 +33,10 @@ func status(status: int) -> void:
__status = status
func type(type: MimeTypeHelper.MimeType) -> void:
__type = type
func to_utf8() -> PoolByteArray:
var content = PoolStringArray()
@ -45,6 +50,7 @@ func to_utf8() -> PoolByteArray:
data = JSON.print(data)
__headers['content-length'] = len(data)
__headers["content-type"] = "application/octet-stream" if !__type else __type.full_type
for header in __headers:
content.append("%s: %s" % [header, String(__headers[header])])
@ -55,3 +61,48 @@ func to_utf8() -> PoolByteArray:
content.append(data)
return content.join("\r\n").to_utf8()
func get_data() -> PoolByteArray:
var res = __response_headers()
var data = __data
if !data:
return res
var type: MimeTypeHelper.MimeType = __type
if !type:
type = MimeTypeHelper.MimeType.new()
if data is String: # else, assume data is PoolByteArray
data = data.to_utf8()
res.append_array(data)
return res
# Private methods
func __response_headers() -> PoolByteArray:
var res = PoolStringArray()
res.append(Status.code_to_status_line(__status))
var data = __data
if !data:
data = Status.code_to_description(__status)
__headers["content-length"] = len(data)
__headers["content-type"] = "application/octet-stream" if !__type else __type.full_type
for header in __headers:
res.append("%s: %s" % [header, String(__headers[header])])
res.append("")
var s = res.join("\r\n")
s = s + "\r\n"
return s.to_utf8()