2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
42#ifndef DOXYGEN_SHOULD_SKIP_THIS
44#include "web/http/http_utils.h"
46#include "utils/hexdump.h"
47#include "utils/system/time.h"
48#include "web/http/CiStringMap.h"
49#include "web/http/CookieOptions.h"
63 return isdigit(ch) != 0 ? ch -
'0' : tolower(ch) -
'a' + 10;
69 for (std::string::const_iterator i = text.begin(), n = text.end(); i != n; ++i) {
70 const std::string::value_type c = (*i);
73 if ((i[1] != 0) && (i[2] != 0)) {
77 }
else if (c ==
'+') {
88 std::ostringstream escaped;
92 for (
const char c : text) {
93 if ((isalnum(c) != 0) || c ==
'-' || c ==
'_' || c ==
'.' || c ==
'~') {
96 escaped << std::uppercase;
97 escaped <<
'%' << std::setw(2) <<
static_cast<
unsigned char>(c);
98 escaped << std::nouppercase;
102 return escaped.str();
106 text.erase(text.find_last_not_of(
" \t") + 1);
107 text.erase(0, text.find_first_not_of(
" \t"));
112 std::pair<std::string, std::string>
str_split(
const std::string& base,
char c_middle) {
113 std::pair<std::string, std::string> split;
115 const unsigned long middle = base.find_first_of(c_middle);
117 split.first = base.substr(0, middle);
119 if (middle != std::string::npos) {
120 split.second = base.substr(middle + 1);
126 std::pair<std::string, std::string>
str_split_last(
const std::string& base,
char c_middle) {
127 std::pair<std::string, std::string> split;
129 const unsigned long middle = base.find_last_of(c_middle);
131 split.first = base.substr(0, middle);
133 if (middle != std::string::npos) {
134 split.second = base.substr(middle + 1);
147 const time_t time = utils::
system::mktime(tm);
151 (
void) strftime(buf,
sizeof buf,
"%a, %d %b %Y %H:%M:%S %Z", tm);
154 return std::string(buf);
157 struct tm from_http_date(
const std::string& http_date) {
160 strptime(http_date.c_str(),
"%a, %d %b %Y %H:%M:%S", &tm);
169 struct stat attrib{};
170 stat(filePath.c_str(), &attrib);
172 (
void) strftime(buf,
sizeof buf,
"%a, %d %b %Y %H:%M:%S %Z", gmtime(&(attrib.st_mtime)));
175 return std::string(buf);
178 std::string::iterator
to_lower(std::string& string) {
179 return std::transform(string.begin(), string.end(), string.begin(), ::tolower);
183 const std::string& url,
184 const std::string& version,
185 const web::http::
CiStringMap<std::string>& queries,
187 const web::http::
CiStringMap<std::string>& cookies,
188 const std::vector<
char>& body) {
189 const int prefixLength = 9;
192 for (
const auto& [key, value] : queries) {
193 keyLength = std::max(keyLength,
static_cast<
int>(key.size()));
195 for (
const auto& [key, value] : header) {
196 keyLength = std::max(keyLength,
static_cast<
int>(key.size()));
198 for (
const auto& [key, value] : cookies) {
199 keyLength = std::max(keyLength,
static_cast<
int>(key.size()));
202 std::stringstream requestStream;
204 requestStream << std::setw(prefixLength) <<
"Request"
205 <<
": " << std::setw(keyLength) <<
"Method"
206 <<
" : " << method <<
"\n";
207 requestStream << std::setw(prefixLength) <<
""
208 <<
": " << std::setw(keyLength) <<
"Url"
209 <<
" : " << url <<
"\n";
210 requestStream << std::setw(prefixLength) <<
""
211 <<
": " << std::setw(keyLength) <<
"Version"
212 <<
" : " << version <<
"\n";
216 if (!queries.empty()) {
218 for (
const auto& [query, value] : queries) {
219 requestStream << std::setw(prefixLength) << prefix <<
": " << std::setw(keyLength) << query <<
" : " << value <<
"\n";
224 if (!header.empty()) {
226 for (
const auto& [field, value] : header) {
227 requestStream << std::setw(prefixLength) << prefix <<
": " << std::setw(keyLength) << field <<
" : " << value <<
"\n";
232 if (!cookies.empty()) {
234 for (
const auto& [cookie, value] : cookies) {
235 requestStream << std::setw(prefixLength) << prefix <<
": " << std::setw(keyLength) << cookie <<
" : " << value <<
"\n";
242 requestStream << std::setw(prefixLength) << prefix << utils
::hexDump(body
, prefixLength
) <<
"\n";
245 std::string string = requestStream.str();
246 if (!string.empty()) {
254 const std::string& statusCode,
255 const std::string& reason,
258 const std::vector<
char>& body) {
259 const int prefixLength = 9;
262 for (
const auto& [key, value] : header) {
263 keyLength = std::max(keyLength,
static_cast<
int>(key.size()));
265 for (
const auto& [key, value] : cookies) {
266 keyLength = std::max(keyLength,
static_cast<
int>(key.size()));
269 std::stringstream requestStream;
271 requestStream << std::setw(prefixLength) <<
"Response"
272 <<
": " << std::setw(keyLength) <<
"Version"
273 <<
" : " << version <<
"\n";
274 requestStream << std::setw(prefixLength) <<
""
275 <<
": " << std::setw(keyLength) <<
"Status"
276 <<
" : " << statusCode <<
"\n";
277 requestStream << std::setw(prefixLength) <<
""
278 <<
": " << std::setw(keyLength) <<
"Reason"
279 <<
" : " << reason <<
"\n";
283 if (!header.empty()) {
285 for (
const auto& [field, value] : header) {
286 requestStream << std::setw(prefixLength) << prefix <<
": " << std::setw(keyLength) << field <<
" : " << value <<
"\n";
291 if (!cookies.empty()) {
293 for (
const auto& [cookie, options] : cookies) {
294 requestStream << std::setw(prefixLength) << prefix <<
": " << std::setw(keyLength) << cookie <<
" : " << options
.getValue()
296 for (
const auto& [optionKey, optionValue] : options
.getOptions()) {
297 requestStream << std::setw(prefixLength) <<
""
298 <<
":" << std::setw(keyLength) <<
""
299 <<
" : " << optionKey <<
"=" << optionValue <<
"\n";
307 requestStream << std::setw(prefixLength) << prefix << utils
::hexDump(body
, prefixLength
) <<
"\n";
310 std::string string = requestStream.str();
311 if (!string.empty()) {
const std::map< std::string, std::string > & getOptions() const
const std::string & getValue() const
std::string to_http_date(struct tm *tm)
std::string toString(const std::string &version, const std::string &statusCode, const std::string &reason, const web::http::CiStringMap< std::string > &header, const web::http::CiStringMap< web::http::CookieOptions > &cookies, const std::vector< char > &body)
static int from_hex(int ch)
std::string url_encode(const std::string &text)
std::string file_mod_http_date(const std::string &filePath)
std::string::iterator to_lower(std::string &string)
std::pair< std::string, std::string > str_split_last(const std::string &base, char c_middle)
std::string url_decode(const std::string &text)
std::pair< std::string, std::string > str_split(const std::string &base, char c_middle)
std::string & str_trimm(std::string &text)
std::string toString(const std::string &method, const std::string &url, const std::string &version, const web::http::CiStringMap< std::string > &queries, const web::http::CiStringMap< std::string > &header, const web::http::CiStringMap< std::string > &cookies, const std::vector< char > &body)
struct tm * gmtime(const time_t *timep)
time_t time(time_t *tloc)
std::string hexDump(const std::vector< char > &bytes, int prefixLength, bool prefixAtFirstLine)