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