From 24e120142e0135bf18a55053d209efafadfa1530 Mon Sep 17 00:00:00 2001 From: Relintai Date: Fri, 1 Jul 2022 17:40:47 +0200 Subject: [PATCH] Implement basig http header parsing, and also send the request through the WebNode tree. --- .../web/http_server_simple/http_parser.cpp | 117 +++++++++++++++--- modules/web/http_server_simple/http_parser.h | 12 +- .../http_server_simple/http_server_simple.cpp | 42 +++---- .../http_server_simple/http_server_simple.h | 3 + .../simple_web_server_request.cpp | 23 +++- .../simple_web_server_request.h | 12 ++ .../http_server_simple/web_server_simple.cpp | 5 + 7 files changed, 166 insertions(+), 48 deletions(-) diff --git a/modules/web/http_server_simple/http_parser.cpp b/modules/web/http_server_simple/http_parser.cpp index 5f24d7da9..92b8cd819 100644 --- a/modules/web/http_server_simple/http_parser.cpp +++ b/modules/web/http_server_simple/http_parser.cpp @@ -1,14 +1,22 @@ #include "http_parser.h" #include "../http/web_server_request.h" - #include "./http_parser/http_parser.h" -Ref HTTPParser::get_request() { - return _request; +#include "simple_web_server_request.h" + +Ref HTTPParser::get_next_request() { + ERR_FAIL_COND_V(_requests.size() == 0, Ref()); + + Ref rn = _requests[0]; + + _requests.remove(0); + + return rn; } -void HTTPParser::set_request(const Ref &val) { - _request = val; + +int HTTPParser::get_request_count() const { + return _requests.size(); } bool HTTPParser::is_ready() const { @@ -22,8 +30,6 @@ void HTTPParser::reset() { //returns the index where processing was ended -> start of the next query if != data_length int HTTPParser::read_from_buffer(const char *p_buffer, const int p_data_length) { - ERR_FAIL_COND_V(!_request.is_valid(), p_data_length); - int parsed_bytes = 0; parsed_bytes = static_cast(http_parser_execute(parser, settings, p_buffer, p_data_length)); @@ -76,50 +82,127 @@ String HTTPParser::chr_len_to_str(const char *at, size_t length) { return ret; } +#define MESSAGE_DEBUG 0 + int HTTPParser::on_message_begin() { - print_error("begin"); + if (_request.is_valid()) { + ERR_PRINT("Request was valid!"); + } + + _in_header = true; + + _request.instance(); + +#if MESSAGE_DEBUG + ERR_PRINT("begin"); +#endif + return 0; } int HTTPParser::on_url(const char *at, size_t length) { + ERR_FAIL_COND_V(!_request.is_valid(), 0); + String s = chr_len_to_str(at, length); - print_error("url " + s); +#if MESSAGE_DEBUG + ERR_PRINT("url " + s); +#endif + + _request->set_parser_path(s); + return 0; } int HTTPParser::on_status(const char *at, size_t length) { + ERR_FAIL_COND_V(!_request.is_valid(), 0); + String s = chr_len_to_str(at, length); - print_error("status " + s); + +#if MESSAGE_DEBUG + ERR_PRINT("status " + s); +#endif + return 0; } int HTTPParser::on_header_field(const char *at, size_t length) { + ERR_FAIL_COND_V(!_request.is_valid(), 0); + String s = chr_len_to_str(at, length); - print_error("header_field " + s); + +#if MESSAGE_DEBUG + ERR_PRINT("header_field " + s); +#endif + + _queued_header_field = s; + return 0; } int HTTPParser::on_header_value(const char *at, size_t length) { + ERR_FAIL_COND_V(!_request.is_valid(), 0); + String s = chr_len_to_str(at, length); - print_error("header_val " + s); + +#if MESSAGE_DEBUG + ERR_PRINT("header_val " + s); +#endif + + _request->add_parameter(_queued_header_field, s); + + if (_queued_header_field == "Host") { + _request->set_host(s); + } + return 0; } int HTTPParser::on_headers_complete() { - print_error("headers_complete"); + ERR_FAIL_COND_V(!_request.is_valid(), 0); + +#if MESSAGE_DEBUG + ERR_PRINT("headers_complete"); +#endif + + _in_header = false; + return 0; } int HTTPParser::on_body(const char *at, size_t length) { + ERR_FAIL_COND_V(!_request.is_valid(), 0); + String s = chr_len_to_str(at, length); - print_error("on_body " + s); + +#if MESSAGE_DEBUG + ERR_PRINT("on_body " + s); +#endif + return 0; } int HTTPParser::on_message_complete() { - print_error("msg_copmlete"); + ERR_FAIL_COND_V(!_request.is_valid(), 0); + +#if MESSAGE_DEBUG + ERR_PRINT("msg_copmlete"); +#endif + + _requests.push_back(_request); + _request.unref(); + return 0; } int HTTPParser::on_chunk_header() { - print_error("chunk_header"); + ERR_FAIL_COND_V(!_request.is_valid(), 0); + +#if MESSAGE_DEBUG + ERR_PRINT("chunk_header"); +#endif + return 0; } int HTTPParser::on_chunk_complete() { - print_error("chunk_complete"); + ERR_FAIL_COND_V(!_request.is_valid(), 0); + +#if MESSAGE_DEBUG + ERR_PRINT("chunk_complete"); +#endif + return 0; } diff --git a/modules/web/http_server_simple/http_parser.h b/modules/web/http_server_simple/http_parser.h index bf68db567..caa731bc4 100644 --- a/modules/web/http_server_simple/http_parser.h +++ b/modules/web/http_server_simple/http_parser.h @@ -5,7 +5,7 @@ #include "core/reference.h" -class WebServerRequest; +class SimpleWebServerRequest; struct http_parser; struct http_parser_settings; @@ -13,8 +13,8 @@ class HTTPParser : public Reference { GDCLASS(HTTPParser, Reference); public: - Ref get_request(); - void set_request(const Ref &val); + Ref get_next_request(); + int get_request_count() const; bool is_ready() const; @@ -31,7 +31,8 @@ protected: String _partial_data; - Ref _request; + Ref _request; + Vector> _requests; bool _is_ready; @@ -62,6 +63,9 @@ private: http_parser *parser; http_parser_settings *settings; + + bool _in_header; + String _queued_header_field; }; #endif diff --git a/modules/web/http_server_simple/http_server_simple.cpp b/modules/web/http_server_simple/http_server_simple.cpp index bcd1dc269..12c4998af 100644 --- a/modules/web/http_server_simple/http_server_simple.cpp +++ b/modules/web/http_server_simple/http_server_simple.cpp @@ -32,6 +32,7 @@ #include "http_parser.h" #include "simple_web_server_request.h" +#include "web_server_simple.h" void HTTPServerSimple::stop() { server->stop(); @@ -186,35 +187,30 @@ void HTTPServerSimple::poll() { return; } - if (read == 0) { - // Busy, wait next poll - return; + if (read > 0) { + int buffer_start_index = 0; + while (true) { + char *rb = reinterpret_cast(&req_buf[buffer_start_index]); + buffer_start_index += _http_parser->read_from_buffer(rb, read); + + if (buffer_start_index >= read) { + break; + } + } } - int buffer_start_index = 0; - while (true) { - char *rb = reinterpret_cast(&req_buf[buffer_start_index]); - buffer_start_index += _http_parser->read_from_buffer(rb, read); + if (_http_parser->get_request_count() > 0) { + Ref request = _http_parser->get_next_request(); - if (_http_parser->is_ready()) { - Ref req; + request->_server = this; - req = _http_parser->get_request(); - - //handle request - - req.instance(); - _http_parser->set_request(req); - _http_parser->reset(); - } - - if (buffer_start_index >= read) { - return; - } + _web_server->server_handle_request(request); } } HTTPServerSimple::HTTPServerSimple() { + _web_server = nullptr; + mimes["html"] = "text/html"; mimes["js"] = "application/javascript"; mimes["json"] = "application/json"; @@ -222,11 +218,9 @@ HTTPServerSimple::HTTPServerSimple() { mimes["png"] = "image/png"; mimes["svg"] = "image/svg"; mimes["wasm"] = "application/wasm"; + server.instance(); _http_parser.instance(); - Ref req; - req.instance(); - _http_parser->set_request(req); stop(); } diff --git a/modules/web/http_server_simple/http_server_simple.h b/modules/web/http_server_simple/http_server_simple.h index 503aa0983..a94f6322e 100644 --- a/modules/web/http_server_simple/http_server_simple.h +++ b/modules/web/http_server_simple/http_server_simple.h @@ -38,6 +38,7 @@ #include "core/project_settings.h" class HTTPParser; +class WebServerSimple; class HTTPServerSimple : public Reference { public: @@ -51,6 +52,8 @@ public: HTTPServerSimple(); ~HTTPServerSimple(); + WebServerSimple *_web_server; + private: Ref server; Map mimes; diff --git a/modules/web/http_server_simple/simple_web_server_request.cpp b/modules/web/http_server_simple/simple_web_server_request.cpp index 9e0270a6f..12138c2c3 100644 --- a/modules/web/http_server_simple/simple_web_server_request.cpp +++ b/modules/web/http_server_simple/simple_web_server_request.cpp @@ -41,7 +41,11 @@ String SimpleWebServerRequest::get_file_data_str(const int index) const { } String SimpleWebServerRequest::get_parameter(const String &key) const { - return ""; + if (!_parameters.has(key)) { + return ""; + } + + return _parameters[key]; } void SimpleWebServerRequest::send_redirect(const String &location, const HTTPServerEnums::HTTPStatusCode status_code) { @@ -61,14 +65,27 @@ void SimpleWebServerRequest::send_file(const String &p_file_path) { } String SimpleWebServerRequest::parser_get_path() { - return ""; + return _parser_path; } String SimpleWebServerRequest::get_host() const { - return ""; + return _host; +} + +void SimpleWebServerRequest::add_parameter(const String &key, const String &value) { + _parameters[key] = value; +} + +void SimpleWebServerRequest::set_parser_path(const String &value) { + _parser_path = value; +} + +void SimpleWebServerRequest::set_host(const String &value) { + _host = value; } SimpleWebServerRequest::SimpleWebServerRequest() { + _server = nullptr; } SimpleWebServerRequest::~SimpleWebServerRequest() { diff --git a/modules/web/http_server_simple/simple_web_server_request.h b/modules/web/http_server_simple/simple_web_server_request.h index 75d5745c9..421d3223a 100644 --- a/modules/web/http_server_simple/simple_web_server_request.h +++ b/modules/web/http_server_simple/simple_web_server_request.h @@ -2,6 +2,7 @@ #define SIMPLE_WEB_SERVER_REQUEST_H #include "core/dictionary.h" +#include "core/hash_map.h" #include "core/ustring.h" #include "core/vector.h" @@ -14,6 +15,7 @@ class WebServerCookie; class HTTPSession; class WebPermission; class WebNode; +class HTTPServerSimple; class SimpleWebServerRequest : public WebServerRequest { GDCLASS(SimpleWebServerRequest, WebServerRequest); @@ -39,13 +41,23 @@ public: virtual String parser_get_path(); virtual String get_host() const; + void add_parameter(const String &key, const String &value); + void set_parser_path(const String &value); + void set_host(const String &value); + //virtual String get_path_full() const; SimpleWebServerRequest(); ~SimpleWebServerRequest(); + HTTPServerSimple *_server; + protected: static void _bind_methods(); + + HashMap _parameters; + String _parser_path; + String _host; }; #endif diff --git a/modules/web/http_server_simple/web_server_simple.cpp b/modules/web/http_server_simple/web_server_simple.cpp index 8b5a59be5..974bc30c4 100644 --- a/modules/web/http_server_simple/web_server_simple.cpp +++ b/modules/web/http_server_simple/web_server_simple.cpp @@ -33,6 +33,8 @@ #include "http_server_simple.h" void WebServerSimple::_start() { + WebServer::_start(); + const uint16_t bind_port = 8080; // Resolve host if needed. const String bind_host = "127.0.0.1"; @@ -64,12 +66,15 @@ void WebServerSimple::_start() { } void WebServerSimple::_stop() { + WebServer::_stop(); + MutexLock lock(server_lock); server->stop(); } WebServerSimple::WebServerSimple() { server.instance(); + server->_web_server = this; server_thread.start(_server_thread_poll, this); }