Implement basig http header parsing, and also send the request through the WebNode tree.

This commit is contained in:
Relintai 2022-07-01 17:40:47 +02:00
parent 10150d67c8
commit 24e120142e
7 changed files with 166 additions and 48 deletions

View File

@ -1,14 +1,22 @@
#include "http_parser.h"
#include "../http/web_server_request.h"
#include "./http_parser/http_parser.h"
Ref<WebServerRequest> HTTPParser::get_request() {
return _request;
#include "simple_web_server_request.h"
Ref<SimpleWebServerRequest> HTTPParser::get_next_request() {
ERR_FAIL_COND_V(_requests.size() == 0, Ref<SimpleWebServerRequest>());
Ref<SimpleWebServerRequest> rn = _requests[0];
_requests.remove(0);
return rn;
}
void HTTPParser::set_request(const Ref<WebServerRequest> &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<int>(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;
}

View File

@ -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<WebServerRequest> get_request();
void set_request(const Ref<WebServerRequest> &val);
Ref<SimpleWebServerRequest> get_next_request();
int get_request_count() const;
bool is_ready() const;
@ -31,7 +31,8 @@ protected:
String _partial_data;
Ref<WebServerRequest> _request;
Ref<SimpleWebServerRequest> _request;
Vector<Ref<SimpleWebServerRequest>> _requests;
bool _is_ready;
@ -62,6 +63,9 @@ private:
http_parser *parser;
http_parser_settings *settings;
bool _in_header;
String _queued_header_field;
};
#endif

View File

@ -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<char *>(&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<char *>(&req_buf[buffer_start_index]);
buffer_start_index += _http_parser->read_from_buffer(rb, read);
if (_http_parser->get_request_count() > 0) {
Ref<SimpleWebServerRequest> request = _http_parser->get_next_request();
if (_http_parser->is_ready()) {
Ref<SimpleWebServerRequest> 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<SimpleWebServerRequest> req;
req.instance();
_http_parser->set_request(req);
stop();
}

View File

@ -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<TCP_Server> server;
Map<String, String> mimes;

View File

@ -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() {

View File

@ -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<String, String> _parameters;
String _parser_path;
String _host;
};
#endif

View File

@ -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);
}