From ca08fe3de284e4b5e2de9e4b534f5fa51f354b61 Mon Sep 17 00:00:00 2001 From: Relintai Date: Thu, 21 Jul 2022 14:05:55 +0200 Subject: [PATCH] Reworked the Web Server's Cookie API. --- modules/web/http/web_server_cookie.cpp | 138 ++++++++++++++++-- modules/web/http/web_server_cookie.h | 38 ++++- modules/web/http/web_server_request.cpp | 36 ++++- modules/web/http/web_server_request.h | 9 +- .../http_server_simple/http_server_simple.cpp | 53 +++++++ .../simple_web_server_request.cpp | 6 - .../simple_web_server_request.h | 2 - 7 files changed, 244 insertions(+), 38 deletions(-) diff --git a/modules/web/http/web_server_cookie.cpp b/modules/web/http/web_server_cookie.cpp index 524d7fc7d..46deff10a 100644 --- a/modules/web/http/web_server_cookie.cpp +++ b/modules/web/http/web_server_cookie.cpp @@ -2,55 +2,145 @@ #include "web_server_cookie.h" String WebServerCookie::get_domain() { - return domain; + return _domain; } void WebServerCookie::set_domain(const String &val) { - domain = val; + _domain = val; } String WebServerCookie::get_path() { - return path; + return _path; } void WebServerCookie::set_path(const String &val) { - path = val; + _path = val; } String WebServerCookie::get_key() { - return key; + return _key; } void WebServerCookie::set_key(const String &val) { - key = val; + _key = val; } String WebServerCookie::get_value() { - return value; + return _value; } void WebServerCookie::set_value(const String &val) { - value = val; + _value = val; } bool WebServerCookie::get_http_only() { - return http_only; + return _http_only; } void WebServerCookie::set_http_only(const bool val) { - http_only = val; + _http_only = val; } bool WebServerCookie::get_secure() { - return secure; + return _secure; } void WebServerCookie::set_secure(const bool val) { - secure = val; + _secure = val; +} + +bool WebServerCookie::get_delete() { + return _delete; +} +void WebServerCookie::set_delete(const bool val) { + _delete = val; +} + +bool WebServerCookie::get_should_expire() { + return _should_expire; +} +void WebServerCookie::set_should_expire(const bool val) { + _should_expire = val; +} + +uint64_t WebServerCookie::get_expiry_date_unix_time() { + return OS::get_singleton()->get_unix_time_from_datetime(_expiry_date); +} +void WebServerCookie::set_expiry_date_unix_time(const uint64_t unix_time) { + _expiry_date = OS::get_singleton()->get_datetime_from_unix_time(unix_time); + + _should_expire = true; +} + +OS::DateTime WebServerCookie::get_expiry_date() { + return _expiry_date; +} +void WebServerCookie::set_expiry_date(OS::DateTime date_time) { + _expiry_date = date_time; + + _should_expire = true; +} +void WebServerCookie::set_expiry_date(OS::Date date, OS::Time time) { + _expiry_date.date = date; + _expiry_date.time = time; + + _should_expire = true; +} + +Dictionary WebServerCookie::get_expiry_date_dict() { + Dictionary date_time; + date_time["year"] = _expiry_date.date.year; + date_time["month"] = _expiry_date.date.month; + date_time["day"] = _expiry_date.date.day; + date_time["weekday"] = _expiry_date.date.weekday; + date_time["dst"] = _expiry_date.date.dst; + date_time["hour"] = _expiry_date.time.hour; + date_time["minute"] = _expiry_date.time.min; + date_time["second"] = _expiry_date.time.sec; + + return date_time; +} + +void WebServerCookie::set_expiry_date_dict(const Dictionary &date, const Dictionary &time) { + int month = date["month"]; + int weekday = date["weekday"]; + + _expiry_date.date.year = date["year"]; + _expiry_date.date.month = static_cast(month); + _expiry_date.date.day = date["day"]; + _expiry_date.date.weekday = static_cast(weekday); + _expiry_date.date.dst = date["dst"]; + _expiry_date.time.hour = time["hour"]; + _expiry_date.time.min = time["minute"]; + _expiry_date.time.sec = time["second"]; + + _should_expire = true; +} + +void WebServerCookie::set_expiry_date_dt_dict(const Dictionary &date_time) { + int month = date_time["month"]; + int weekday = date_time["weekday"]; + + _expiry_date.date.year = date_time["year"]; + _expiry_date.date.month = static_cast(month); + _expiry_date.date.day = date_time["day"]; + _expiry_date.date.weekday = static_cast(weekday); + _expiry_date.date.dst = date_time["dst"]; + _expiry_date.time.hour = date_time["hour"]; + _expiry_date.time.min = date_time["minute"]; + _expiry_date.time.sec = date_time["second"]; + + _should_expire = true; } void WebServerCookie::set_data(const String &p_key, const String &p_value) { - key = p_key; - value = p_value; + _key = p_key; + _value = p_value; +} + +String WebServerCookie::get_response_header_string() { + return ""; } WebServerCookie::WebServerCookie() { - http_only = true; - secure = false; + _should_expire = false; + _http_only = true; + _secure = false; + _delete = false; } WebServerCookie::~WebServerCookie() { @@ -81,5 +171,21 @@ void WebServerCookie::_bind_methods() { ClassDB::bind_method(D_METHOD("set_secure", "val"), &WebServerCookie::set_secure); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "secure"), "set_secure", "get_secure"); + ClassDB::bind_method(D_METHOD("get_delete"), &WebServerCookie::get_delete); + ClassDB::bind_method(D_METHOD("set_delete", "val"), &WebServerCookie::set_delete); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "delete"), "set_delete", "get_delete"); + + ClassDB::bind_method(D_METHOD("get_should_expire"), &WebServerCookie::get_should_expire); + ClassDB::bind_method(D_METHOD("set_should_expire", "val"), &WebServerCookie::set_should_expire); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "should_expire"), "set_should_expire", "get_should_expire"); + + ClassDB::bind_method(D_METHOD("get_expiry_date_unix_time"), &WebServerCookie::get_expiry_date_unix_time); + ClassDB::bind_method(D_METHOD("set_expiry_date_unix_time", "unix_time"), &WebServerCookie::set_expiry_date_unix_time); + + ClassDB::bind_method(D_METHOD("get_expiry_date"), &WebServerCookie::get_expiry_date_dict); + ClassDB::bind_method(D_METHOD("set_expiry_date", "date", "time"), &WebServerCookie::set_expiry_date_dict); + ClassDB::bind_method(D_METHOD("set_expiry_date_dt", "date_time"), &WebServerCookie::set_expiry_date_dt_dict); + ClassDB::bind_method(D_METHOD("set_data", "key", "value"), &WebServerCookie::set_data); + ClassDB::bind_method(D_METHOD("get_response_header_string"), &WebServerCookie::get_response_header_string); } diff --git a/modules/web/http/web_server_cookie.h b/modules/web/http/web_server_cookie.h index ee12e2890..41bae91f1 100644 --- a/modules/web/http/web_server_cookie.h +++ b/modules/web/http/web_server_cookie.h @@ -1,6 +1,7 @@ #ifndef WEB_SERVER_COOKIE_H #define WEB_SERVER_COOKIE_H +#include "core/os/os.h" #include "core/ustring.h" #include "core/reference.h" @@ -27,21 +28,42 @@ public: bool get_secure(); void set_secure(const bool val); + bool get_delete(); + void set_delete(const bool val); + + bool get_should_expire(); + void set_should_expire(const bool val); + + uint64_t get_expiry_date_unix_time(); + void set_expiry_date_unix_time(const uint64_t unix_time); + + OS::DateTime get_expiry_date(); + void set_expiry_date(OS::DateTime date_time); + void set_expiry_date(OS::Date date, OS::Time time); + + Dictionary get_expiry_date_dict(); + void set_expiry_date_dict(const Dictionary &date, const Dictionary &time); + void set_expiry_date_dt_dict(const Dictionary &date_time); + void set_data(const String &p_key, const String &p_value); + String get_response_header_string(); + WebServerCookie(); ~WebServerCookie(); - //todo date - String domain; - String path; - String key; - String value; - bool http_only; - bool secure; - protected: static void _bind_methods(); + + bool _should_expire; + OS::DateTime _expiry_date; + String _domain; + String _path; + String _key; + String _value; + bool _http_only; + bool _secure; + bool _delete; }; #endif diff --git a/modules/web/http/web_server_request.cpp b/modules/web/http/web_server_request.cpp index ee412b2e2..7844fe8e1 100644 --- a/modules/web/http/web_server_request.cpp +++ b/modules/web/http/web_server_request.cpp @@ -153,10 +153,34 @@ String WebServerRequest::get_cookie(const String &key) { return ""; } -void WebServerRequest::add_cookie(const Ref &cookie) { +void WebServerRequest::response_add_cookie(const Ref &cookie) { + _cookies.push_back(cookie); } -void WebServerRequest::remove_cookie(const String &key) { +int WebServerRequest::response_get_cookie_count() { + return _cookies.size(); +} + +Ref WebServerRequest::response_get_cookie(const int index) { + ERR_FAIL_INDEX_V(index, _cookies.size(), Ref()); + + return _cookies[index]; +} + +void WebServerRequest::response_remove_cookie(const int index) { + ERR_FAIL_INDEX(index, _cookies.size()); + + _cookies.remove(index); +} + +void WebServerRequest::response_remove_cookie_simple(const String &key) { + Ref cookie; + cookie.instance(); + + cookie->set_data(key, ""); + cookie->set_delete(true); + + _cookies.push_back(cookie); } HTTPServerEnums::HTTPMethod WebServerRequest::get_method() const { @@ -500,8 +524,12 @@ void WebServerRequest::_bind_methods() { ClassDB::bind_method(D_METHOD("validate_csrf_token"), &WebServerRequest::validate_csrf_token); ClassDB::bind_method(D_METHOD("get_cookie", "key"), &WebServerRequest::get_cookie); - ClassDB::bind_method(D_METHOD("add_cookie", "cookie"), &WebServerRequest::add_cookie); - ClassDB::bind_method(D_METHOD("remove_cookie", "key"), &WebServerRequest::remove_cookie); + + ClassDB::bind_method(D_METHOD("response_add_cookie", "cookie"), &WebServerRequest::response_add_cookie); + ClassDB::bind_method(D_METHOD("response_get_cookie_count"), &WebServerRequest::response_get_cookie_count); + ClassDB::bind_method(D_METHOD("response_get_cookie", "index"), &WebServerRequest::response_get_cookie); + ClassDB::bind_method(D_METHOD("response_remove_cookie", "index"), &WebServerRequest::response_remove_cookie); + ClassDB::bind_method(D_METHOD("response_remove_cookie_simple", "key"), &WebServerRequest::response_remove_cookie_simple); ClassDB::bind_method(D_METHOD("get_method"), &WebServerRequest::get_method); diff --git a/modules/web/http/web_server_request.h b/modules/web/http/web_server_request.h index 0f795b8ca..aea424409 100644 --- a/modules/web/http/web_server_request.h +++ b/modules/web/http/web_server_request.h @@ -60,8 +60,12 @@ public: bool validate_csrf_token(); virtual String get_cookie(const String &key); - virtual void add_cookie(const Ref &cookie); - virtual void remove_cookie(const String &key); + + void response_add_cookie(const Ref &cookie); + int response_get_cookie_count(); + Ref response_get_cookie(const int index); + void response_remove_cookie(const int index); + void response_remove_cookie_simple(const String &key); virtual HTTPServerEnums::HTTPMethod get_method() const; @@ -141,6 +145,7 @@ protected: String _full_path; Vector _path_stack; int _path_stack_pointer; + Vector> _cookies; }; #endif diff --git a/modules/web/http_server_simple/http_server_simple.cpp b/modules/web/http_server_simple/http_server_simple.cpp index eeebbd739..7cacecb50 100644 --- a/modules/web/http_server_simple/http_server_simple.cpp +++ b/modules/web/http_server_simple/http_server_simple.cpp @@ -30,6 +30,7 @@ #include "http_server_simple.h" +#include "../http/web_server_cookie.h" #include "http_parser.h" #include "simple_web_server_request.h" #include "web_server_simple.h" @@ -218,6 +219,19 @@ void HTTPServerSimple::send_redirect(Ref request, const String String s = "HTTP/1.1 " + HTTPServerEnums::get_status_code_header_string(status_code) + "\r\n"; s += "Location: " + location + "\r\n"; s += "Connection: Close\r\n"; + + for (int i = 0; i < request->response_get_cookie_count(); ++i) { + Ref cookie = request->response_get_cookie(i); + + ERR_CONTINUE(!cookie.is_valid()); + + String cookie_str = cookie->get_response_header_string(); + + if (cookie_str != "") { + s += cookie_str; + } + } + s += "\r\n"; CharString cs = s.utf8(); peer->put_data((const uint8_t *)cs.get_data(), cs.size() - 1); @@ -229,6 +243,19 @@ void HTTPServerSimple::send(Ref request) { s += "Content-Length: " + itos(body.size()) + "\r\n"; s += "Content-type: text/html\r\n"; s += "Connection: Close\r\n"; + + for (int i = 0; i < request->response_get_cookie_count(); ++i) { + Ref cookie = request->response_get_cookie(i); + + ERR_CONTINUE(!cookie.is_valid()); + + String cookie_str = cookie->get_response_header_string(); + + if (cookie_str != "") { + s += cookie_str; + } + } + s += "\r\n"; s += body; @@ -239,6 +266,19 @@ void HTTPServerSimple::send_file(Ref request, const String &p_ if (!FileAccess::exists(p_file_path)) { String s = "HTTP/1.1 404 Not Found\r\n"; s += "Connection: Close\r\n"; + + for (int i = 0; i < request->response_get_cookie_count(); ++i) { + Ref cookie = request->response_get_cookie(i); + + ERR_CONTINUE(!cookie.is_valid()); + + String cookie_str = cookie->get_response_header_string(); + + if (cookie_str != "") { + s += cookie_str; + } + } + s += "\r\n"; CharString cs = s.utf8(); peer->put_data((const uint8_t *)cs.get_data(), cs.size() - 1); @@ -259,6 +299,19 @@ void HTTPServerSimple::send_file(Ref request, const String &p_ String s = "HTTP/1.1 200 OK\r\n"; s += "Connection: Close\r\n"; s += "Content-Type: " + ctype + "\r\n"; + + for (int i = 0; i < request->response_get_cookie_count(); ++i) { + Ref cookie = request->response_get_cookie(i); + + ERR_CONTINUE(!cookie.is_valid()); + + String cookie_str = cookie->get_response_header_string(); + + if (cookie_str != "") { + s += cookie_str; + } + } + s += "Access-Control-Allow-Origin: *\r\n"; s += "Cross-Origin-Opener-Policy: same-origin\r\n"; s += "Cross-Origin-Embedder-Policy: require-corp\r\n"; 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 9344c8c94..5a72f9bf3 100644 --- a/modules/web/http_server_simple/simple_web_server_request.cpp +++ b/modules/web/http_server_simple/simple_web_server_request.cpp @@ -16,12 +16,6 @@ String SimpleWebServerRequest::get_cookie(const String &key) { return ""; } -void SimpleWebServerRequest::add_cookie(const Ref &cookie) { -} - -void SimpleWebServerRequest::remove_cookie(const String &key) { -} - HTTPServerEnums::HTTPMethod SimpleWebServerRequest::get_method() const { return HTTPServerEnums::HTTP_METHOD_GET; } 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 20856f6b7..174e33a38 100644 --- a/modules/web/http_server_simple/simple_web_server_request.h +++ b/modules/web/http_server_simple/simple_web_server_request.h @@ -22,8 +22,6 @@ class SimpleWebServerRequest : public WebServerRequest { public: virtual String get_cookie(const String &key); - virtual void add_cookie(const Ref &cookie); - virtual void remove_cookie(const String &key); virtual HTTPServerEnums::HTTPMethod get_method() const;