SNode.C
Loading...
Searching...
No Matches
EventSource.h
Go to the documentation of this file.
1/*
2 * SNode.C - A Slim Toolkit for Network Communication
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2020, 2021, 2022, 2023, 2024, 2025
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21 * MIT License
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in
31 * all copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 * THE SOFTWARE.
40 */
41
42#ifndef WEB_HTTP_LEGACY_UN_EVENTSOURCE_H
43#define WEB_HTTP_LEGACY_UN_EVENTSOURCE_H
44
45#include "web/http/client/tools/EventSource.h"
46#include "web/http/legacy/un/Client.h"
47
48#include <memory>
49
50#ifndef DOXYGEN_SHOULD_SKIP_THIS
51
52#endif // DOXYGEN_SHOULD_SKIP_THIS
53
54namespace web::http::legacy::un {
55
56 class EventSource : public web::http::client::tools::EventSourceT<web::http::legacy::un::Client> {
57 private:
58 using Super = web::http::client::tools::EventSourceT<web::http::legacy::un::Client>;
59
60 public:
61 inline ~EventSource() override;
62
63 friend inline std::shared_ptr<web::http::client::tools::EventSource> EventSource(const std::string& scheme, //
64 const SocketAddress& socketAddress,
65 const std::string& path);
66 };
67
69 }
70
71 inline std::shared_ptr<web::http::client::tools::EventSource>
72 EventSource(const std::string& scheme, const net::un::SocketAddress& socketAddress, const std::string& path) {
73 std::shared_ptr<class EventSource> eventSource = std::make_shared<class EventSource>();
74 eventSource->init(scheme, socketAddress, path);
75
76 return eventSource;
77 }
78
79 inline std::shared_ptr<web::http::client::tools::EventSource> EventSource(const std::string& socketPath, const std::string& path) {
80 return EventSource("http", net::un::SocketAddress(socketPath), path);
81 }
82
83 inline std::shared_ptr<web::http::client::tools::EventSource> EventSource(const std::string& url) {
84 std::shared_ptr<web::http::client::tools::EventSource> eventSource;
85
86 // One-liner regex: scheme + token (no '/' inside token) + optional /path + optional ?query + optional #fragment
87 static const std::regex re(R"(^(?:un://)([^/?#]+)(/[^?#]*)?(\?[^#]*)?(?:#.*)?$)", std::regex::ECMAScript | std::regex::icase);
88
89 auto pct_decode = [](std::string_view s) -> std::string {
90 std::string out;
91 out.reserve(s.size());
92 for (size_t i = 0; i < s.size(); ++i) {
93 if (s[i] == '%' && i + 2 < s.size()) {
94 auto hex = [](char c) -> int {
95 if (c >= '0' && c <= '9') {
96 return c - '0';
97 }
98 c |= 0x20;
99 if (c >= 'a' && c <= 'f') {
100 return 10 + (c - 'a');
101 }
102 return -1;
103 };
104 const int h = hex(s[i + 1]);
105 const int l = hex(s[i + 2]);
106 if (h >= 0 && l >= 0) {
107 out.push_back(static_cast<char>((h << 4) | l));
108 i += 2;
109 continue;
110 }
111 }
112 out.push_back(s[i]);
113 }
114 return out;
115 };
116
117 std::smatch match;
118 if (std::regex_match(url, match, re)) {
119 // Factory for Unix Domain Sockets (un://)
120 // URL form: un://<pct-encoded-sockpath>[/http-path][?query][#fragment]
121 // [1] sockToken -> percent-encoded abs path ("/...") or abstract name ("@name")
122 // [2] path -> optional HTTP path (defaults to "/")
123 // [3] query -> optional
124
125 const std::string sockToken = match[1].str();
126 std::string socketPath = pct_decode(sockToken); // may start with '/' or '@'
127
128 if ((!socketPath.empty() && (socketPath.front() == '/' || socketPath.front() == '@'))) {
129 const std::string scheme = "un"; // fixed
130 const std::string httpPath = match[2].matched ? match[2].str() : "/";
131 const std::string query = match[3].matched ? match[3].str() : "";
132
133 eventSource = EventSource(scheme, net::un::SocketAddress(socketPath), httpPath + query);
134 } else {
135 LOG(ERROR) << "UNIX socket must decode to absolute ('/..') or abstract ('@name'): " << sockToken;
136 }
137 } else {
138 LOG(ERROR) << "EventSource unix-domain url not accepted: " << url;
139 }
140
141 return eventSource;
142 }
143
144} // namespace web::http::legacy::un
145
146#endif // WEB_HTTP_LEGACY_UN_EVENTSOURCE_H
SocketAddress(const std::string &sunPath)
void init(const std::string &scheme, const SocketAddress &socketAddress, const std::string &path)
web::http::client::tools::EventSourceT< web::http::legacy::un::Client > Super
Definition EventSource.h:58
web::http::client::Client< net::un::stream::legacy::SocketClient > Client
Definition Client.h:54
std::shared_ptr< web::http::client::tools::EventSource > EventSource(const std::string &scheme, const net::un::SocketAddress &socketAddress, const std::string &path)
Definition EventSource.h:72