TrinityCore
BaseHttpSocket.cpp
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#include "BaseHttpSocket.h"
19#include <boost/asio/buffers_iterator.hpp>
20#include <boost/beast/http/serializer.hpp>
21#include <boost/uuid/uuid_io.hpp>
22
24{
25using RequestSerializer = boost::beast::http::request_serializer<ResponseBody>;
26using ResponseSerializer = boost::beast::http::response_serializer<ResponseBody>;
27
29{
30 if (!parser.is_done())
31 {
32 // need more data in the payload
33 boost::system::error_code ec = {};
34 std::size_t readDataSize = parser.put(boost::asio::const_buffer(packet.GetReadPointer(), packet.GetActiveSize()), ec);
35 packet.ReadCompleted(readDataSize);
36 }
37
38 return parser.is_done();
39}
40
42{
43 if (!parser.is_done())
44 {
45 // need more data in the payload
46 boost::system::error_code ec = {};
47 std::size_t readDataSize = parser.put(boost::asio::const_buffer(packet.GetReadPointer(), packet.GetActiveSize()), ec);
48 packet.ReadCompleted(readDataSize);
49 }
50
51 return parser.is_done();
52}
53
55{
56 RequestSerializer serializer(request);
57
58 MessageBuffer buffer;
59 while (!serializer.is_done())
60 {
61 serializer.limit(buffer.GetRemainingSpace());
62
63 size_t totalBytes = 0;
64 boost::system::error_code ec = {};
65 serializer.next(ec, [&]<typename ConstBufferSequence>(boost::system::error_code& currentError, ConstBufferSequence const& buffers)
66 {
67 size_t totalBytesInBuffers = boost::asio::buffer_size(buffers);
68 if (totalBytesInBuffers > buffer.GetRemainingSpace())
69 {
70 currentError = boost::beast::http::error::need_more;
71 return;
72 }
73
74 auto begin = boost::asio::buffers_begin(buffers);
75 auto end = boost::asio::buffers_end(buffers);
76
77 std::copy(begin, end, buffer.GetWritePointer());
78 buffer.WriteCompleted(totalBytesInBuffers);
79 totalBytes += totalBytesInBuffers;
80 });
81
82 serializer.consume(totalBytes);
83
84 if (ec == boost::beast::http::error::need_more)
85 buffer.Resize(buffer.GetBufferSize() + 4096);
86 }
87
88 return buffer;
89}
90
92{
93 ResponseSerializer serializer(response);
94 bool (*serializerIsDone)(ResponseSerializer&);
95 if (request.method() != boost::beast::http::verb::head)
96 {
97 serializerIsDone = [](ResponseSerializer& s) { return s.is_done(); };
98 }
99 else
100 {
101 serializerIsDone = [](ResponseSerializer& s) { return s.is_header_done(); };
102 serializer.split(true);
103 }
104
105 MessageBuffer buffer;
106 while (!serializerIsDone(serializer))
107 {
108 serializer.limit(buffer.GetRemainingSpace());
109
110 size_t totalBytes = 0;
111 boost::system::error_code ec = {};
112 serializer.next(ec, [&]<typename ConstBufferSequence>(boost::system::error_code& currentError, ConstBufferSequence const& buffers)
113 {
114 size_t totalBytesInBuffers = boost::asio::buffer_size(buffers);
115 if (totalBytesInBuffers > buffer.GetRemainingSpace())
116 {
117 currentError = boost::beast::http::error::need_more;
118 return;
119 }
120
121 auto begin = boost::asio::buffers_begin(buffers);
122 auto end = boost::asio::buffers_end(buffers);
123
124 std::copy(begin, end, buffer.GetWritePointer());
125 buffer.WriteCompleted(totalBytesInBuffers);
126 totalBytes += totalBytesInBuffers;
127 });
128
129 serializer.consume(totalBytes);
130
131 if (ec == boost::beast::http::error::need_more)
132 buffer.Resize(buffer.GetBufferSize() + 4096);
133 }
134
135 return buffer;
136}
137
139{
140 if (Logger const* logger = sLog->GetEnabledLogger("server.http", LOG_LEVEL_DEBUG))
141 {
142 std::string clientInfo = GetClientInfo();
143 sLog->OutMessageTo(logger, "server.http", LOG_LEVEL_DEBUG, "{} Request {} {} done, status {}", clientInfo,
144 ToStdStringView(context.request.method_string()), ToStdStringView(context.request.target()), context.response.result_int());
145 if (sLog->ShouldLog("server.http", LOG_LEVEL_TRACE))
146 {
147 if (CanLogRequestContent(context))
148 {
149 MessageBuffer request = SerializeRequest(context.request);
150 sLog->OutMessageTo(logger, "server.http", LOG_LEVEL_TRACE, "{} Request: {}", clientInfo,
151 std::string_view(reinterpret_cast<char const*>(request.GetBasePointer()), request.GetActiveSize()));
152 }
153 else
154 sLog->OutMessageTo(logger, "server.http", LOG_LEVEL_TRACE, "{} Request: <REDACTED>", clientInfo);
155
156 if (CanLogResponseContent(context))
157 sLog->OutMessageTo(logger, "server.http", LOG_LEVEL_TRACE, "{} Response: {}", clientInfo,
158 std::string_view(reinterpret_cast<char const*>(buffer.GetBasePointer()), buffer.GetActiveSize()));
159 else
160 sLog->OutMessageTo(logger, "server.http", LOG_LEVEL_TRACE, "{} Response: <REDACTED>", clientInfo);
161 }
162 }
163}
164
165std::string AbstractSocket::GetClientInfo(boost::asio::ip::address const& address, uint16 port, SessionState const* state)
166{
167 std::string info = StringFormat("[{}:{}", address.to_string(), port);
168 if (state)
169 {
170 info.append(", Session Id: ");
171 info.append(boost::uuids::to_string(state->Id));
172 }
173
174 info += ']';
175 return info;
176}
177}
uint16_t uint16
Definition: Define.h:149
@ LOG_LEVEL_DEBUG
Definition: LogCommon.h:28
@ LOG_LEVEL_TRACE
Definition: LogCommon.h:27
#define sLog
Definition: Log.h:154
Definition: Logger.h:30
void Resize(size_type bytes)
Definition: MessageBuffer.h:51
size_type GetRemainingSpace() const
Definition: MessageBuffer.h:68
void ReadCompleted(size_type bytes)
Definition: MessageBuffer.h:62
void WriteCompleted(size_type bytes)
Definition: MessageBuffer.h:64
uint8 * GetReadPointer()
Definition: MessageBuffer.h:58
size_type GetActiveSize() const
Definition: MessageBuffer.h:66
uint8 * GetWritePointer()
Definition: MessageBuffer.h:60
size_type GetBufferSize() const
Definition: MessageBuffer.h:70
uint8 * GetBasePointer()
Definition: MessageBuffer.h:56
virtual std::string GetClientInfo() const =0
static MessageBuffer SerializeRequest(Request const &request)
static bool ParseRequest(MessageBuffer &packet, RequestParser &parser)
void LogRequestAndResponse(RequestContext const &context, MessageBuffer &buffer) const
static MessageBuffer SerializeResponse(Request const &request, Response const &response)
static bool ParseResponse(MessageBuffer &packet, ResponseParser &parser)
boost::beast::http::request_serializer< ResponseBody > RequestSerializer
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
boost::beast::http::response_serializer< ResponseBody > ResponseSerializer
boost::beast::http::response_parser< RequestBody > ResponseParser
TC_NETWORK_API bool CanLogResponseContent(RequestContext const &context)
Definition: HttpService.cpp:34
boost::beast::http::request< RequestBody > Request
Definition: HttpCommon.h:30
TC_NETWORK_API bool CanLogRequestContent(RequestContext const &context)
Definition: HttpService.cpp:29
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38