UniSet 2.41.2
JHttpServer.h
1/*
2 * Copyright (c) 2025 Pavel Vainerman.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation, version 2.1.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Lesser Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16// --------------------------------------------------------------------------
17#ifndef JHttpServer_H_
18#define JHttpServer_H_
19// --------------------------------------------------------------------------
20#include <memory>
21#include <atomic>
22#include <condition_variable>
23#include <future>
24#include <mutex>
25#include <queue>
26#include <Poco/Net/HTTPServer.h>
27#include <Poco/Net/HTTPRequestHandler.h>
28#include <Poco/Net/HTTPServerRequest.h>
29#include <Poco/Net/HTTPServerResponse.h>
30#include <Poco/Net/HTTPRequestHandlerFactory.h>
31#include "DebugStream.h"
32// --------------------------------------------------------------------------
33namespace uniset
34{
35 // ----------------------------------------------------------------------
36 class JHttpServer final:
37 public std::enable_shared_from_this<JHttpServer>,
38 public Poco::Net::HTTPRequestHandlerFactory
39 {
40 public:
41 JHttpServer( size_t httpMaxThreads, size_t httpMaxRequestQueue );
42 ~JHttpServer() final;
43
44 bool isRunning();
45 void start( const std::string& host, int port );
46 void stop();
47 void softStop(std::chrono::milliseconds timeout);
48
49 void setProcessTimeout(std::chrono::milliseconds d) noexcept
50 {
51 processTimeout_ = d;
52 }
53 std::chrono::milliseconds processTimeout() const noexcept
54 {
55 return processTimeout_;
56 }
57
58 inline std::shared_ptr<DebugStream> log() noexcept
59 {
60 return mylog;
61 }
62
63 class Factory : public HTTPRequestHandlerFactory
64 {
65 public:
66 Factory( JHttpServer* s ): srv(s) {}
67
68 Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& req) override
69 {
70 return srv->createRequestHandler(req);
71 }
72 private:
73 JHttpServer* srv;
74 };
75
77 {
78 std::string method;
79 std::string uri;
80 std::string version;
81 std::vector<std::pair<std::string, std::string>> headers;
82 std::string body;
83 };
84
86 {
87 int status = 200;
88 std::string reason = "OK";
89 std::vector<std::pair<std::string, std::string>> headers;
90 std::string body;
91 };
92
94 {
96 bool finished = false;
97 };
98
99 using HandlerFn = std::function<ResponseSnapshot(const RequestSnapshot&)>;
100
101 void httpLoop( HandlerFn& fn, size_t count, std::chrono::milliseconds& timeout );
102
103 void setMaxQueueSize(size_t n) noexcept
104 {
105 queue_.setMaxSize(n);
106 }
107
108 class Handler;
110 {
111 public:
112 struct Job
113 {
114 RequestSnapshot req;
115 std::promise<ResponseSnapshot> prom;
116 };
117
118 bool push(Job&& j)
119 {
120 {
121 std::lock_guard<std::mutex> lk(m_);
122
123 if (maxSize_ > 0 && q_.size() >= maxSize_) return false;
124
125 q_.emplace(std::move(j));
126 }
127 cv_.notify_one();
128 return true;
129 }
130
131 // returns false when shutting down and queue is empty
132 bool pop(Job& out, std::chrono::milliseconds timeout)
133 {
134 std::unique_lock<std::mutex> lk(m_);
135
136 bool ret = cv_.wait_for(lk, timeout, [&]
137 {
138 return stop_ || !q_.empty();
139 });
140
141 if( !ret )
142 return false;
143
144 if(stop_ && q_.empty())
145 return false;
146
147 out = std::move(q_.front());
148 q_.pop();
149 return true;
150 }
151
152
153 bool empty() const
154 {
155 std::lock_guard<std::mutex> lk(m_);
156 return q_.empty();
157 }
158
159 void setMaxSize(size_t n) noexcept
160 {
161 maxSize_ = n;
162 }
163
164 void shutdown()
165 {
166 {
167 std::lock_guard<std::mutex> lk(m_);
168 stop_ = true;
169 }
170 cv_.notify_all();
171 }
172
173 private:
174 mutable std::mutex m_;
175 std::condition_variable cv_;
176 std::queue<Job> q_;
177 bool stop_ = false;
178 size_t maxSize_ = 0;
179 };
180
181 protected:
182 friend class Factory;
183 Poco::Net::HTTPRequestHandler* createRequestHandler( const Poco::Net::HTTPServerRequest& ) override;
184
185 private:
186 Poco::Net::SocketAddress sa;
187 std::shared_ptr<Poco::Net::HTTPServer> http;
188 std::shared_ptr<DebugStream> mylog;
189 std::atomic_bool started;
190
191 // default timeout: 10s
192 std::chrono::milliseconds processTimeout_{std::chrono::seconds(10)};
193
194 // lifecycle
195 std::atomic_bool started_{false};
196 std::atomic_bool workerRunning_{false};
197 std::atomic_bool softStopping_{false};
198 std::atomic_bool workerBusy_{false};
199 std::condition_variable cvStop_;
200 std::mutex cvStopMutex_;
201
202 size_t httpMaxThreads = { 3 };
203 size_t httpMaxRequestQueue = { 50 };
204
205 // request funnel
206 RequestQueue queue_;
207
208 };
209 // ----------------------------------------------------------------------
210} // end of namespace uniset
211// --------------------------------------------------------------------------
212#endif
Определения JHttpServer.h:64
Определения JHttpServer.h:110
Определения Calibration.h:27
Определения JHttpServer.h:113
Определения JHttpServer.h:77
Определения JHttpServer.h:94
Определения JHttpServer.h:86