7 #include <unordered_map>
25 using std::make_unique;
26 using std::nouppercase;
27 using std::ostringstream;
30 using std::stringstream;
32 using std::unique_ptr;
33 using std::unordered_map;
52 const string HTTPClient::HTTP_METHOD_GET =
"GET";
53 const string HTTPClient::HTTP_METHOD_HEAD =
"HEAD";
54 const string HTTPClient::HTTP_METHOD_POST =
"POST";
55 const string HTTPClient::HTTP_METHOD_PUT =
"PUT";
56 const string HTTPClient::HTTP_METHOD_DELETE =
"DELETE";
58 string HTTPClient::urlEncode(
const string &value) {
61 ostringstream escaped;
65 for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
66 string::value_type c = (*i);
69 if (Character::isAlphaNumeric(c) ==
true || c ==
'-' || c ==
'_' || c ==
'.' || c ==
'~') {
76 escaped <<
'%' << setw(2) << int((
unsigned char) c);
77 escaped << nouppercase;
85 for (
const auto& [parameterName, parameterValue]:
getParameters) {
86 if (query.empty() ==
true) query+=
"?";
else query+=
"&";
90 string(
method +
" " + relativeUrl + query +
" HTTP/1.1\r\n") +
91 string(
"User-Agent: tdme2-httpclient\r\n") +
92 string(
"Accept-Charset: UTF-8\r\n") +
93 string(
"Host: " + hostname +
"\r\n") +
94 string(
"Connection: close\r\n");
98 request+=
"Authorization: Basic " + base64Pass +
"\r\n";
104 for (
const auto& [headerName, headerValue]:
headers) {
105 request+= headerName +
": " + headerValue +
"\r\n";
110 for (
const auto& [parameterName, parameterValue]:
postParameters) {
111 if (_body.size() >= 0) _body+=
"&";
117 request+=
"Content-Length: " + to_string(_body.size()) +
"\r\n\r\n";
133 if (lastChar ==
'\r' && currentChar ==
'\n') {
134 if (line.empty() ==
false) {
135 if (headerIdx == 0) {
139 auto headerNameValueSeparator = StringTools::indexOf(line,
':');
140 responseHeaders[StringTools::trim(StringTools::substring(line, 0, headerNameValueSeparator))] =
141 StringTools::trim(StringTools::substring(line, headerNameValueSeparator + 1));
148 if (currentChar !=
'\r' && currentChar !=
'\n') {
151 lastChar = currentChar;
153 if (statusHeader.empty() ==
false) {
181 unique_ptr<TCPSocket> socket;
184 auto protocolSeparatorIdx = StringTools::indexOf(
url,
string(
"://"));
186 auto relativeUrl = StringTools::substring(
url, protocolSeparatorIdx + 3);
188 auto slashIdx = relativeUrl.find(
'/');
189 auto hostname = relativeUrl;
190 if (slashIdx != -1) hostname = StringTools::substring(relativeUrl, 0, slashIdx);
191 relativeUrl = StringTools::substring(relativeUrl, hostname.size());
193 if (StringTools::startsWith(
url,
"http://") ==
true) {
194 auto ip = Network::getIpByHostname(hostname);
195 if (ip.empty() ==
true) {
196 Console::println(
"HTTPClient::execute(): failed");
200 socket = make_unique<TCPSocket>();
201 socket->connect(ip, 80);
203 if (StringTools::startsWith(
url,
"https://") ==
true) {
204 socket = make_unique<SecureTCPSocket>();
205 socket->connect(hostname, 443);
211 socket->write((
void*)request.data(), request.length());
213 char rawResponseBuf[16384];
214 auto rawResponseBytesRead = 0;
217 auto rawResponseBytesRead = socket->read(rawResponseBuf,
sizeof(rawResponseBuf));
218 rawResponse.write(rawResponseBuf, rawResponseBytesRead);
232 Console::println(
string(
"HTTPClient::execute(): performed HTTP request: FAILED: ") + exception.what());
unordered_map< string, string > headers
void execute()
Execute HTTP request.
static STATIC_DLL_IMPEXT const string HTTP_METHOD_POST
static STATIC_DLL_IMPEXT const string HTTP_METHOD_PUT
unordered_map< string, string > getParameters
unordered_map< string, string > responseHeaders
unordered_map< string, string > postParameters
static string urlEncode(const string &value)
Returns a URL encoded representation of value.
void reset()
Reset this HTTP client.
string createHTTPRequestHeaders(const string &hostname, const string &relativeUrl, const string &body)
Create HTTP request headers.
void parseHTTPResponseHeaders(stringstream &rawResponse)
Parse HTTP response headers.
Network socket closed exception.
Class representing a secure TCP socket.
Class representing a TCP socket.
Base64 encoding/decoding class.
const string & nextToken()
void tokenize(const string &str, const string &delimiters, bool emptyTokens=false)
Tokenize.
std::exception Exception
Exception base class.