5 #ifndef HTTPREQUEST_HPP
6 #define HTTPREQUEST_HPP
20 #include <system_error>
21 #include <type_traits>
24 #if defined(_WIN32) || defined(__CYGWIN__)
25 # pragma push_macro("WIN32_LEAN_AND_MEAN")
26 # pragma push_macro("NOMINMAX")
27 # ifndef WIN32_LEAN_AND_MEAN
28 # define WIN32_LEAN_AND_MEAN
33 # include <winsock2.h>
34 # if _WIN32_WINNT < _WIN32_WINNT_WINXP
35 extern "C" char *_strdup(
const char *strSource);
36 # define strdup _strdup
39 # include <ws2tcpip.h>
40 # pragma pop_macro("WIN32_LEAN_AND_MEAN")
41 # pragma pop_macro("NOMINMAX")
45 # include <netinet/in.h>
47 # include <sys/select.h>
48 # include <sys/socket.h>
49 # include <sys/types.h>
58 using logic_error::logic_error;
64 using runtime_error::runtime_error;
175 std::vector<std::uint8_t>
body;
178 inline namespace detail
180 #if defined(_WIN32) || defined(__CYGWIN__)
187 const auto error = WSAStartup(MAKEWORD(2, 2), &wsaData);
189 throw std::system_error{error, std::system_category(),
"WSAStartup failed"};
191 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
194 throw std::runtime_error{
"Invalid WinSock version"};
202 if (started) WSACleanup();
205 WinSock(WinSock&& other) noexcept:
206 started{other.started}
208 other.started =
false;
211 WinSock& operator=(WinSock&& other) noexcept
213 if (&other ==
this)
return *
this;
214 if (started) WSACleanup();
215 started = other.started;
216 other.started =
false;
221 bool started =
false;
227 #if defined(_WIN32) || defined(__CYGWIN__)
228 return WSAGetLastError();
244 #if defined(_WIN32) || defined(__CYGWIN__)
253 endpoint{socket(
getAddressFamily(internetProtocol), SOCK_STREAM, IPPROTO_TCP)}
256 throw std::system_error{
getLastError(), std::system_category(),
"Failed to create socket"};
258 #if defined(_WIN32) || defined(__CYGWIN__)
260 if (ioctlsocket(endpoint, FIONBIO, &mode) != 0)
263 throw std::system_error{WSAGetLastError(), std::system_category(),
"Failed to get socket flags"};
266 const auto flags = fcntl(endpoint, F_GETFL);
270 throw std::system_error{errno, std::system_category(),
"Failed to get socket flags"};
273 if (fcntl(endpoint, F_SETFL, flags | O_NONBLOCK) == -1)
276 throw std::system_error{errno, std::system_category(),
"Failed to set socket flags"};
282 if (setsockopt(endpoint, SOL_SOCKET, SO_NOSIGPIPE, &value,
sizeof(value)) == -1)
285 throw std::system_error{errno, std::system_category(),
"Failed to set socket option"};
292 if (endpoint !=
invalid) close();
296 endpoint{other.endpoint}
303 if (&other ==
this)
return *
this;
304 if (endpoint !=
invalid) close();
305 endpoint = other.endpoint;
310 void connect(
const struct sockaddr* address,
const socklen_t addressSize,
const std::int64_t timeout)
312 #if defined(_WIN32) || defined(__CYGWIN__)
313 auto result =
::connect(endpoint, address, addressSize);
314 while (result == -1 && WSAGetLastError() == WSAEINTR)
315 result =
::connect(endpoint, address, addressSize);
319 if (WSAGetLastError() == WSAEWOULDBLOCK)
321 select(SelectType::write, timeout);
323 char socketErrorPointer[
sizeof(int)];
324 socklen_t optionLength =
sizeof(socketErrorPointer);
325 if (getsockopt(endpoint, SOL_SOCKET, SO_ERROR, socketErrorPointer, &optionLength) == -1)
326 throw std::system_error{WSAGetLastError(), std::system_category(),
"Failed to get socket option"};
329 std::memcpy(&socketError, socketErrorPointer,
sizeof(socketErrorPointer));
331 if (socketError != 0)
332 throw std::system_error{socketError, std::system_category(),
"Failed to connect"};
335 throw std::system_error{WSAGetLastError(), std::system_category(),
"Failed to connect"};
338 auto result =
::connect(endpoint, address, addressSize);
339 while (result == -1 && errno == EINTR)
340 result =
::connect(endpoint, address, addressSize);
344 if (errno == EINPROGRESS)
346 select(SelectType::write, timeout);
349 socklen_t optionLength =
sizeof(socketError);
350 if (getsockopt(endpoint, SOL_SOCKET, SO_ERROR, &socketError, &optionLength) == -1)
351 throw std::system_error{errno, std::system_category(),
"Failed to get socket option"};
353 if (socketError != 0)
354 throw std::system_error{socketError, std::system_category(),
"Failed to connect"};
357 throw std::system_error{errno, std::system_category(),
"Failed to connect"};
362 std::size_t
send(
const void* buffer,
const std::size_t length,
const std::int64_t timeout)
364 select(SelectType::write, timeout);
365 #if defined(_WIN32) || defined(__CYGWIN__)
366 auto result =
::send(endpoint,
reinterpret_cast<const char*
>(buffer),
367 static_cast<int>(length), 0);
369 while (result == -1 && WSAGetLastError() == WSAEINTR)
370 result =
::send(endpoint,
reinterpret_cast<const char*
>(buffer),
371 static_cast<int>(length), 0);
374 throw std::system_error{WSAGetLastError(), std::system_category(),
"Failed to send data"};
376 auto result =
::send(endpoint,
reinterpret_cast<const char*
>(buffer),
379 while (result == -1 && errno == EINTR)
380 result =
::send(endpoint,
reinterpret_cast<const char*
>(buffer),
384 throw std::system_error{errno, std::system_category(),
"Failed to send data"};
386 return static_cast<std::size_t
>(result);
389 std::size_t
recv(
void* buffer,
const std::size_t length,
const std::int64_t timeout)
391 select(SelectType::read, timeout);
392 #if defined(_WIN32) || defined(__CYGWIN__)
393 auto result =
::recv(endpoint,
reinterpret_cast<char*
>(buffer),
394 static_cast<int>(length), 0);
396 while (result == -1 && WSAGetLastError() == WSAEINTR)
397 result =
::recv(endpoint,
reinterpret_cast<char*
>(buffer),
398 static_cast<int>(length), 0);
401 throw std::system_error{WSAGetLastError(), std::system_category(),
"Failed to read data"};
403 auto result =
::recv(endpoint,
reinterpret_cast<char*
>(buffer),
406 while (result == -1 && errno == EINTR)
407 result =
::recv(endpoint,
reinterpret_cast<char*
>(buffer),
411 throw std::system_error{errno, std::system_category(),
"Failed to read data"};
413 return static_cast<std::size_t
>(result);
417 enum class SelectType
423 void select(
const SelectType type,
const std::int64_t timeout)
425 fd_set descriptorSet;
426 FD_ZERO(&descriptorSet);
427 FD_SET(endpoint, &descriptorSet);
429 #if defined(_WIN32) || defined(__CYGWIN__)
430 TIMEVAL selectTimeout{
431 static_cast<LONG
>(timeout / 1000),
432 static_cast<LONG
>((timeout % 1000) * 1000)
434 auto count = ::select(0,
435 (type == SelectType::read) ? &descriptorSet :
nullptr,
436 (type == SelectType::write) ? &descriptorSet :
nullptr,
438 (timeout >= 0) ? &selectTimeout :
nullptr);
440 while (count == -1 && WSAGetLastError() == WSAEINTR)
442 (type == SelectType::read) ? &descriptorSet :
nullptr,
443 (type == SelectType::write) ? &descriptorSet :
nullptr,
445 (timeout >= 0) ? &selectTimeout :
nullptr);
448 throw std::system_error{WSAGetLastError(), std::system_category(),
"Failed to select socket"};
450 throw ResponseError{
"Request timed out"};
452 timeval selectTimeout{
453 static_cast<time_t
>(timeout / 1000),
454 static_cast<suseconds_t
>((timeout % 1000) * 1000)
456 auto count = ::select(endpoint + 1,
457 (type == SelectType::read) ? &descriptorSet :
nullptr,
458 (type == SelectType::write) ? &descriptorSet :
nullptr,
460 (timeout >= 0) ? &selectTimeout :
nullptr);
462 while (count == -1 && errno == EINTR)
463 count = ::select(endpoint + 1,
464 (type == SelectType::read) ? &descriptorSet :
nullptr,
465 (type == SelectType::write) ? &descriptorSet :
nullptr,
467 (timeout >= 0) ? &selectTimeout :
nullptr);
470 throw std::system_error{errno, std::system_category(),
"Failed to select socket"};
472 throw ResponseError{
"Request timed out"};
476 void close() noexcept
478 #if defined(_WIN32) || defined(__CYGWIN__)
479 closesocket(endpoint);
485 #if defined(__unix__) && !defined(__APPLE__) && !defined(__CYGWIN__)
486 static constexpr
int noSignal = MSG_NOSIGNAL;
488 static constexpr
int noSignal = 0;
495 template <
typename C>
498 return c == 0x20 || c == 0x09;
502 template <
typename C>
505 return c >= 0x30 && c <= 0x39;
509 template <
typename C>
513 (c >= 0x61 && c <= 0x7A) ||
514 (c >= 0x41 && c <= 0x5A);
518 template <
typename C>
541 template <
typename C>
544 return c >= 0x21 && c <= 0x7E;
548 template <
typename C>
551 return static_cast<unsigned char>(c) >= 0x80 &&
552 static_cast<unsigned char>(c) <= 0xFF;
555 template <
class Iterator>
559 for (i = begin; i != end; ++i)
567 template <typename T, typename C, typename std::enable_if<std::is_unsigned<T>::value>::type* =
nullptr>
571 return (c >= 0x30 && c <= 0x39) ?
static_cast<T
>(c - 0x30) :
576 template <typename T, typename C, typename std::enable_if<std::is_unsigned<T>::value>::type* =
nullptr>
580 return (c >= 0x30 && c <= 0x39) ?
static_cast<T
>(c - 0x30) :
581 (c >= 0x41 && c <= 0x46) ?
static_cast<T
>(c - 0x41) + T(10) :
582 (c >= 0x61 && c <= 0x66) ? static_cast<T>(c - 0x61) + T(10) :
587 template <
class Iterator>
597 result.
scheme.push_back(*i++);
600 result.
scheme.push_back(*i);
602 if (i == end || *i++ !=
':')
604 if (i == end || *i++ !=
'/')
606 if (i == end || *i++ !=
'/')
610 std::string authority = std::string(i, end);
613 const auto fragmentPosition = authority.find(
'#');
614 if (fragmentPosition != std::string::npos)
616 result.
fragment = authority.substr(fragmentPosition + 1);
617 authority.resize(fragmentPosition);
621 const auto queryPosition = authority.find(
'?');
622 if (queryPosition != std::string::npos)
624 result.
query = authority.substr(queryPosition + 1);
625 authority.resize(queryPosition);
629 const auto pathPosition = authority.find(
'/');
630 if (pathPosition != std::string::npos)
633 result.
path = authority.substr(pathPosition);
634 authority.resize(pathPosition);
640 std::string userinfo;
641 const auto hostPosition = authority.find(
'@');
642 if (hostPosition != std::string::npos)
644 userinfo = authority.substr(0, hostPosition);
646 const auto passwordPosition = userinfo.find(
':');
647 if (passwordPosition != std::string::npos)
649 result.
user = userinfo.substr(0, passwordPosition);
650 result.
password = userinfo.substr(passwordPosition + 1);
653 result.
user = userinfo;
655 result.
host = authority.substr(hostPosition + 1);
658 result.
host = authority;
661 const auto portPosition = result.
host.find(
':');
662 if (portPosition != std::string::npos)
665 result.
port = result.
host.substr(portPosition + 1);
666 result.
host.resize(portPosition);
673 template <
class Iterator>
674 std::pair<Iterator, HttpVersion>
parseHttpVersion(
const Iterator begin,
const Iterator end)
678 if (i == end || *i++ !=
'H')
680 if (i == end || *i++ !=
'T')
682 if (i == end || *i++ !=
'T')
684 if (i == end || *i++ !=
'P')
686 if (i == end || *i++ !=
'/')
692 const auto majorVersion = digitToUint<std::uint16_t>(*i++);
694 if (i == end || *i++ !=
'.')
700 const auto minorVersion = digitToUint<std::uint16_t>(*i++);
702 return {i,
HttpVersion{majorVersion, minorVersion}};
706 template <
class Iterator>
707 std::pair<Iterator, std::uint16_t>
parseStatusCode(
const Iterator begin,
const Iterator end)
709 std::uint16_t result = 0;
713 result =
static_cast<std::uint16_t
>(result * 10U) + digitToUint<std::uint16_t>(*i++);
715 if (std::distance(begin, i) != 3)
722 template <
class Iterator>
729 result.push_back(
static_cast<char>(*i));
731 return {i, std::move(result)};
735 template <
class Iterator>
736 std::pair<Iterator, std::string>
parseToken(
const Iterator begin,
const Iterator end)
742 result.push_back(
static_cast<char>(*i));
747 return {i, std::move(result)};
751 template <
class Iterator>
752 std::pair<Iterator, std::string>
parseFieldValue(
const Iterator begin,
const Iterator end)
758 result.push_back(
static_cast<char>(*i));
761 result.erase(std::find_if(result.rbegin(), result.rend(), [](
const char c) noexcept {
763 }).base(), result.end());
765 return {i, std::move(result)};
769 template <
class Iterator>
779 i = fieldValueResult.first;
780 result += fieldValueResult.second;
784 auto obsoleteFoldIterator = i;
785 if (obsoleteFoldIterator == end || *obsoleteFoldIterator++ !=
'\r')
788 if (obsoleteFoldIterator == end || *obsoleteFoldIterator++ !=
'\n')
791 if (obsoleteFoldIterator == end || !
isWhiteSpaceChar(*obsoleteFoldIterator++))
794 result.push_back(
' ');
795 i = obsoleteFoldIterator;
798 return {i, std::move(result)};
802 template <
class Iterator>
803 std::pair<Iterator, HeaderField>
parseHeaderField(
const Iterator begin,
const Iterator end)
806 auto i = tokenResult.first;
807 auto fieldName = std::move(tokenResult.second);
809 if (i == end || *i++ !=
':')
815 i = valueResult.first;
816 auto fieldValue = std::move(valueResult.second);
818 if (i == end || *i++ !=
'\r')
821 if (i == end || *i++ !=
'\n')
824 return {i, {std::move(fieldName), std::move(fieldValue)}};
828 template <
class Iterator>
832 auto i = httpVersionResult.first;
834 if (i == end || *i++ !=
' ')
838 i = statusCodeResult.first;
840 if (i == end || *i++ !=
' ')
844 i = reasonPhraseResult.first;
846 if (i == end || *i++ !=
'\r')
849 if (i == end || *i++ !=
'\n')
853 httpVersionResult.second,
854 statusCodeResult.second,
855 std::move(reasonPhraseResult.second)
860 template <typename T, class Iterator, typename std::enable_if<std::is_unsigned<T>::value>::type* =
nullptr>
864 for (
auto i = begin; i != end; ++i)
865 result = T(10U) * result + digitToUint<T>(*i);
870 template <typename T, class Iterator, typename std::enable_if<std::is_unsigned<T>::value>::type* =
nullptr>
874 for (
auto i = begin; i != end; ++i)
875 result = T(16U) * result + hexDigitToUint<T>(*i);
883 return method +
" " + target +
" HTTP/1.1\r\n";
890 for (
const auto& headerField : headerFields)
892 if (headerField.first.empty())
895 for (
const auto c : headerField.first)
899 for (
const auto c : headerField.second)
903 result += headerField.first +
": " + headerField.second +
"\r\n";
910 template <
class Iterator>
913 constexpr std::array<char, 64> chars{
914 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
915 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
916 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
917 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
918 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'
923 std::array<std::uint8_t, 3> charArray;
925 for (
auto i = begin; i != end; ++i)
927 charArray[c++] =
static_cast<std::uint8_t
>(*i);
930 result += chars[
static_cast<std::uint8_t
>((charArray[0] & 0xFC) >> 2)];
931 result += chars[
static_cast<std::uint8_t
>(((charArray[0] & 0x03) << 4) + ((charArray[1] & 0xF0) >> 4))];
932 result += chars[
static_cast<std::uint8_t
>(((charArray[1] & 0x0F) << 2) + ((charArray[2] & 0xC0) >> 6))];
933 result += chars[
static_cast<std::uint8_t
>(charArray[2] & 0x3f)];
940 result += chars[
static_cast<std::uint8_t
>((charArray[0] & 0xFC) >> 2)];
943 result += chars[
static_cast<std::uint8_t
>((charArray[0] & 0x03) << 4)];
946 result += chars[
static_cast<std::uint8_t
>(((charArray[0] & 0x03) << 4) + ((charArray[1] & 0xF0) >> 4))];
947 result += chars[
static_cast<std::uint8_t
>((charArray[1] & 0x0F) << 2)];
950 while (++c < 4) result +=
'=';
957 const std::string& method,
958 const std::vector<uint8_t>& body,
965 const std::string requestTarget = uri.
path + (uri.
query.empty() ?
"" :
'?' + uri.
query);
968 headerFields.push_back({
"Host", uri.
host});
971 headerFields.push_back({
"Content-Length", std::to_string(body.size())});
977 headerFields.push_back({
"Authorization",
"Basic " +
encodeBase64(userinfo.begin(), userinfo.end())});
984 std::vector<uint8_t> result(headerData.begin(), headerData.end());
985 result.insert(result.end(), body.begin(), body.end());
994 explicit Request(
const std::string& uriString,
996 internetProtocol{protocol},
997 uri{
parseUri(uriString.begin(), uriString.end())}
1002 const std::string& body =
"",
1004 const std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
1007 std::vector<uint8_t>(body.begin(), body.end()),
1013 const std::vector<uint8_t>& body,
1015 const std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
1017 const auto stopTime = std::chrono::steady_clock::now() + timeout;
1019 if (uri.
scheme !=
"http")
1020 throw RequestError{
"Only HTTP scheme is supported"};
1022 addrinfo hints = {};
1024 hints.ai_socktype = SOCK_STREAM;
1026 const char* port = uri.
port.empty() ?
"80" : uri.
port.c_str();
1029 if (getaddrinfo(uri.
host.c_str(), port, &hints, &info) != 0)
1030 throw std::system_error{
getLastError(), std::system_category(),
"Failed to get address info of " + uri.
host};
1032 const std::unique_ptr<addrinfo, decltype(&freeaddrinfo)> addressInfo{info, freeaddrinfo};
1034 const auto requestData =
encodeHtml(uri, method, body, headerFields);
1036 Socket socket{internetProtocol};
1038 const auto getRemainingMilliseconds = [](
const std::chrono::steady_clock::time_point time) noexcept -> std::int64_t {
1039 const auto now = std::chrono::steady_clock::now();
1040 const auto remainingTime = std::chrono::duration_cast<std::chrono::milliseconds>(time - now);
1041 return (remainingTime.count() > 0) ? remainingTime.count() : 0;
1045 socket.connect(addressInfo->ai_addr,
static_cast<socklen_t
>(addressInfo->ai_addrlen),
1046 (timeout.count() >= 0) ? getRemainingMilliseconds(stopTime) : -1);
1048 auto remaining = requestData.size();
1049 auto sendData = requestData.data();
1052 while (remaining > 0)
1054 const auto size = socket.send(sendData, remaining,
1055 (timeout.count() >= 0) ? getRemainingMilliseconds(stopTime) : -1);
1060 std::array<std::uint8_t, 4096> tempBuffer;
1061 constexpr std::array<std::uint8_t, 2> crlf = {
'\r',
'\n'};
1062 constexpr std::array<std::uint8_t, 4> headerEnd = {
'\r',
'\n',
'\r',
'\n'};
1064 std::vector<std::uint8_t> responseData;
1065 bool parsingBody =
false;
1066 bool contentLengthReceived =
false;
1067 std::size_t contentLength = 0U;
1068 bool chunkedResponse =
false;
1069 std::size_t expectedChunkSize = 0U;
1070 bool removeCrlfAfterChunk =
false;
1075 const auto size = socket.recv(tempBuffer.data(), tempBuffer.size(),
1076 (timeout.count() >= 0) ? getRemainingMilliseconds(stopTime) : -1);
1080 responseData.insert(responseData.end(), tempBuffer.begin(), tempBuffer.begin() + size);
1086 const auto endIterator = std::search(responseData.cbegin(), responseData.cend(),
1087 headerEnd.cbegin(), headerEnd.cend());
1088 if (endIterator == responseData.cend())
break;
1090 const auto headerBeginIterator = responseData.cbegin();
1091 const auto headerEndIterator = endIterator + 2;
1093 auto statusLineResult =
parseStatusLine(headerBeginIterator, headerEndIterator);
1094 auto i = statusLineResult.first;
1096 response.status = std::move(statusLineResult.second);
1101 i = headerFieldResult.first;
1103 auto fieldName = std::move(headerFieldResult.second.first);
1104 const auto toLower = [](
const char c) noexcept {
1105 return (c >=
'A' && c <=
'Z') ? c - (
'A' -
'a') : c;
1107 std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), toLower);
1109 auto fieldValue = std::move(headerFieldResult.second.second);
1111 if (fieldName ==
"transfer-encoding")
1114 if (fieldValue ==
"chunked")
1115 chunkedResponse =
true;
1117 throw ResponseError{
"Unsupported transfer encoding: " + fieldValue};
1119 else if (fieldName ==
"content-length")
1122 contentLength = stringToUint<std::size_t>(fieldValue.cbegin(), fieldValue.cend());
1123 contentLengthReceived =
true;
1124 response.body.reserve(contentLength);
1127 response.headerFields.push_back({std::move(fieldName), std::move(fieldValue)});
1129 if (i == headerEndIterator)
1133 responseData.erase(responseData.cbegin(), headerEndIterator + 2);
1140 if (chunkedResponse)
1145 if (expectedChunkSize > 0)
1147 const auto toWrite = (std::min)(expectedChunkSize, responseData.size());
1148 response.body.insert(response.body.end(), responseData.begin(),
1149 responseData.begin() +
static_cast<std::ptrdiff_t
>(toWrite));
1150 responseData.erase(responseData.begin(),
1151 responseData.begin() +
static_cast<std::ptrdiff_t
>(toWrite));
1152 expectedChunkSize -= toWrite;
1154 if (expectedChunkSize == 0) removeCrlfAfterChunk =
true;
1155 if (responseData.empty())
break;
1159 if (removeCrlfAfterChunk)
1161 if (responseData.size() < 2)
break;
1163 if (!std::equal(crlf.begin(), crlf.end(), responseData.begin()))
1164 throw ResponseError{
"Invalid chunk"};
1166 removeCrlfAfterChunk =
false;
1167 responseData.erase(responseData.begin(), responseData.begin() + 2);
1170 const auto i = std::search(responseData.begin(), responseData.end(),
1171 crlf.begin(), crlf.end());
1173 if (i == responseData.end())
break;
1175 expectedChunkSize = detail::hexStringToUint<std::size_t>(responseData.begin(), i);
1176 responseData.erase(responseData.begin(), i + 2);
1178 if (expectedChunkSize == 0)
1185 response.body.insert(response.body.end(), responseData.begin(), responseData.end());
1186 responseData.clear();
1189 if (contentLengthReceived && response.body.size() >= contentLength)
1199 #if defined(_WIN32) || defined(__CYGWIN__)
Definition: HTTPRequest.h:56
Definition: HTTPRequest.h:992
Response send(const std::string &method, const std::vector< uint8_t > &body, const HeaderFields &headerFields={}, const std::chrono::milliseconds timeout=std::chrono::milliseconds{-1})
Definition: HTTPRequest.h:1012
Request(const std::string &uriString, const InternetProtocol protocol=InternetProtocol::v4)
Definition: HTTPRequest.h:994
Response send(const std::string &method="GET", const std::string &body="", const HeaderFields &headerFields={}, const std::chrono::milliseconds timeout=std::chrono::milliseconds{-1})
Definition: HTTPRequest.h:1001
Definition: HTTPRequest.h:62
Definition: HTTPRequest.h:242
Socket & operator=(Socket &&other) noexcept
Definition: HTTPRequest.h:301
static constexpr Type invalid
Definition: HTTPRequest.h:249
std::size_t recv(void *buffer, const std::size_t length, const std::int64_t timeout)
Definition: HTTPRequest.h:389
Socket(Socket &&other) noexcept
Definition: HTTPRequest.h:295
Socket(const InternetProtocol internetProtocol)
Definition: HTTPRequest.h:252
std::size_t send(const void *buffer, const std::size_t length, const std::int64_t timeout)
Definition: HTTPRequest.h:362
int Type
Definition: HTTPRequest.h:248
void connect(const struct sockaddr *address, const socklen_t addressSize, const std::int64_t timeout)
Definition: HTTPRequest.h:310
~Socket()
Definition: HTTPRequest.h:290
std::string encodeHeaderFields(const HeaderFields &headerFields)
Definition: HTTPRequest.h:887
std::pair< Iterator, std::string > parseToken(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:736
std::pair< Iterator, std::uint16_t > parseStatusCode(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:707
std::vector< std::uint8_t > encodeHtml(const Uri &uri, const std::string &method, const std::vector< uint8_t > &body, HeaderFields headerFields)
Definition: HTTPRequest.h:956
Uri parseUri(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:588
constexpr bool isWhiteSpaceChar(const C c) noexcept
Definition: HTTPRequest.h:496
Iterator skipWhiteSpaces(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:556
constexpr T hexDigitToUint(const C c)
Definition: HTTPRequest.h:577
constexpr bool isTokenChar(const C c) noexcept
Definition: HTTPRequest.h:519
std::pair< Iterator, std::string > parseFieldValue(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:752
std::pair< Iterator, Status > parseStatusLine(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:829
std::pair< Iterator, std::string > parseReasonPhrase(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:723
T stringToUint(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:861
std::pair< Iterator, HttpVersion > parseHttpVersion(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:674
std::string encodeRequestLine(const std::string &method, const std::string &target)
Definition: HTTPRequest.h:881
T hexStringToUint(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:871
constexpr int getAddressFamily(const InternetProtocol internetProtocol)
Definition: HTTPRequest.h:234
constexpr bool isVisibleChar(const C c) noexcept
Definition: HTTPRequest.h:542
constexpr bool isObsoleteTextChar(const C c) noexcept
Definition: HTTPRequest.h:549
constexpr bool isAlphaChar(const C c) noexcept
Definition: HTTPRequest.h:510
constexpr bool isDigitChar(const C c) noexcept
Definition: HTTPRequest.h:503
constexpr T digitToUint(const C c)
Definition: HTTPRequest.h:568
std::string encodeBase64(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:911
std::pair< Iterator, HeaderField > parseHeaderField(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:803
std::pair< Iterator, std::string > parseFieldContent(const Iterator begin, const Iterator end)
Definition: HTTPRequest.h:770
int getLastError() noexcept
Definition: HTTPRequest.h:225
Definition: HTTPRequest.h:54
std::vector< HeaderField > HeaderFields
Definition: HTTPRequest.h:169
std::pair< std::string, std::string > HeaderField
Definition: HTTPRequest.h:168
InternetProtocol
Definition: HTTPRequest.h:68
Definition: HTTPRequest.h:86
uint16_t minor
Definition: HTTPRequest.h:88
uint16_t major
Definition: HTTPRequest.h:87
Definition: HTTPRequest.h:172
HeaderFields headerFields
Definition: HTTPRequest.h:174
std::vector< std::uint8_t > body
Definition: HTTPRequest.h:175
Status status
Definition: HTTPRequest.h:173
Definition: HTTPRequest.h:92
HttpVersion httpVersion
Definition: HTTPRequest.h:163
std::string reason
Definition: HTTPRequest.h:165
std::uint16_t code
Definition: HTTPRequest.h:164
Code
Definition: HTTPRequest.h:95
@ Forbidden
Definition: HTTPRequest.h:124
@ PartialContent
Definition: HTTPRequest.h:107
@ PayloadTooLarge
Definition: HTTPRequest.h:134
@ MovedPermanently
Definition: HTTPRequest.h:113
@ ImUsed
Definition: HTTPRequest.h:110
@ GatewayTimeout
Definition: HTTPRequest.h:154
@ InsufficientStorage
Definition: HTTPRequest.h:157
@ ProxyAuthenticationRequired
Definition: HTTPRequest.h:128
@ Found
Definition: HTTPRequest.h:114
@ TooEarly
Definition: HTTPRequest.h:143
@ Continue
Definition: HTTPRequest.h:96
@ EarlyHints
Definition: HTTPRequest.h:99
@ NotExtended
Definition: HTTPRequest.h:159
@ PreconditionFailed
Definition: HTTPRequest.h:133
@ RequestHeaderFieldsTooLarge
Definition: HTTPRequest.h:147
@ SeeOther
Definition: HTTPRequest.h:115
@ Locked
Definition: HTTPRequest.h:141
@ UriTooLong
Definition: HTTPRequest.h:135
@ LoopDetected
Definition: HTTPRequest.h:158
@ UnsupportedMediaType
Definition: HTTPRequest.h:136
@ NotFound
Definition: HTTPRequest.h:125
@ NotModified
Definition: HTTPRequest.h:116
@ NotAcceptable
Definition: HTTPRequest.h:127
@ BadRequest
Definition: HTTPRequest.h:121
@ Unauthorized
Definition: HTTPRequest.h:122
@ FailedDependency
Definition: HTTPRequest.h:142
@ ServiceUnavailable
Definition: HTTPRequest.h:153
@ TemporaryRedirect
Definition: HTTPRequest.h:118
@ TooManyRequests
Definition: HTTPRequest.h:146
@ MultipleChoice
Definition: HTTPRequest.h:112
@ AlreadyReported
Definition: HTTPRequest.h:109
@ LengthRequired
Definition: HTTPRequest.h:132
@ SwitchingProtocol
Definition: HTTPRequest.h:97
@ Accepted
Definition: HTTPRequest.h:103
@ PermanentRedirect
Definition: HTTPRequest.h:119
@ InternalServerError
Definition: HTTPRequest.h:150
@ NonAuthoritativeInformation
Definition: HTTPRequest.h:104
@ Processing
Definition: HTTPRequest.h:98
@ NetworkAuthenticationRequired
Definition: HTTPRequest.h:160
@ NoContent
Definition: HTTPRequest.h:105
@ BadGateway
Definition: HTTPRequest.h:152
@ PreconditionRequired
Definition: HTTPRequest.h:145
@ Ok
Definition: HTTPRequest.h:101
@ UpgradeRequired
Definition: HTTPRequest.h:144
@ Created
Definition: HTTPRequest.h:102
@ Conflict
Definition: HTTPRequest.h:130
@ UseProxy
Definition: HTTPRequest.h:117
@ MisdirectedRequest
Definition: HTTPRequest.h:139
@ ResetContent
Definition: HTTPRequest.h:106
@ RangeNotSatisfiable
Definition: HTTPRequest.h:137
@ RequestTimeout
Definition: HTTPRequest.h:129
@ VariantAlsoNegotiates
Definition: HTTPRequest.h:156
@ NotImplemented
Definition: HTTPRequest.h:151
@ UnavailableForLegalReasons
Definition: HTTPRequest.h:148
@ ExpectationFailed
Definition: HTTPRequest.h:138
@ Gone
Definition: HTTPRequest.h:131
@ UnprocessableEntity
Definition: HTTPRequest.h:140
@ HttpVersionNotSupported
Definition: HTTPRequest.h:155
@ MultiStatus
Definition: HTTPRequest.h:108
@ PaymentRequired
Definition: HTTPRequest.h:123
@ MethodNotAllowed
Definition: HTTPRequest.h:126
Definition: HTTPRequest.h:74
std::string scheme
Definition: HTTPRequest.h:75
std::string fragment
Definition: HTTPRequest.h:82
std::string host
Definition: HTTPRequest.h:78
std::string user
Definition: HTTPRequest.h:76
std::string path
Definition: HTTPRequest.h:80
std::string password
Definition: HTTPRequest.h:77
std::string port
Definition: HTTPRequest.h:79
std::string query
Definition: HTTPRequest.h:81