TrinityCore
BaseHttpSocket.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_BASE_HTTP_SOCKET_H
19#define TRINITYCORE_BASE_HTTP_SOCKET_H
20
22#include "DatabaseEnvFwd.h"
23#include "HttpCommon.h"
24#include "HttpSessionState.h"
25#include "Optional.h"
26#include "QueryCallback.h"
27#include "Socket.h"
28#include <boost/asio/buffers_iterator.hpp>
29#include <boost/beast/http/parser.hpp>
30#include <boost/beast/http/string_body.hpp>
31#include <boost/uuid/uuid_io.hpp>
32
33namespace Trinity::Net::Http
34{
35using RequestParser = boost::beast::http::request_parser<RequestBody>;
36
38{
39public:
40 AbstractSocket() = default;
41 AbstractSocket(AbstractSocket const& other) = default;
42 AbstractSocket(AbstractSocket&& other) = default;
43 AbstractSocket& operator=(AbstractSocket const& other) = default;
45 virtual ~AbstractSocket() = default;
46
47 static bool ParseRequest(MessageBuffer& packet, RequestParser& parser);
48
49 static std::string SerializeRequest(Request const& request);
50 static MessageBuffer SerializeResponse(Request const& request, Response& response);
51
52 virtual void SendResponse(RequestContext& context) = 0;
53
54 virtual void QueueQuery(QueryCallback&& queryCallback) = 0;
55
56 virtual std::string GetClientInfo() const = 0;
57
59};
60
61template<typename Derived, typename Stream>
62class BaseSocket : public ::Socket<Derived, Stream>, public AbstractSocket
63{
65
66public:
67 template<typename... Args>
68 explicit BaseSocket(boost::asio::ip::tcp::socket&& socket, Args&&... args)
69 : Base(std::move(socket), std::forward<Args>(args)...) { }
70
71 BaseSocket(BaseSocket const& other) = delete;
72 BaseSocket(BaseSocket&& other) = delete;
73 BaseSocket& operator=(BaseSocket const& other) = delete;
74 BaseSocket& operator=(BaseSocket&& other) = delete;
75
76 ~BaseSocket() = default;
77
78 void ReadHandler() override
79 {
80 if (!this->IsOpen())
81 return;
82
83 MessageBuffer& packet = this->GetReadBuffer();
84 while (packet.GetActiveSize() > 0)
85 {
86 if (!ParseRequest(packet, *_httpParser))
87 {
88 // Couldn't receive the whole data this time.
89 break;
90 }
91
92 if (!HandleMessage(_httpParser->get()))
93 {
94 this->CloseSocket();
95 break;
96 }
97
98 this->ResetHttpParser();
99 }
100
101 this->AsyncRead();
102 }
103
104 bool HandleMessage(Request& request)
105 {
106 RequestContext context { .request = std::move(request) };
107
108 if (!_state)
109 _state = this->ObtainSessionState(context);
110
111 RequestHandlerResult status = this->RequestHandler(context);
112
113 if (status != RequestHandlerResult::Async)
114 this->SendResponse(context);
115
116 return status != RequestHandlerResult::Error;
117 }
118
120
121 void SendResponse(RequestContext& context) override
122 {
123 MessageBuffer buffer = SerializeResponse(context.request, context.response);
124
125 TC_LOG_DEBUG("server.http", "{} Request {} {} done, status {}", this->GetClientInfo(), ToStdStringView(context.request.method_string()),
126 ToStdStringView(context.request.target()), context.response.result_int());
127 if (sLog->ShouldLog("server.http", LOG_LEVEL_TRACE))
128 {
129 sLog->OutMessage("server.http", LOG_LEVEL_TRACE, "{} Request: {}", this->GetClientInfo(),
130 CanLogRequestContent(context) ? SerializeRequest(context.request) : "<REDACTED>");
131 sLog->OutMessage("server.http", LOG_LEVEL_TRACE, "{} Response: {}", this->GetClientInfo(),
132 CanLogResponseContent(context) ? std::string_view(reinterpret_cast<char const*>(buffer.GetBasePointer()), buffer.GetActiveSize()) : "<REDACTED>");
133 }
134
135 this->QueuePacket(std::move(buffer));
136
137 if (!context.response.keep_alive())
138 this->DelayedCloseSocket();
139 }
140
141 void QueueQuery(QueryCallback&& queryCallback) override
142 {
143 this->_queryProcessor.AddCallback(std::move(queryCallback));
144 }
145
146 bool Update() override
147 {
148 if (!this->Base::Update())
149 return false;
150
152 return true;
153 }
154
155 std::string GetClientInfo() const override
156 {
157 std::string info;
158 info.reserve(500);
159 auto itr = StringFormatTo(std::back_inserter(info), "[{}:{}", this->GetRemoteIpAddress().to_string(), this->GetRemotePort());
160 if (_state)
161 itr = StringFormatTo(itr, ", Session Id: {}", boost::uuids::to_string(_state->Id));
162
163 StringFormatTo(itr, "]");
164 return info;
165 }
166
168 {
169 if (this->_state)
170 return this->_state->Id;
171
172 return {};
173 }
174
175protected:
177 {
178 this->_httpParser.reset();
179 this->_httpParser.emplace();
180 this->_httpParser->eager(true);
181 }
182
183 virtual std::shared_ptr<SessionState> ObtainSessionState(RequestContext& context) const = 0;
184
187 std::shared_ptr<SessionState> _state;
188};
189}
190
191#endif // TRINITYCORE_BASE_HTTP_SOCKET_H
#define TC_SHARED_API
Definition: Define.h:117
@ LOG_LEVEL_TRACE
Definition: LogCommon.h:27
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define sLog
Definition: Log.h:130
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
size_type GetActiveSize() const
Definition: MessageBuffer.h:67
uint8 * GetBasePointer()
Definition: MessageBuffer.h:57
Definition: Socket.h:63
MessageBuffer & GetReadBuffer()
Definition: Socket.h:169
virtual bool Update()
Definition: Socket.h:87
void DelayedCloseSocket()
Marks the socket for closing after write buffer becomes empty.
Definition: Socket.h:167
boost::asio::ip::address GetRemoteIpAddress() const
Definition: Socket.h:103
void QueuePacket(MessageBuffer &&buffer)
Definition: Socket.h:141
bool IsOpen() const
Definition: Socket.h:150
uint16 GetRemotePort() const
Definition: Socket.h:108
AbstractSocket(AbstractSocket &&other)=default
virtual std::string GetClientInfo() const =0
virtual void SendResponse(RequestContext &context)=0
static std::string SerializeRequest(Request const &request)
AbstractSocket & operator=(AbstractSocket &&other)=default
AbstractSocket(AbstractSocket const &other)=default
static MessageBuffer SerializeResponse(Request const &request, Response &response)
static bool ParseRequest(MessageBuffer &packet, RequestParser &parser)
virtual void QueueQuery(QueryCallback &&queryCallback)=0
virtual Optional< boost::uuids::uuid > GetSessionId() const =0
AbstractSocket & operator=(AbstractSocket const &other)=default
void SendResponse(RequestContext &context) override
BaseSocket & operator=(BaseSocket const &other)=delete
virtual std::shared_ptr< SessionState > ObtainSessionState(RequestContext &context) const =0
bool HandleMessage(Request &request)
BaseSocket(BaseSocket &&other)=delete
BaseSocket & operator=(BaseSocket &&other)=delete
BaseSocket(boost::asio::ip::tcp::socket &&socket, Args &&... args)
Optional< RequestParser > _httpParser
Optional< boost::uuids::uuid > GetSessionId() const final
QueryCallbackProcessor _queryProcessor
std::string GetClientInfo() const override
virtual RequestHandlerResult RequestHandler(RequestContext &context)=0
BaseSocket(BaseSocket const &other)=delete
std::shared_ptr< SessionState > _state
void QueueQuery(QueryCallback &&queryCallback) override
boost::beast::http::response< ResponseBody > Response
Definition: HttpCommon.h:31
boost::beast::http::request_parser< RequestBody > RequestParser
std::string_view ToStdStringView(boost::beast::string_view bsw)
Definition: HttpCommon.h:43
TC_SHARED_API bool CanLogResponseContent(RequestContext const &context)
Definition: HttpService.cpp:33
boost::beast::http::request< RequestBody > Request
Definition: HttpCommon.h:30
TC_SHARED_API bool CanLogRequestContent(RequestContext const &context)
Definition: HttpService.cpp:28
OutputIt StringFormatTo(OutputIt out, FormatString< Args... > fmt, Args &&... args)
Definition: StringFormat.h:51
STL namespace.