TrinityCore
Loading...
Searching...
No Matches
HttpService.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITYCORE_HTTP_SERVICE_H
19#define TRINITYCORE_HTTP_SERVICE_H
20
21#include "AsioHacksFwd.h"
22#include "Concepts.h"
23#include "Define.h"
24#include "EnumFlag.h"
25#include "HttpCommon.h"
26#include "HttpSessionState.h"
27#include "Optional.h"
28#include "SocketMgr.h"
29#include <boost/uuid/uuid.hpp>
30#include <functional>
31#include <map>
32#include <set>
33#include <shared_mutex>
34
35namespace Trinity::Net::Http
36{
37class AbstractSocket;
38
40{
41 None = 0x0,
44};
45
47
49{
50 std::function<RequestHandlerResult(std::shared_ptr<AbstractSocket> session, RequestContext& context)> Func;
52};
53
55{
56public:
57 explicit DispatcherService(std::string_view loggerSuffix) : _logger("server.http.dispatcher.")
58 {
59 _logger.append(loggerSuffix);
60 }
61
62 RequestHandlerResult HandleRequest(std::shared_ptr<AbstractSocket> session, RequestContext& context);
63
64 static RequestHandlerResult HandleBadRequest(std::shared_ptr<AbstractSocket> session, RequestContext& context);
65 static RequestHandlerResult HandleUnauthorized(std::shared_ptr<AbstractSocket> session, RequestContext& context);
66 static RequestHandlerResult HandlePathNotFound(std::shared_ptr<AbstractSocket> session, RequestContext& context);
67
68protected:
69 void RegisterHandler(boost::beast::http::verb method, std::string_view path,
70 std::function<RequestHandlerResult(std::shared_ptr<AbstractSocket> session, RequestContext& context)> handler,
71 RequestHandlerFlag flags = RequestHandlerFlag::None);
72
73private:
74 using HttpMethodHandlerMap = std::map<std::string, RequestHandler, std::less<>>;
75
78
79 std::string _logger;
80};
81
83{
84public:
85 explicit SessionService(std::string_view loggerSuffix) : _logger("server.http.session.")
86 {
87 _logger.append(loggerSuffix);
88 }
89
90 void Start(Asio::IoContext& ioContext);
91 void Stop();
92
93 std::shared_ptr<SessionState> FindAndRefreshSessionState(std::string_view id, boost::asio::ip::address const& address);
94 void MarkSessionInactive(boost::uuids::uuid const& id);
95
96protected:
97 void InitAndStoreSessionState(std::shared_ptr<SessionState> state, boost::asio::ip::address const& address);
98
99 void KillInactiveSessions();
100
101private:
102 std::shared_mutex _sessionsMutex;
103 std::map<boost::uuids::uuid, std::shared_ptr<SessionState>> _sessions;
104
106 std::set<boost::uuids::uuid> _inactiveSessions;
107 std::unique_ptr<Asio::DeadlineTimer> _inactiveSessionsKillTimer;
108
109 std::string _logger;
110};
111
112template<typename Callable, typename SessionImpl>
114
115template<typename SessionImpl>
116class HttpService;
117
118template<typename SessionImpl>
119class HttpNetworkThread final : public NetworkThread<SessionImpl, HttpNetworkThread<SessionImpl>>
120{
121public:
122 void SocketRemoved(std::shared_ptr<SessionImpl> const& session) override
123 {
124 if (Optional<boost::uuids::uuid> id = session->GetSessionId())
126 }
127
128private:
129 friend class HttpService<SessionImpl>;
131};
132
133template<typename SessionImpl>
140
141template<typename SessionImpl>
142class HttpService : public SocketMgr<HttpServiceTraits<SessionImpl>>, public DispatcherService, public SessionService
143{
145
147
148public:
149 HttpService(std::string_view loggerSuffix) : DispatcherService(loggerSuffix), SessionService(loggerSuffix), _ioContext(nullptr), _logger("server.http.")
150 {
151 _logger.append(loggerSuffix);
152 }
153
154 bool StartNetwork(Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, int32 threadCount = 1) override
155 {
156 if (!BaseSocketMgr::StartNetwork(ioContext, bindIp, port, threadCount))
157 return false;
158
159 SessionService::Start(ioContext);
160 return true;
161 }
162
163 void StopNetwork() override
164 {
167 }
168
169 // http handling
171
172 template<HttpRequestHandler<SessionImpl> Callable>
173 void RegisterHandler(boost::beast::http::verb method, std::string_view path, Callable handler, RequestHandlerFlag flags = RequestHandlerFlag::None)
174 {
175 this->DispatcherService::RegisterHandler(method, path, [handler = std::move(handler)](std::shared_ptr<AbstractSocket> session, RequestContext& context) -> RequestHandlerResult
176 {
177 return handler(std::static_pointer_cast<SessionImpl>(std::move(session)), context);
178 }, flags);
179 }
180
181 // session tracking
182 virtual std::shared_ptr<SessionState> CreateNewSessionState(boost::asio::ip::address const& address)
183 {
184 std::shared_ptr<SessionState> state = std::make_shared<SessionState>();
185 InitAndStoreSessionState(state, address);
186 return state;
187 }
188
189protected:
190 std::unique_ptr<HttpNetworkThread<SessionImpl>[]> CreateThreads() const override
191 {
192 std::unique_ptr<HttpNetworkThread<SessionImpl>[]> threads = std::make_unique<HttpNetworkThread<SessionImpl>[]>(this->GetNetworkThreadCount());
193 for (int32 i = 0; i < this->GetNetworkThreadCount(); ++i)
194 threads[i]._service = const_cast<HttpService*>(this);
195 return threads;
196 }
197
199 std::string _logger;
200};
201}
202
203#endif // TRINITYCORE_HTTP_SERVICE_H
#define TC_NETWORK_API
Definition Define.h:117
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
uint16 flags
#define DEFINE_ENUM_FLAG(enumType)
Definition EnumFlag.h:26
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
DispatcherService(std::string_view loggerSuffix)
Definition HttpService.h:57
void RegisterHandler(boost::beast::http::verb method, std::string_view path, std::function< RequestHandlerResult(std::shared_ptr< AbstractSocket > session, RequestContext &context)> handler, RequestHandlerFlag flags=RequestHandlerFlag::None)
std::map< std::string, RequestHandler, std::less<> > HttpMethodHandlerMap
Definition HttpService.h:74
void SocketRemoved(std::shared_ptr< SessionImpl > const &session) override
virtual std::shared_ptr< SessionState > CreateNewSessionState(boost::asio::ip::address const &address)
bool StartNetwork(Asio::IoContext &ioContext, std::string const &bindIp, uint16 port, int32 threadCount=1) override
HttpService(std::string_view loggerSuffix)
std::unique_ptr< HttpNetworkThread< SessionImpl >[]> CreateThreads() const override
void RegisterHandler(boost::beast::http::verb method, std::string_view path, Callable handler, RequestHandlerFlag flags=RequestHandlerFlag::None)
std::map< boost::uuids::uuid, std::shared_ptr< SessionState > > _sessions
std::unique_ptr< Asio::DeadlineTimer > _inactiveSessionsKillTimer
std::set< boost::uuids::uuid > _inactiveSessions
SessionService(std::string_view loggerSuffix)
Definition HttpService.h:85
void Start(Asio::IoContext &ioContext)
void InitAndStoreSessionState(std::shared_ptr< SessionState > state, boost::asio::ip::address const &address)
void MarkSessionInactive(boost::uuids::uuid const &id)
virtual bool StartNetwork(Asio::IoContext &ioContext, std::string const &bindIp, uint16 port, int threadCount)
Definition SocketMgr.h:48
std::function< RequestHandlerResult(std::shared_ptr< AbstractSocket > session, RequestContext &context)> Func
Definition HttpService.h:50
EnumFlag< RequestHandlerFlag > Flags
Definition HttpService.h:51