From 9f92959b946e8fd632c56ae87d803b8d78b5375f Mon Sep 17 00:00:00 2001 From: Dimiden Date: Sat, 16 Nov 2024 19:55:18 +0900 Subject: [PATCH] Fixed issue where the stream name was not applied to _path after parsing the URL (#1739) --- src/projects/base/ovlibrary/type.h | 14 +-- src/projects/base/ovlibrary/url.cpp | 137 ++++++++++++++++++++++------ src/projects/base/ovlibrary/url.h | 26 +++--- 3 files changed, 131 insertions(+), 46 deletions(-) diff --git a/src/projects/base/ovlibrary/type.h b/src/projects/base/ovlibrary/type.h index 4eaa7bf25..80fa6d779 100644 --- a/src/projects/base/ovlibrary/type.h +++ b/src/projects/base/ovlibrary/type.h @@ -22,10 +22,12 @@ namespace ov using UnderylingType = std::underlying_type_t; } // namespace ov -#define OV_DEFINE_SETTER(type, setter, member, extra_qualifier) \ - void setter(const type &value) extra_qualifier \ - { \ - member = value; \ +#define OV_DEFINE_SETTER(type, setter, member, extra_qualifier, pre_process, post_process) \ + void setter(const type &value) extra_qualifier \ + { \ + pre_process; \ + member = value; \ + post_process; \ } #define OV_DEFINE_GETTER(type, getter, member, extra_qualifier) \ @@ -40,6 +42,6 @@ namespace ov return member; \ } -#define OV_DEFINE_SETTER_CONST_GETTER(type, setter, getter, member, extra_qualifier) \ - OV_DEFINE_SETTER(type, setter, member, extra_qualifier) \ +#define OV_DEFINE_SETTER_CONST_GETTER(type, setter, getter, member, extra_qualifier, pre_process, post_process) \ + OV_DEFINE_SETTER(type, setter, member, extra_qualifier, pre_process, post_process) \ OV_DEFINE_CONST_GETTER(type, getter, member, extra_qualifier) diff --git a/src/projects/base/ovlibrary/url.cpp b/src/projects/base/ovlibrary/url.cpp index 38eafac6d..6540b319d 100644 --- a/src/projects/base/ovlibrary/url.cpp +++ b/src/projects/base/ovlibrary/url.cpp @@ -144,30 +144,49 @@ namespace ov } } - std::shared_ptr Url::Parse(const ov::String &url) + bool Url::ParseFromSource() { - auto object = std::make_shared(); - std::string url_string = url.CStr(); - - object->_source = url; - - auto matches = g_url_parse_regex.Matches(url); + auto matches = g_url_parse_regex.Matches(_source); if (matches.GetError() != nullptr) { - return nullptr; + _scheme = ""; + _id = ""; + _password = ""; + _host = ""; + _port = 0; + _path = ""; + _query_string = ""; + _has_query_string = false; + _query_parsed = false; + + _app = ""; + _stream = ""; + _file = ""; + + return false; } auto group_list = matches.GetNamedGroupList(); - object->_scheme = group_list["scheme"].GetValue(); - object->_id = group_list["id"].GetValue(); - object->_password = group_list["password"].GetValue(); - object->_host = group_list["host"].GetValue(); - object->_port = ov::Converter::ToUInt32(group_list["port"].GetValue()); - object->SetPath(group_list["path"].GetValue()); - object->_query_string = group_list["qs"].GetValue(); - object->_has_query_string = (object->_query_string.IsEmpty() == false); + _scheme = group_list["scheme"].GetValue(); + _id = group_list["id"].GetValue(); + _password = group_list["password"].GetValue(); + _host = group_list["host"].GetValue(); + _port = ov::Converter::ToUInt32(group_list["port"].GetValue()); + SetPath(group_list["path"].GetValue()); + _query_string = group_list["qs"].GetValue(); + _has_query_string = (_query_string.IsEmpty() == false); + _query_parsed = false; + + return true; + } + + std::shared_ptr Url::Parse(const ov::String &url) + { + auto object = std::make_shared(); + + object->SetSource(url); return object; } @@ -249,6 +268,39 @@ namespace ov return true; } + void Url::UpdateUrl(bool is_source_updated) + { + if (is_source_updated) + { + // Get component values from the _source + ParseFromSource(); + } + else + { + _source = ToUrlString(); + + _path = ""; + + if (_app.IsEmpty() == false) + { + _path.Append("/"); + _path.Append(_app); + } + + if (_stream.IsEmpty() == false) + { + _path.Append("/"); + _path.Append(_stream); + } + + if (_file.IsEmpty() == false) + { + _path.Append("/"); + _path.Append(_file); + } + } + } + void Url::ParseQueryIfNeeded() const { if ((_has_query_string == false) || _query_parsed) @@ -375,21 +427,48 @@ namespace ov ov::String Url::ToUrlString(bool include_query_string) const { - return ov::String::FormatString( - "%s://%s%s%s%s%s", - _scheme.CStr(), - _host.CStr(), (_port > 0) ? ov::String::FormatString(":%d", _port).CStr() : "", - _path.CStr(), ((include_query_string == false) || _query_string.IsEmpty()) ? "" : "?", include_query_string ? _query_string.CStr() : ""); + ov::String url; + + url.AppendFormat("%s://", _scheme.CStr()); + + if (_id.IsEmpty() == false) + { + url.Append(_id.CStr()); + + if (_password.IsEmpty()) + { + url.Append('@'); + } + } + + if (_password.IsEmpty() == false) + { + url.AppendFormat(":%s@", _password.CStr()); + } + + url.Append(_host.CStr()); + if (_port > 0) + { + url.AppendFormat(":%d", _port); + } + + url.Append(_path); + + if (include_query_string && (_query_string.IsEmpty() == false)) + { + url.Append("?"); + url.Append(_query_string); + } + + return url; } ov::String Url::ToString() const { - return ov::String::FormatString( - "%s://%s%s%s%s%s%s (app: %s, stream: %s, file: %s)", - _scheme.CStr(), - _id.IsEmpty() ? "" : ov::String::FormatString("%s:%s@", _id.CStr(), _password.CStr()).CStr(), - _host.CStr(), (_port > 0) ? ov::String::FormatString(":%d", _port).CStr() : "", - _path.CStr(), _query_string.IsEmpty() ? "" : "?", _query_string.CStr(), - _app.CStr(), _stream.CStr(), _file.CStr()); + auto url = ToUrlString(); + + url.AppendFormat(" (app: %s, stream: %s, file: %s)", _app.CStr(), _stream.CStr(), _file.CStr()); + + return url; } -} // namespace ov \ No newline at end of file +} // namespace ov diff --git a/src/projects/base/ovlibrary/url.h b/src/projects/base/ovlibrary/url.h index c773a09c9..49af79df5 100644 --- a/src/projects/base/ovlibrary/url.h +++ b/src/projects/base/ovlibrary/url.h @@ -23,17 +23,17 @@ namespace ov // ://[:][/][?] static std::shared_ptr Parse(const ov::String &url); - OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetSource, Source, _source, ) - OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetScheme, Scheme, _scheme, ) - OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetHost, Host, _host, ) - OV_DEFINE_SETTER_CONST_GETTER(uint32_t, SetPort, Port, _port, ) + OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetSource, Source, _source, , , UpdateUrl(true)) + OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetScheme, Scheme, _scheme, , , UpdateUrl(false)) + OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetHost, Host, _host, , , UpdateUrl(false)) + OV_DEFINE_SETTER_CONST_GETTER(uint32_t, SetPort, Port, _port, , , UpdateUrl(false)) OV_DEFINE_CONST_GETTER(ov::String, Path, _path, ) void SetPath(const ov::String &path); - OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetApp, App, _app, ) - OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetStream, Stream, _stream, ) - OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetFile, File, _file, ) - OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetId, Id, _id, ) - OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetPassword, Password, _password, ) + OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetApp, App, _app, , , UpdateUrl(false)) + OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetStream, Stream, _stream, , , UpdateUrl(false)) + OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetFile, File, _file, , , UpdateUrl(false)) + OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetId, Id, _id, , , UpdateUrl(false)) + OV_DEFINE_SETTER_CONST_GETTER(ov::String, SetPassword, Password, _password, , , UpdateUrl(false)) bool HasQueryString() const; const ov::String &Query() const; @@ -50,11 +50,15 @@ namespace ov Url &operator=(const Url &other) noexcept; - Url() =default; + Url() = default; Url(const Url &other); std::shared_ptr Clone() const; + protected: + bool ParseFromSource(); + void UpdateUrl(bool is_source_updated); + private: void ParseQueryIfNeeded() const; @@ -66,8 +70,8 @@ namespace ov ov::String _host; uint32_t _port = 0; ov::String _path; - bool _has_query_string = false; ov::String _query_string; + bool _has_query_string = false; // To reduce the cost of parsing the query map, parsing the query only when Query() or QueryMap() is called mutable bool _query_parsed = false; mutable std::mutex _query_map_mutex;