mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-22 20:06:49 +01:00
- Now WebServerSimple can also use temporary files for uploads.
- Added move_file() and is_file_moved() helper methods to WebServerRequest. - get_file_length() in WebServerRequest now returns uint64_t. - Removed parse_files() from WebServerRequest. It's doesn't work well with how the http protocol works.
This commit is contained in:
parent
432478cb70
commit
f86c6440fb
@ -34,6 +34,8 @@
|
||||
#include "./http_parser/http_parser.h"
|
||||
#include "./multipart_parser_c/multipart_parser.h"
|
||||
#include "core/log/logger.h"
|
||||
#include "core/os/dir_access.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
#include "modules/web/http/web_server_request.h"
|
||||
|
||||
@ -97,7 +99,13 @@ int HTTPParser::read_from_buffer(const char *p_buffer, const int p_data_length)
|
||||
HTTPParser::HTTPParser() {
|
||||
// Should always get set from the outside, if it remains 0 it's a bug.
|
||||
max_request_size = 0;
|
||||
request_max_file_upload_size = 0;
|
||||
upload_file_store_type = WebServerSimple::FILE_UPLOAD_STORE_TYPE_MEMORY;
|
||||
|
||||
_upload_file_access = NULL;
|
||||
|
||||
_current_request_size = 0;
|
||||
_current_upload_files_size = 0;
|
||||
|
||||
_is_ready = false;
|
||||
_content_type = REQUEST_CONTENT_URLENCODED;
|
||||
@ -140,6 +148,20 @@ HTTPParser::~HTTPParser() {
|
||||
memdelete(parser);
|
||||
memdelete(settings);
|
||||
parser = nullptr;
|
||||
|
||||
if (_upload_file_access) {
|
||||
String path = _upload_file_access->get_path();
|
||||
_upload_file_access->close();
|
||||
memdelete(_upload_file_access);
|
||||
_upload_file_access = NULL;
|
||||
|
||||
DirAccess *d = DirAccess::create_for_path(path.get_base_dir());
|
||||
|
||||
if (d) {
|
||||
d->remove(path);
|
||||
memdelete(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPParser::_bind_methods() {
|
||||
@ -169,6 +191,7 @@ void HTTPParser::_process_multipart_header_value(const String &val) {
|
||||
|
||||
if (_multipart_form_name.length() >= 2 && _multipart_form_name.begins_with("\"") && _multipart_form_name.ends_with("\"")) {
|
||||
_multipart_form_name.remove(0);
|
||||
//TODO check if this should be _multipart_form_name.remove(_multipart_form_name.length() - 1);
|
||||
_multipart_form_name.remove(_multipart_form_name.size() - 1);
|
||||
}
|
||||
} else if (kk == "filename") {
|
||||
@ -178,8 +201,55 @@ void HTTPParser::_process_multipart_header_value(const String &val) {
|
||||
|
||||
if (_multipart_form_name.length() >= 2 && _multipart_form_name.begins_with("\"") && _multipart_form_name.ends_with("\"")) {
|
||||
_multipart_form_name.remove(0);
|
||||
//TODO check if this should be _multipart_form_name.remove(_multipart_form_name.length() - 1);
|
||||
_multipart_form_name.remove(_multipart_form_name.size() - 1);
|
||||
}
|
||||
|
||||
if (upload_file_store_type == WebServerSimple::FILE_UPLOAD_STORE_TYPE_TEMP_FILES) {
|
||||
if (_upload_file_access) {
|
||||
ERR_PRINT("BUG! if (_upload_file_access) is true!");
|
||||
_upload_file_access->close();
|
||||
memdelete(_upload_file_access);
|
||||
_upload_file_access = NULL;
|
||||
}
|
||||
|
||||
DirAccess *da = DirAccess::create_for_path(upload_temp_file_store_path);
|
||||
|
||||
if (!da) {
|
||||
// NO fallback!
|
||||
ERR_PRINT("upload_file_store_type == FILE_UPLOAD_STORE_TYPE_TEMP_FILES, but temp file path cannot be opened! Sending Error!");
|
||||
_error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Just use OS::Time for now. These names are internal, and if the file is not copied out it will get deleted automatically.
|
||||
// If filename exists just add values
|
||||
String fbase_name = upload_temp_file_store_path + itos(OS::get_singleton()->get_unix_time()) + "_" + itos(OS::get_singleton()->get_ticks_usec());
|
||||
|
||||
String fname = fbase_name;
|
||||
int fcounter = 0;
|
||||
|
||||
while (da->file_exists(fname) && fcounter < 100) {
|
||||
fname = fbase_name + "_" + itos(fcounter);
|
||||
++fcounter;
|
||||
}
|
||||
|
||||
memdelete(da);
|
||||
|
||||
Error err;
|
||||
_upload_file_access = FileAccess::open(fname, FileAccess::WRITE, &err);
|
||||
|
||||
if (err != OK) {
|
||||
ERR_PRINT(vformat("upload_file_store_type == FILE_UPLOAD_STORE_TYPE_TEMP_FILES, but temp file cannot be opened! Sending Error! Error: %d, FileName: %s", itos(err), fname));
|
||||
_error = true;
|
||||
|
||||
if (_upload_file_access) {
|
||||
memdelete(_upload_file_access);
|
||||
}
|
||||
}
|
||||
|
||||
_upload_file_full_path = fname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -576,12 +646,38 @@ int HTTPParser::on_multipart_part_data_cb(const char *at, size_t length) {
|
||||
ERR_PRINT("on_multipart_part_data_cb");
|
||||
#endif
|
||||
|
||||
int l = static_cast<int>(length);
|
||||
int mfdofs = _multipart_form_data.size();
|
||||
_multipart_form_data.resize(mfdofs + length);
|
||||
char *w = _multipart_form_data.ptrw();
|
||||
for (int i = 0; i < l; ++i) {
|
||||
w[mfdofs++] = at[i];
|
||||
if (_upload_file_access) {
|
||||
_upload_file_access->store_buffer((const uint8_t *)at, (uint64_t)length);
|
||||
|
||||
_current_upload_files_size += length;
|
||||
|
||||
if (_current_upload_files_size >= request_max_file_upload_size) {
|
||||
_error = true;
|
||||
|
||||
#if PROTOCOL_ERROR_LOGGING_ENABLED
|
||||
PLOG_ERR("_current_upload_files_size >= request_max_file_upload_size");
|
||||
#endif
|
||||
|
||||
_upload_file_access->close();
|
||||
memdelete(_upload_file_access);
|
||||
_upload_file_access = NULL;
|
||||
|
||||
DirAccess *d = DirAccess::create_for_path(_upload_file_full_path.get_base_dir());
|
||||
|
||||
if (d) {
|
||||
d->remove(_upload_file_full_path);
|
||||
memdelete(d);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
int l = static_cast<int>(length);
|
||||
int mfdofs = _multipart_form_data.size();
|
||||
_multipart_form_data.resize(mfdofs + length);
|
||||
char *w = _multipart_form_data.ptrw();
|
||||
for (int i = 0; i < l; ++i) {
|
||||
w[mfdofs++] = at[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -606,19 +702,27 @@ int HTTPParser::on_multipart_part_data_end_cb() {
|
||||
#endif
|
||||
|
||||
if (_multipart_form_is_file) {
|
||||
if (_multipart_form_data.size() > 0) {
|
||||
PoolByteArray file_data;
|
||||
int len = _multipart_form_data.size();
|
||||
file_data.resize(len);
|
||||
PoolByteArray::Write w = file_data.write();
|
||||
const char *r = _multipart_form_data.ptr();
|
||||
for (int i = 0; i < len; i++) {
|
||||
w[i] = r[i];
|
||||
if (_upload_file_access) {
|
||||
_upload_file_access->close();
|
||||
memdelete(_upload_file_access);
|
||||
_upload_file_access = NULL;
|
||||
|
||||
_request->add_file_temp_file(_multipart_form_name, _multipart_form_filename, _upload_file_full_path);
|
||||
} else {
|
||||
if (_multipart_form_data.size() > 0) {
|
||||
PoolByteArray file_data;
|
||||
int len = _multipart_form_data.size();
|
||||
file_data.resize(len);
|
||||
PoolByteArray::Write w = file_data.write();
|
||||
const char *r = _multipart_form_data.ptr();
|
||||
for (int i = 0; i < len; i++) {
|
||||
w[i] = r[i];
|
||||
}
|
||||
|
||||
w.release();
|
||||
|
||||
_request->add_file_memory(_multipart_form_name, _multipart_form_filename, file_data);
|
||||
}
|
||||
|
||||
w.release();
|
||||
|
||||
_request->add_file(_multipart_form_name, _multipart_form_filename, file_data);
|
||||
}
|
||||
} else {
|
||||
String s = String::utf8(_multipart_form_data.ptr(), _multipart_form_data.size());
|
||||
|
@ -34,9 +34,12 @@
|
||||
|
||||
#include "core/containers/vector.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/os/file_access.h"
|
||||
|
||||
#include "core/object/reference.h"
|
||||
|
||||
#include "web_server_simple.h"
|
||||
|
||||
class SimpleWebServerRequest;
|
||||
struct http_parser;
|
||||
struct http_parser_settings;
|
||||
@ -54,6 +57,10 @@ public:
|
||||
};
|
||||
|
||||
uint64_t max_request_size;
|
||||
uint64_t request_max_file_upload_size;
|
||||
|
||||
WebServerSimple::FileUploadStoreType upload_file_store_type;
|
||||
String upload_temp_file_store_path;
|
||||
|
||||
Ref<SimpleWebServerRequest> get_next_request();
|
||||
int get_request_count() const;
|
||||
@ -76,6 +83,10 @@ protected:
|
||||
String _partial_data;
|
||||
|
||||
uint64_t _current_request_size;
|
||||
uint64_t _current_upload_files_size;
|
||||
|
||||
String _upload_file_full_path;
|
||||
FileAccess *_upload_file_access;
|
||||
|
||||
Ref<SimpleWebServerRequest> _request;
|
||||
Vector<Ref<SimpleWebServerRequest>> _requests;
|
||||
|
@ -586,7 +586,6 @@ HTTPServerConnection::HTTPServerConnection() {
|
||||
_timeout_usec = 20 * 1000 * 1000;
|
||||
|
||||
_http_parser.instance();
|
||||
_http_parser->max_request_size = max_request_size;
|
||||
time = 0;
|
||||
|
||||
memset(req_buf, 0, sizeof(req_buf));
|
||||
@ -681,8 +680,10 @@ 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->_http_parser->request_max_file_upload_size = request_max_file_upload_size;
|
||||
connection->_http_parser->upload_file_store_type = upload_file_store_type;
|
||||
connection->_http_parser->upload_temp_file_store_path = upload_temp_file_store_path;
|
||||
|
||||
connection->use_ssl = use_ssl;
|
||||
connection->key = key;
|
||||
@ -842,6 +843,9 @@ HTTPServerSimple::HTTPServerSimple() {
|
||||
|
||||
server.instance();
|
||||
stop();
|
||||
|
||||
max_request_size = 0;
|
||||
request_max_file_upload_size = 0;
|
||||
}
|
||||
|
||||
HTTPServerSimple::~HTTPServerSimple() {
|
||||
|
@ -46,6 +46,8 @@
|
||||
|
||||
#include "modules/web/http/http_server_enums.h"
|
||||
|
||||
#include "web_server_simple.h"
|
||||
|
||||
class HTTPParser;
|
||||
class WebServerSimple;
|
||||
class WebServerRequest;
|
||||
@ -78,8 +80,6 @@ public:
|
||||
WebServerSimple *_web_server;
|
||||
HTTPServerSimple *_http_server;
|
||||
|
||||
uint64_t max_request_size;
|
||||
|
||||
bool use_ssl = false;
|
||||
Ref<CryptoKey> key;
|
||||
Ref<X509Certificate> _certificate;
|
||||
@ -126,6 +126,10 @@ public:
|
||||
WebServerSimple *_web_server;
|
||||
|
||||
uint64_t max_request_size;
|
||||
uint64_t request_max_file_upload_size;
|
||||
|
||||
WebServerSimple::FileUploadStoreType upload_file_store_type;
|
||||
String upload_temp_file_store_path;
|
||||
|
||||
RBMap<StringName, String> mimes;
|
||||
|
||||
|
@ -43,6 +43,8 @@
|
||||
#include "http_server_simple.h"
|
||||
#include "modules/web/http/web_permission.h"
|
||||
|
||||
#include "core/os/dir_access.h"
|
||||
|
||||
String SimpleWebServerRequest::get_cookie(const String &key) {
|
||||
for (int i = 0; i < _cookies.size(); ++i) {
|
||||
const CookieData &d = _cookies[i];
|
||||
@ -58,8 +60,6 @@ HTTPServerEnums::HTTPMethod SimpleWebServerRequest::get_method() const {
|
||||
return _method;
|
||||
}
|
||||
|
||||
void SimpleWebServerRequest::parse_files() {
|
||||
}
|
||||
int SimpleWebServerRequest::get_file_count() const {
|
||||
return _files.size();
|
||||
}
|
||||
@ -73,26 +73,122 @@ String SimpleWebServerRequest::get_file_key(const int index) const {
|
||||
|
||||
return _files[index].file_name;
|
||||
}
|
||||
int SimpleWebServerRequest::get_file_length(const int index) const {
|
||||
uint64_t SimpleWebServerRequest::get_file_length(const int index) const {
|
||||
ERR_FAIL_INDEX_V(index, _files.size(), 0);
|
||||
|
||||
return _files[index].data.size();
|
||||
const FileEntry &e = _files[index];
|
||||
|
||||
if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) {
|
||||
return e.data.size();
|
||||
}
|
||||
|
||||
Error err;
|
||||
FileAccess *fa = FileAccess::open(e.path, FileAccess::READ, &err);
|
||||
|
||||
ERR_FAIL_NULL_V(fa, 0);
|
||||
|
||||
if (err != OK) {
|
||||
memdelete(fa);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t len = fa->get_len();
|
||||
|
||||
memdelete(fa);
|
||||
|
||||
return len;
|
||||
}
|
||||
PoolByteArray SimpleWebServerRequest::get_file_data(const int index) const {
|
||||
ERR_FAIL_INDEX_V(index, _files.size(), PoolByteArray());
|
||||
|
||||
return _files[index].data;
|
||||
const FileEntry &e = _files[index];
|
||||
|
||||
if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) {
|
||||
return e.data;
|
||||
}
|
||||
|
||||
Error err;
|
||||
FileAccess *f = FileAccess::open(e.path, FileAccess::READ, &err);
|
||||
if (!f) {
|
||||
ERR_FAIL_V_MSG(PoolByteArray(), "Can't open file from path '" + String(e.path) + "'.");
|
||||
}
|
||||
|
||||
PoolByteArray data;
|
||||
data.resize(f->get_len());
|
||||
PoolByteArray::Write w = data.write();
|
||||
uint8_t *dptr = w.ptr();
|
||||
|
||||
f->get_buffer(dptr, data.size());
|
||||
memdelete(f);
|
||||
|
||||
return data;
|
||||
}
|
||||
String SimpleWebServerRequest::get_file_data_str(const int index) const {
|
||||
ERR_FAIL_INDEX_V(index, _files.size(), "");
|
||||
|
||||
PoolByteArray::Read r = _files[index].data.read();
|
||||
const FileEntry &e = _files[index];
|
||||
|
||||
String ret = reinterpret_cast<const char *>(r.ptr());
|
||||
if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) {
|
||||
PoolByteArray::Read r = _files[index].data.read();
|
||||
|
||||
r.release();
|
||||
String ret = reinterpret_cast<const char *>(r.ptr());
|
||||
|
||||
return ret;
|
||||
r.release();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Error err;
|
||||
String data = FileAccess::get_file_as_string(e.path, &err);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(err != OK, "", vformat("Error accessing file! Error: %d", err));
|
||||
|
||||
return data;
|
||||
}
|
||||
Error SimpleWebServerRequest::move_file(const int index, const String &p_dest_file) {
|
||||
ERR_FAIL_INDEX_V(index, _files.size(), ERR_INVALID_PARAMETER);
|
||||
|
||||
DirAccess *dir = DirAccess::create_for_path(p_dest_file.get_base_dir());
|
||||
|
||||
if (!dir) {
|
||||
return ERR_FILE_BAD_PATH;
|
||||
}
|
||||
|
||||
if (dir->file_exists(p_dest_file)) {
|
||||
return ERR_ALREADY_IN_USE;
|
||||
}
|
||||
|
||||
const FileEntry &e = _files[index];
|
||||
|
||||
if (e.type == FileEntry::FILE_ENTRY_TYPE_MEMORY) {
|
||||
memdelete(dir);
|
||||
|
||||
Error err;
|
||||
FileAccess *f = FileAccess::open(e.path, FileAccess::WRITE, &err);
|
||||
if (!f) {
|
||||
return ERR_FILE_BAD_PATH;
|
||||
}
|
||||
|
||||
PoolByteArray::Read r = e.data.read();
|
||||
const uint8_t *rptr = r.ptr();
|
||||
|
||||
f->store_buffer(rptr, e.data.size());
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
dir->rename(e.path, p_dest_file);
|
||||
memdelete(dir);
|
||||
|
||||
e.moved = true;
|
||||
e.path = p_dest_file;
|
||||
|
||||
return OK;
|
||||
}
|
||||
bool SimpleWebServerRequest::is_file_moved(const int index) const {
|
||||
ERR_FAIL_INDEX_V(index, _files.size(), true);
|
||||
|
||||
return _files[index].moved;
|
||||
}
|
||||
|
||||
String SimpleWebServerRequest::get_parameter(const String &key) const {
|
||||
@ -271,8 +367,9 @@ void SimpleWebServerRequest::set_host(const String &value) {
|
||||
_host = value;
|
||||
}
|
||||
|
||||
void SimpleWebServerRequest::add_file(const String &key, const String &file_name, const PoolByteArray &data) {
|
||||
void SimpleWebServerRequest::add_file_memory(const String &key, const String &file_name, const PoolByteArray &data) {
|
||||
FileEntry e;
|
||||
e.type = FileEntry::FILE_ENTRY_TYPE_MEMORY;
|
||||
e.key = key;
|
||||
e.file_name = file_name;
|
||||
e.data = data;
|
||||
@ -280,6 +377,16 @@ void SimpleWebServerRequest::add_file(const String &key, const String &file_name
|
||||
_files.push_back(e);
|
||||
}
|
||||
|
||||
void SimpleWebServerRequest::add_file_temp_file(const String &key, const String &file_name, const String &path) {
|
||||
FileEntry e;
|
||||
e.type = FileEntry::FILE_ENTRY_TYPE_TEMP_FILE;
|
||||
e.key = key;
|
||||
e.file_name = file_name;
|
||||
e.path = path;
|
||||
|
||||
_files.push_back(e);
|
||||
}
|
||||
|
||||
void SimpleWebServerRequest::add_cookie_data(const String &key, const String &value) {
|
||||
CookieData d;
|
||||
d.key = key;
|
||||
@ -303,6 +410,20 @@ SimpleWebServerRequest::SimpleWebServerRequest() {
|
||||
}
|
||||
|
||||
SimpleWebServerRequest::~SimpleWebServerRequest() {
|
||||
for (int i = 0; i < _files.size(); ++i) {
|
||||
const FileEntry &e = _files[i];
|
||||
|
||||
if (e.type == FileEntry::FILE_ENTRY_TYPE_TEMP_FILE) {
|
||||
if (!e.moved && !e.path.empty()) {
|
||||
DirAccess *d = DirAccess::create_for_path(e.path.get_base_dir());
|
||||
|
||||
if (d) {
|
||||
d->remove(e.path);
|
||||
memdelete(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleWebServerRequest::_bind_methods() {
|
||||
|
@ -58,13 +58,14 @@ public:
|
||||
|
||||
virtual HTTPServerEnums::HTTPMethod get_method() const;
|
||||
|
||||
virtual void parse_files();
|
||||
virtual int get_file_count() const;
|
||||
virtual String get_file_file_name(const int index) const;
|
||||
virtual String get_file_key(const int index) const;
|
||||
virtual int get_file_length(const int index) const;
|
||||
virtual uint64_t get_file_length(const int index) const;
|
||||
virtual PoolByteArray get_file_data(const int index) const;
|
||||
virtual String get_file_data_str(const int index) const;
|
||||
virtual Error move_file(const int index, const String &p_dest_file);
|
||||
virtual bool is_file_moved(const int index) const;
|
||||
|
||||
virtual String get_parameter(const String &key) const;
|
||||
virtual String get_post_parameter(const String &key) const;
|
||||
@ -93,7 +94,8 @@ public:
|
||||
void set_parser_path(const String &value);
|
||||
void set_host(const String &value);
|
||||
|
||||
void add_file(const String &key, const String &file_name, const PoolByteArray &data);
|
||||
void add_file_memory(const String &key, const String &file_name, const PoolByteArray &data);
|
||||
void add_file_temp_file(const String &key, const String &file_name, const String &path);
|
||||
|
||||
void add_cookie_data(const String &key, const String &value);
|
||||
|
||||
@ -121,9 +123,22 @@ protected:
|
||||
String _host;
|
||||
|
||||
struct FileEntry {
|
||||
enum FileEntryType {
|
||||
FILE_ENTRY_TYPE_MEMORY = 0,
|
||||
FILE_ENTRY_TYPE_TEMP_FILE = 0,
|
||||
};
|
||||
|
||||
mutable bool moved;
|
||||
|
||||
FileEntryType type;
|
||||
String file_name;
|
||||
PoolByteArray data;
|
||||
String key; //form name key
|
||||
mutable String path;
|
||||
|
||||
FileEntry() {
|
||||
moved = false;
|
||||
}
|
||||
};
|
||||
|
||||
Vector<FileEntry> _files;
|
||||
|
@ -129,6 +129,37 @@ void WebServerSimple::set_max_request_size(const int val) {
|
||||
_apply_max_request_size_type();
|
||||
}
|
||||
|
||||
WebServerSimple::FileUploadStoreType WebServerSimple::upload_get_file_store_type() {
|
||||
return _upload_file_store_type;
|
||||
}
|
||||
void WebServerSimple::upload_set_file_store_type(const FileUploadStoreType val) {
|
||||
_upload_file_store_type = val;
|
||||
property_list_changed_notify();
|
||||
}
|
||||
|
||||
String WebServerSimple::upload_get_temp_file_store_path() {
|
||||
return _upload_temp_file_store_path;
|
||||
}
|
||||
void WebServerSimple::upload_set_temp_file_store_path(const String &val) {
|
||||
_upload_temp_file_store_path = val;
|
||||
}
|
||||
|
||||
WebServerSimple::MaxRequestSizeTypes WebServerSimple::upload_get_request_max_file_size_type() {
|
||||
return _upload_request_max_file_size_type;
|
||||
}
|
||||
void WebServerSimple::upload_set_request_max_file_size_type(const MaxRequestSizeTypes val) {
|
||||
_upload_request_max_file_size_type = val;
|
||||
_apply_request_max_file_upload_size_type();
|
||||
}
|
||||
|
||||
int WebServerSimple::upload_get_request_max_file_size() {
|
||||
return _upload_request_max_file_size;
|
||||
}
|
||||
void WebServerSimple::upload_set_request_max_file_size(const int val) {
|
||||
_upload_request_max_file_size = val;
|
||||
_apply_request_max_file_upload_size_type();
|
||||
}
|
||||
|
||||
void WebServerSimple::add_mime_type(const String &file_extension, const String &mime_type) {
|
||||
_server->mimes[file_extension] = mime_type;
|
||||
}
|
||||
@ -145,6 +176,9 @@ void WebServerSimple::_start() {
|
||||
|
||||
WebServer::_start();
|
||||
|
||||
_server->upload_file_store_type = _upload_file_store_type;
|
||||
_server->upload_temp_file_store_path = _upload_temp_file_store_path.path_ensure_end_slash();
|
||||
|
||||
if (!OS::get_singleton()->can_use_threads()) {
|
||||
_server->_use_worker_threads = false;
|
||||
} else {
|
||||
@ -231,6 +265,11 @@ WebServerSimple::WebServerSimple() {
|
||||
_max_request_size_type = MAX_REQUEST_SIZE_TYPE_MEGA_BYTE;
|
||||
_max_request_size = 3;
|
||||
|
||||
_upload_file_store_type = FILE_UPLOAD_STORE_TYPE_MEMORY;
|
||||
_upload_temp_file_store_path = "user://http_temp_files/";
|
||||
_upload_request_max_file_size_type = MAX_REQUEST_SIZE_TYPE_MEGA_BYTE;
|
||||
_upload_request_max_file_size = 10;
|
||||
|
||||
_bind_port = 8080;
|
||||
_bind_host = "0.0.0.0";
|
||||
|
||||
@ -251,6 +290,7 @@ WebServerSimple::WebServerSimple() {
|
||||
_server->_web_server = this;
|
||||
|
||||
_apply_max_request_size_type();
|
||||
_apply_request_max_file_upload_size_type();
|
||||
}
|
||||
|
||||
WebServerSimple::~WebServerSimple() {
|
||||
@ -267,6 +307,22 @@ 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::_apply_request_max_file_upload_size_type() {
|
||||
_server->request_max_file_upload_size = (static_cast<uint64_t>(1) << (10 * static_cast<uint64_t>(_upload_request_max_file_size_type))) * static_cast<uint64_t>(_upload_request_max_file_size);
|
||||
}
|
||||
|
||||
void WebServerSimple::_validate_property(PropertyInfo &property) const {
|
||||
if (_upload_file_store_type == FILE_UPLOAD_STORE_TYPE_MEMORY) {
|
||||
if (property.name.begins_with("upload_")) {
|
||||
if (property.name == "upload_file_store_type") {
|
||||
return;
|
||||
}
|
||||
|
||||
property.usage = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebServerSimple::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_INTERNAL_PROCESS: {
|
||||
@ -331,6 +387,24 @@ void WebServerSimple::_bind_methods() {
|
||||
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");
|
||||
|
||||
ADD_GROUP("Upload", "upload_");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("upload_get_file_store_type"), &WebServerSimple::upload_get_file_store_type);
|
||||
ClassDB::bind_method(D_METHOD("upload_set_file_store_type", "val"), &WebServerSimple::upload_set_file_store_type);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "upload_file_store_type", PROPERTY_HINT_ENUM, "Memory,Temp Files"), "upload_set_file_store_type", "upload_get_file_store_type");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("upload_get_temp_file_store_path"), &WebServerSimple::upload_get_temp_file_store_path);
|
||||
ClassDB::bind_method(D_METHOD("upload_set_temp_file_store_path", "val"), &WebServerSimple::upload_set_temp_file_store_path);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "upload_temp_file_store_path"), "upload_set_temp_file_store_path", "upload_get_temp_file_store_path");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("upload_get_request_max_file_size_type"), &WebServerSimple::upload_get_request_max_file_size_type);
|
||||
ClassDB::bind_method(D_METHOD("upload_set_request_max_file_size_type", "val"), &WebServerSimple::upload_set_request_max_file_size_type);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "upload_request_max_file_size_type", PROPERTY_HINT_ENUM, "B,KB,MB,GB"), "upload_set_request_max_file_size_type", "upload_get_request_max_file_size_type");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("upload_get_request_max_file_size"), &WebServerSimple::upload_get_request_max_file_size);
|
||||
ClassDB::bind_method(D_METHOD("upload_set_request_max_file_size", "val"), &WebServerSimple::upload_set_request_max_file_size);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "upload_request_max_file_size"), "upload_set_request_max_file_size", "upload_get_request_max_file_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);
|
||||
|
||||
@ -340,6 +414,9 @@ void WebServerSimple::_bind_methods() {
|
||||
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);
|
||||
|
||||
BIND_ENUM_CONSTANT(FILE_UPLOAD_STORE_TYPE_MEMORY);
|
||||
BIND_ENUM_CONSTANT(FILE_UPLOAD_STORE_TYPE_TEMP_FILES);
|
||||
}
|
||||
|
||||
void WebServerSimple::_server_thread_poll(void *data) {
|
||||
|
@ -56,6 +56,12 @@ public:
|
||||
MAX_REQUEST_SIZE_TYPE_GIGA_BYTE = 3,
|
||||
};
|
||||
|
||||
enum FileUploadStoreType {
|
||||
FILE_UPLOAD_STORE_TYPE_MEMORY = 0,
|
||||
FILE_UPLOAD_STORE_TYPE_TEMP_FILES,
|
||||
//FILE_UPLOAD_STORE_TYPE_TEMP_FILES_SORTED_FOLDERS -> Use a hash as file name, and sort them into folders like /ab/cd/abcd... TODO
|
||||
};
|
||||
|
||||
int get_bind_port();
|
||||
void set_bind_port(const int val);
|
||||
|
||||
@ -86,15 +92,26 @@ public:
|
||||
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!)
|
||||
// This includes the entire request header,
|
||||
// including file uploads (only if they are stored in memory) because
|
||||
// then 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);
|
||||
|
||||
FileUploadStoreType upload_get_file_store_type();
|
||||
void upload_set_file_store_type(const FileUploadStoreType val);
|
||||
|
||||
String upload_get_temp_file_store_path();
|
||||
void upload_set_temp_file_store_path(const String &val);
|
||||
|
||||
// Total, not per file (less room for misconfigurations). Only relevant if FILE_UPLOAD_STORE_TYPE_TEMP_FILES.
|
||||
MaxRequestSizeTypes upload_get_request_max_file_size_type();
|
||||
void upload_set_request_max_file_size_type(const MaxRequestSizeTypes val);
|
||||
|
||||
int upload_get_request_max_file_size();
|
||||
void upload_set_request_max_file_size(const int val);
|
||||
|
||||
void add_mime_type(const String &file_extension, const String &mime_type);
|
||||
void remove_mime_type(const String &file_extension);
|
||||
|
||||
@ -110,7 +127,9 @@ public:
|
||||
|
||||
protected:
|
||||
void _apply_max_request_size_type();
|
||||
void _apply_request_max_file_upload_size_type();
|
||||
|
||||
void _validate_property(PropertyInfo &property) const;
|
||||
void _notification(int p_what);
|
||||
|
||||
static void _bind_methods();
|
||||
@ -120,7 +139,6 @@ protected:
|
||||
|
||||
bool _start_on_ready;
|
||||
|
||||
//TODO add binds to set path
|
||||
bool _use_ssl;
|
||||
String _ssl_key;
|
||||
String _ssl_cert;
|
||||
@ -134,6 +152,11 @@ protected:
|
||||
MaxRequestSizeTypes _max_request_size_type;
|
||||
int _max_request_size;
|
||||
|
||||
FileUploadStoreType _upload_file_store_type;
|
||||
String _upload_temp_file_store_path;
|
||||
MaxRequestSizeTypes _upload_request_max_file_size_type;
|
||||
int _upload_request_max_file_size;
|
||||
|
||||
Ref<HTTPServerSimple> _server;
|
||||
bool _server_quit;
|
||||
Mutex _server_lock;
|
||||
@ -144,5 +167,6 @@ protected:
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(WebServerSimple::MaxRequestSizeTypes);
|
||||
VARIANT_ENUM_CAST(WebServerSimple::FileUploadStoreType);
|
||||
|
||||
#endif
|
||||
|
@ -45,8 +45,6 @@ HTTPServerEnums::HTTPMethod WebNodeEditorWebServerRequest::get_method() const {
|
||||
return HTTPServerEnums::HTTP_METHOD_GET;
|
||||
}
|
||||
|
||||
void WebNodeEditorWebServerRequest::parse_files() {
|
||||
}
|
||||
int WebNodeEditorWebServerRequest::get_file_count() const {
|
||||
return 0;
|
||||
}
|
||||
@ -56,7 +54,7 @@ String WebNodeEditorWebServerRequest::get_file_file_name(const int index) const
|
||||
String WebNodeEditorWebServerRequest::get_file_key(const int index) const {
|
||||
return "";
|
||||
}
|
||||
int WebNodeEditorWebServerRequest::get_file_length(const int index) const {
|
||||
uint64_t WebNodeEditorWebServerRequest::get_file_length(const int index) const {
|
||||
return 0;
|
||||
}
|
||||
PoolByteArray WebNodeEditorWebServerRequest::get_file_data(const int index) const {
|
||||
|
@ -61,11 +61,10 @@ public:
|
||||
|
||||
HTTPServerEnums::HTTPMethod get_method() const;
|
||||
|
||||
void parse_files();
|
||||
int get_file_count() const;
|
||||
String get_file_file_name(const int index) const;
|
||||
String get_file_key(const int index) const;
|
||||
int get_file_length(const int index) const;
|
||||
uint64_t get_file_length(const int index) const;
|
||||
PoolByteArray get_file_data(const int index) const;
|
||||
String get_file_data_str(const int index) const;
|
||||
|
||||
|
@ -246,8 +246,6 @@ HTTPServerEnums::HTTPMethod WebServerRequest::get_method() const {
|
||||
return HTTPServerEnums::HTTP_METHOD_GET;
|
||||
}
|
||||
|
||||
void WebServerRequest::parse_files() {
|
||||
}
|
||||
int WebServerRequest::get_file_count() const {
|
||||
return 0;
|
||||
}
|
||||
@ -257,7 +255,7 @@ String WebServerRequest::get_file_file_name(const int index) const {
|
||||
String WebServerRequest::get_file_key(const int index) const {
|
||||
return String();
|
||||
}
|
||||
int WebServerRequest::get_file_length(const int index) const {
|
||||
uint64_t WebServerRequest::get_file_length(const int index) const {
|
||||
return 0;
|
||||
}
|
||||
PoolByteArray WebServerRequest::get_file_data(const int index) const {
|
||||
@ -266,6 +264,12 @@ PoolByteArray WebServerRequest::get_file_data(const int index) const {
|
||||
String WebServerRequest::get_file_data_str(const int index) const {
|
||||
return String();
|
||||
}
|
||||
Error WebServerRequest::move_file(const int index, const String &p_dest_file) {
|
||||
return ERR_PRINTER_ON_FIRE;
|
||||
}
|
||||
bool WebServerRequest::is_file_moved(const int index) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
String WebServerRequest::get_parameter(const String &key) const {
|
||||
return String();
|
||||
@ -646,13 +650,14 @@ void WebServerRequest::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_method"), &WebServerRequest::get_method);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("parse_files"), &WebServerRequest::parse_files);
|
||||
ClassDB::bind_method(D_METHOD("get_file_count"), &WebServerRequest::get_file_count);
|
||||
ClassDB::bind_method(D_METHOD("get_file_file_name", "index"), &WebServerRequest::get_file_file_name);
|
||||
ClassDB::bind_method(D_METHOD("get_file_key", "index"), &WebServerRequest::get_file_key);
|
||||
ClassDB::bind_method(D_METHOD("get_file_length", "index"), &WebServerRequest::get_file_length);
|
||||
ClassDB::bind_method(D_METHOD("get_file_data", "index"), &WebServerRequest::get_file_data);
|
||||
ClassDB::bind_method(D_METHOD("get_file_data_str", "index"), &WebServerRequest::get_file_data_str);
|
||||
ClassDB::bind_method(D_METHOD("move_file", "index", "dest_file"), &WebServerRequest::move_file);
|
||||
ClassDB::bind_method(D_METHOD("is_file_moved", "index"), &WebServerRequest::is_file_moved);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_parameter", "key"), &WebServerRequest::get_parameter);
|
||||
ClassDB::bind_method(D_METHOD("get_post_parameter", "key"), &WebServerRequest::get_post_parameter);
|
||||
|
@ -110,13 +110,14 @@ public:
|
||||
|
||||
virtual HTTPServerEnums::HTTPMethod get_method() const;
|
||||
|
||||
virtual void parse_files();
|
||||
virtual int get_file_count() const;
|
||||
virtual String get_file_file_name(const int index) const;
|
||||
virtual String get_file_key(const int index) const;
|
||||
virtual int get_file_length(const int index) const;
|
||||
virtual uint64_t get_file_length(const int index) const;
|
||||
virtual PoolByteArray get_file_data(const int index) const;
|
||||
virtual String get_file_data_str(const int index) const;
|
||||
virtual Error move_file(const int index, const String &p_dest_file);
|
||||
virtual bool is_file_moved(const int index) const;
|
||||
|
||||
virtual String get_parameter(const String &key) const;
|
||||
virtual String get_post_parameter(const String &key) const;
|
||||
|
@ -44,9 +44,6 @@ HTTPServerEnums::HTTPMethod WebServerRequestScriptable::get_method() const {
|
||||
return static_cast<HTTPServerEnums::HTTPMethod>(m);
|
||||
}
|
||||
|
||||
void WebServerRequestScriptable::parse_files() {
|
||||
call("_parse_files");
|
||||
}
|
||||
int WebServerRequestScriptable::get_file_count() const {
|
||||
return const_cast<WebServerRequestScriptable *>(this)->call("_get_file_count");
|
||||
}
|
||||
@ -56,7 +53,7 @@ String WebServerRequestScriptable::get_file_file_name(const int index) const {
|
||||
String WebServerRequestScriptable::get_file_key(const int index) const {
|
||||
return const_cast<WebServerRequestScriptable *>(this)->call("_get_file_key", index);
|
||||
}
|
||||
int WebServerRequestScriptable::get_file_length(const int index) const {
|
||||
uint64_t WebServerRequestScriptable::get_file_length(const int index) const {
|
||||
return const_cast<WebServerRequestScriptable *>(this)->call("_get_file_length", index);
|
||||
}
|
||||
PoolByteArray WebServerRequestScriptable::get_file_data(const int index) const {
|
||||
@ -65,6 +62,12 @@ PoolByteArray WebServerRequestScriptable::get_file_data(const int index) const {
|
||||
String WebServerRequestScriptable::get_file_data_str(const int index) const {
|
||||
return const_cast<WebServerRequestScriptable *>(this)->call("_get_file_data_str", index);
|
||||
}
|
||||
Error WebServerRequestScriptable::move_file(const int index, const String &p_dest_file) {
|
||||
return (Error)(int)call("_move_file", index, p_dest_file);
|
||||
}
|
||||
bool WebServerRequestScriptable::is_file_moved(const int index) const {
|
||||
return const_cast<WebServerRequestScriptable *>(this)->call("_is_file_moved", index);
|
||||
}
|
||||
|
||||
String WebServerRequestScriptable::get_parameter(const String &key) const {
|
||||
return const_cast<WebServerRequestScriptable *>(this)->call("_get_parameter", key);
|
||||
@ -155,8 +158,6 @@ HTTPServerEnums::HTTPMethod WebServerRequestScriptable::_get_method() const {
|
||||
return HTTPServerEnums::HTTP_METHOD_GET;
|
||||
}
|
||||
|
||||
void WebServerRequestScriptable::_parse_files() {
|
||||
}
|
||||
int WebServerRequestScriptable::_get_file_count() const {
|
||||
return 0;
|
||||
}
|
||||
@ -175,6 +176,12 @@ PoolByteArray WebServerRequestScriptable::_get_file_data(const int index) const
|
||||
String WebServerRequestScriptable::_get_file_data_str(const int index) const {
|
||||
return String();
|
||||
}
|
||||
Error WebServerRequestScriptable::_move_file(const int index, const String &p_dest_file) {
|
||||
return ERR_PRINTER_ON_FIRE;
|
||||
}
|
||||
bool WebServerRequestScriptable::_is_file_moved(const int index) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
String WebServerRequestScriptable::_get_parameter(const String &key) const {
|
||||
return String();
|
||||
@ -295,13 +302,14 @@ void WebServerRequestScriptable::_bind_methods() {
|
||||
|
||||
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_method"));
|
||||
|
||||
BIND_VMETHOD(MethodInfo("_parse_files"));
|
||||
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_file_count"));
|
||||
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_file_file_name", PropertyInfo(Variant::INT, "index")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_file_key", PropertyInfo(Variant::INT, "index")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_file_length", PropertyInfo(Variant::INT, "index")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::POOL_BYTE_ARRAY, "_get_file_data", PropertyInfo(Variant::INT, "index")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_file_data_str", PropertyInfo(Variant::INT, "index")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::INT, "_move_file", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::STRING, "dest_file")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_file_moved", PropertyInfo(Variant::INT, "index")));
|
||||
|
||||
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_parameter", PropertyInfo(Variant::STRING, "key")));
|
||||
BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_post_parameter", PropertyInfo(Variant::STRING, "key")));
|
||||
@ -336,13 +344,14 @@ void WebServerRequestScriptable::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_get_method"), &WebServerRequestScriptable::_get_method);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_parse_files"), &WebServerRequestScriptable::_parse_files);
|
||||
ClassDB::bind_method(D_METHOD("_get_file_count"), &WebServerRequestScriptable::_get_file_count);
|
||||
ClassDB::bind_method(D_METHOD("_get_file_file_name", "index"), &WebServerRequestScriptable::_get_file_file_name);
|
||||
ClassDB::bind_method(D_METHOD("_get_file_key", "index"), &WebServerRequestScriptable::_get_file_key);
|
||||
ClassDB::bind_method(D_METHOD("_get_file_length", "index"), &WebServerRequestScriptable::_get_file_length);
|
||||
ClassDB::bind_method(D_METHOD("_get_file_data", "index"), &WebServerRequestScriptable::_get_file_data);
|
||||
ClassDB::bind_method(D_METHOD("_get_file_data_str", "index"), &WebServerRequestScriptable::_get_file_data_str);
|
||||
ClassDB::bind_method(D_METHOD("_move_file", "index", "dest_file"), &WebServerRequestScriptable::_move_file);
|
||||
ClassDB::bind_method(D_METHOD("_is_file_moved", "index"), &WebServerRequestScriptable::_is_file_moved);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_get_parameter", "key"), &WebServerRequestScriptable::_get_parameter);
|
||||
ClassDB::bind_method(D_METHOD("_get_post_parameter", "key"), &WebServerRequestScriptable::_get_post_parameter);
|
||||
|
@ -57,13 +57,14 @@ public:
|
||||
|
||||
virtual HTTPServerEnums::HTTPMethod get_method() const;
|
||||
|
||||
virtual void parse_files();
|
||||
virtual int get_file_count() const;
|
||||
virtual String get_file_file_name(const int index) const;
|
||||
virtual String get_file_key(const int index) const;
|
||||
virtual int get_file_length(const int index) const;
|
||||
virtual uint64_t get_file_length(const int index) const;
|
||||
virtual PoolByteArray get_file_data(const int index) const;
|
||||
virtual String get_file_data_str(const int index) const;
|
||||
virtual Error move_file(const int index, const String &p_dest_file);
|
||||
virtual bool is_file_moved(const int index) const;
|
||||
|
||||
virtual String get_parameter(const String &key) const;
|
||||
virtual String get_post_parameter(const String &key) const;
|
||||
@ -98,13 +99,14 @@ public:
|
||||
|
||||
virtual HTTPServerEnums::HTTPMethod _get_method() const;
|
||||
|
||||
virtual void _parse_files();
|
||||
virtual int _get_file_count() const;
|
||||
virtual String _get_file_file_name(const int index) const;
|
||||
virtual String _get_file_key(const int index) const;
|
||||
virtual int _get_file_length(const int index) const;
|
||||
virtual PoolByteArray _get_file_data(const int index) const;
|
||||
virtual String _get_file_data_str(const int index) const;
|
||||
virtual Error _move_file(const int index, const String &p_dest_file);
|
||||
virtual bool _is_file_moved(const int index) const;
|
||||
|
||||
virtual String _get_parameter(const String &key) const;
|
||||
virtual String _get_post_parameter(const String &key) const;
|
||||
|
Loading…
Reference in New Issue
Block a user