Implement max request size limit for HTTPServerSimple.

This commit is contained in:
Relintai 2023-03-18 11:52:25 +01:00
parent e607aba732
commit a155e44491
6 changed files with 91 additions and 0 deletions

View File

@ -51,10 +51,23 @@ int HTTPParser::read_from_buffer(const char *p_buffer, const int p_data_length)
parsed_bytes = static_cast<int>(http_parser_execute(parser, settings, p_buffer, p_data_length));
_current_request_size += parsed_bytes;
if (_current_request_size >= max_request_size) {
_error = true;
#if PROTOCOL_ERROR_LOGGING_ENABLED
PLOG_ERR("_current_request_size >= max_request_size");
#endif
}
return parsed_bytes;
}
HTTPParser::HTTPParser() {
// Should always get set from the outside, if it remains 0 it's a bug.
max_request_size = 0;
_current_request_size = 0;
_is_ready = false;
_content_type = REQUEST_CONTENT_URLENCODED;
_multipart_form_is_file = false;
@ -206,6 +219,8 @@ int HTTPParser::on_message_begin() {
ERR_PRINT("Request was valid!");
}
_current_request_size = 0;
_in_header = true;
_content_type = REQUEST_CONTENT_URLENCODED;
_multipart_form_is_file = false;

View File

@ -22,6 +22,8 @@ public:
REQUEST_CONTENT_TEXT_PLAIN,
};
uint64_t max_request_size;
Ref<SimpleWebServerRequest> get_next_request();
int get_request_count() const;
@ -42,6 +44,8 @@ protected:
String _partial_data;
uint64_t _current_request_size;
Ref<SimpleWebServerRequest> _request;
Vector<Ref<SimpleWebServerRequest>> _requests;

View File

@ -340,6 +340,7 @@ HTTPServerConnection::HTTPServerConnection() {
_http_server = nullptr;
_http_parser.instance();
_http_parser->max_request_size = max_request_size;
time = 0;
memset(req_buf, 0, sizeof(req_buf));
@ -428,6 +429,9 @@ void HTTPServerSimple::poll() {
connection->_web_server = _web_server;
connection->_http_server = this;
connection->max_request_size = max_request_size;
connection->_http_parser->max_request_size = max_request_size;
connection->use_ssl = use_ssl;
connection->key = key;

View File

@ -69,6 +69,8 @@ public:
WebServerSimple *_web_server;
HTTPServerSimple *_http_server;
uint64_t max_request_size;
bool use_ssl = false;
Ref<CryptoKey> key;
@ -98,6 +100,8 @@ public:
WebServerSimple *_web_server;
uint64_t max_request_size;
RBMap<String, String> mimes;
Ref<X509Certificate> cert;

View File

@ -105,6 +105,22 @@ void WebServerSimple::set_worker_thread_count(const int val) {
_worker_thread_count = val;
}
WebServerSimple::MaxRequestSizeTypes WebServerSimple::get_max_request_size_type() {
return _max_request_size_type;
}
void WebServerSimple::set_max_request_size_type(const MaxRequestSizeTypes val) {
_max_request_size_type = val;
_apply_max_request_size_type();
}
int WebServerSimple::get_max_request_size() {
return _max_request_size;
}
void WebServerSimple::set_max_request_size(const int val) {
_max_request_size = val;
_apply_max_request_size_type();
}
void WebServerSimple::add_mime_type(const String &file_extension, const String &mime_type) {
_server->mimes[file_extension] = mime_type;
}
@ -200,6 +216,9 @@ void WebServerSimple::_stop() {
}
WebServerSimple::WebServerSimple() {
_max_request_size_type = MAX_REQUEST_SIZE_TYPE_MEGA_BYTE;
_max_request_size = 3;
_bind_port = 8080;
_bind_host = "127.0.0.1";
@ -216,6 +235,8 @@ WebServerSimple::WebServerSimple() {
_server.instance();
_server->_web_server = this;
_apply_max_request_size_type();
}
WebServerSimple::~WebServerSimple() {
@ -228,6 +249,10 @@ WebServerSimple::~WebServerSimple() {
}
}
void WebServerSimple::_apply_max_request_size_type() {
_server->max_request_size = (static_cast<uint64_t>(1) << (10 * static_cast<uint64_t>(_max_request_size_type))) * static_cast<uint64_t>(_max_request_size);
}
void WebServerSimple::_notification(int p_what) {
if (p_what == NOTIFICATION_INTERNAL_PROCESS) {
if (_single_threaded_poll) {
@ -271,10 +296,23 @@ void WebServerSimple::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_worker_thread_count", "val"), &WebServerSimple::set_worker_thread_count);
ADD_PROPERTY(PropertyInfo(Variant::INT, "worker_thread_count"), "set_worker_thread_count", "get_worker_thread_count");
ClassDB::bind_method(D_METHOD("get_max_request_size_type"), &WebServerSimple::get_max_request_size_type);
ClassDB::bind_method(D_METHOD("set_max_request_size_type", "val"), &WebServerSimple::set_max_request_size_type);
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_request_size_type", PROPERTY_HINT_ENUM, "B,KB,MB,GB"), "set_max_request_size_type", "get_max_request_size_type");
ClassDB::bind_method(D_METHOD("get_max_request_size"), &WebServerSimple::get_max_request_size);
ClassDB::bind_method(D_METHOD("set_max_request_size", "val"), &WebServerSimple::set_max_request_size);
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_request_size"), "set_max_request_size", "get_max_request_size");
ClassDB::bind_method(D_METHOD("add_mime_type", "file_extension", "mime_type"), &WebServerSimple::add_mime_type);
ClassDB::bind_method(D_METHOD("remove_mime_type", "file_extension"), &WebServerSimple::remove_mime_type);
ClassDB::bind_method(D_METHOD("is_running"), &WebServerSimple::is_running);
BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_BYTE);
BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_KILO_BYTE);
BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_MEGA_BYTE);
BIND_ENUM_CONSTANT(MAX_REQUEST_SIZE_TYPE_GIGA_BYTE);
}
void WebServerSimple::_server_thread_poll(void *data) {

View File

@ -47,6 +47,13 @@ class WebServerSimple : public WebServer {
GDCLASS(WebServerSimple, WebServer);
public:
enum MaxRequestSizeTypes {
MAX_REQUEST_SIZE_TYPE_BYTE = 0,
MAX_REQUEST_SIZE_TYPE_KILO_BYTE = 1,
MAX_REQUEST_SIZE_TYPE_MEGA_BYTE = 2,
MAX_REQUEST_SIZE_TYPE_GIGA_BYTE = 3,
};
int get_bind_port();
void set_bind_port(const int val);
@ -71,6 +78,18 @@ public:
int get_worker_thread_count();
void set_worker_thread_count(const int val);
MaxRequestSizeTypes get_max_request_size_type();
void set_max_request_size_type(const MaxRequestSizeTypes val);
// Note, that the implementation is extremely simple for now.
// This includes the entire request header, including file uploads,
// as right now uploaded files are stored in memory,
// so this will not change until temp files are implemented.
// (A big file upload / request can eat all the ram in a server!)
// Also 0 means 0, not unlimited -> This should NOT change (Reason: line above).
int get_max_request_size();
void set_max_request_size(const int val);
void add_mime_type(const String &file_extension, const String &mime_type);
void remove_mime_type(const String &file_extension);
@ -83,6 +102,8 @@ public:
~WebServerSimple();
protected:
void _apply_max_request_size_type();
void _notification(int p_what);
static void _bind_methods();
@ -101,6 +122,9 @@ protected:
bool _single_threaded_poll;
MaxRequestSizeTypes _max_request_size_type;
int _max_request_size;
Ref<HTTPServerSimple> _server;
bool _server_quit;
Mutex _server_lock;
@ -110,4 +134,6 @@ protected:
static void _server_thread_poll(void *data);
};
VARIANT_ENUM_CAST(WebServerSimple::MaxRequestSizeTypes);
#endif