can specify extra headers

This commit is contained in:
Benjamin Sergeant 2019-02-25 17:17:05 -08:00
parent 3bcd6f97a6
commit b563541b14
4 changed files with 54 additions and 55 deletions

View File

@ -36,6 +36,7 @@ namespace ix
HttpResponse HttpClient::request( HttpResponse HttpClient::request(
const std::string& url, const std::string& url,
const std::string& verb, const std::string& verb,
const WebSocketHttpHeaders& extraHeaders,
const HttpParameters& httpParameters, const HttpParameters& httpParameters,
bool verbose) bool verbose)
{ {
@ -98,6 +99,12 @@ namespace ix
ss << "Host: " << host << "\r\n"; ss << "Host: " << host << "\r\n";
ss << "User-Agent: ixwebsocket/1.0.0" << "\r\n"; ss << "User-Agent: ixwebsocket/1.0.0" << "\r\n";
ss << "Accept: */*" << "\r\n"; ss << "Accept: */*" << "\r\n";
for (auto&& it : extraHeaders)
{
ss << it.first << ": " << urlEncode(it.second) << "\r\n";
}
if (verb == "POST") if (verb == "POST")
{ {
ss << "Content-Length: " << body.size() << "\r\n"; ss << "Content-Length: " << body.size() << "\r\n";
@ -196,7 +203,7 @@ namespace ix
payload.reserve(contentLength); payload.reserve(contentLength);
// very inefficient way to read bytes, but it works... // FIXME: very inefficient way to read bytes, but it works...
for (int i = 0; i < contentLength; ++i) for (int i = 0; i < contentLength; ++i)
{ {
char c; char c;
@ -215,17 +222,19 @@ namespace ix
HttpResponse HttpClient::get( HttpResponse HttpClient::get(
const std::string& url, const std::string& url,
const WebSocketHttpHeaders& extraHeaders,
bool verbose) bool verbose)
{ {
return request(url, "GET", HttpParameters(), verbose); return request(url, "GET", extraHeaders, HttpParameters(), verbose);
} }
HttpResponse HttpClient::post( HttpResponse HttpClient::post(
const std::string& url, const std::string& url,
const WebSocketHttpHeaders& extraHeaders,
const HttpParameters& httpParameters, const HttpParameters& httpParameters,
bool verbose) bool verbose)
{ {
return request(url, "POST", httpParameters, verbose); return request(url, "POST", extraHeaders, httpParameters, verbose);
} }
std::string HttpClient::urlEncode(const std::string& value) std::string HttpClient::urlEncode(const std::string& value)
@ -255,48 +264,3 @@ namespace ix
return escaped.str(); return escaped.str();
} }
} }
#if 0
std::vector<uint8_t> rxbuf;
while (true)
{
int N = (int) _rxbuf.size();
_rxbuf.resize(N + 1500);
ssize_t ret = _socket->recv((char*)&_rxbuf[0] + N, 1500);
if (ret < 0 && (_socket->getErrno() == EWOULDBLOCK ||
_socket->getErrno() == EAGAIN)) {
_rxbuf.resize(N);
break;
}
else if (ret <= 0)
{
_rxbuf.resize(N);
_socket->close();
setReadyState(CLOSED);
break;
}
else
{
_rxbuf.resize(N + ret);
}
}
ssize_t ret = _socket->recv((char*)&rxbuf[0], contentLength);
payload = std::string(rxbuf.begin(), rxbuf.end());
std::cerr << "socket->recv: " << ret << std::endl;
if (ret != contentLength)
{
ss.str("");
ss << "Cannot retrieve all bytes"
<< " want: " << contentLength
<< ", got: " << ret;
std::cerr << "adscasdcadcasdc" << std::endl;
std::cerr << ss.str() << std::endl;
return std::make_tuple(-1, headers, payload, ss.str());
}
#endif

View File

@ -28,14 +28,18 @@ namespace ix
~HttpClient(); ~HttpClient();
// Static methods ? // Static methods ?
HttpResponse get(const std::string& url, bool verbose); HttpResponse get(const std::string& url,
const WebSocketHttpHeaders& extraHeaders,
bool verbose);
HttpResponse post(const std::string& url, HttpResponse post(const std::string& url,
const WebSocketHttpHeaders& extraHeaders,
const HttpParameters& httpParameters, const HttpParameters& httpParameters,
bool verbose); bool verbose);
private: private:
HttpResponse request(const std::string& url, HttpResponse request(const std::string& url,
const std::string& verb, const std::string& verb,
const WebSocketHttpHeaders& extraHeaders,
const HttpParameters& httpParameters, const HttpParameters& httpParameters,
bool verbose); bool verbose);

View File

@ -18,6 +18,7 @@
namespace ix namespace ix
{ {
int ws_http_client_main(const std::string& url, int ws_http_client_main(const std::string& url,
const std::string& headers,
const std::string& data); const std::string& data);
int ws_ping_pong_main(const std::string& url); int ws_ping_pong_main(const std::string& url);
@ -49,6 +50,7 @@ int main(int argc, char** argv)
std::string path; std::string path;
std::string user; std::string user;
std::string data; std::string data;
std::string headers;
int port = 8080; int port = 8080;
CLI::App* sendApp = app.add_subcommand("send", "Send a file"); CLI::App* sendApp = app.add_subcommand("send", "Send a file");
@ -82,6 +84,7 @@ int main(int argc, char** argv)
httpClientApp->add_option("url", url, "Connection url")->required(); httpClientApp->add_option("url", url, "Connection url")->required();
httpClientApp->add_option("-d", data, "Form data")->join(); httpClientApp->add_option("-d", data, "Form data")->join();
httpClientApp->add_option("-F", data, "Form data")->join(); httpClientApp->add_option("-F", data, "Form data")->join();
httpClientApp->add_option("-H", headers, "Header")->join();
CLI11_PARSE(app, argc, argv); CLI11_PARSE(app, argc, argv);
@ -123,7 +126,7 @@ int main(int argc, char** argv)
else if (app.got_subcommand("http_client")) else if (app.got_subcommand("http_client"))
{ {
std::cout << "data: " << data << std::endl; std::cout << "data: " << data << std::endl;
return ix::ws_http_client_main(url, data); return ix::ws_http_client_main(url, headers, data);
} }
return 1; return 1;

View File

@ -7,9 +7,35 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <ixwebsocket/IXHttpClient.h> #include <ixwebsocket/IXHttpClient.h>
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
namespace ix namespace ix
{ {
WebSocketHttpHeaders parseHeaders(const std::string& data)
{
WebSocketHttpHeaders headers;
// Split by \n
std::string token;
std::stringstream tokenStream(data);
while (std::getline(tokenStream, token))
{
std::size_t pos = token.rfind(':');
// Bail out if last '.' is found
if (pos == std::string::npos) continue;
auto key = token.substr(0, pos);
auto val = token.substr(pos+2);
std::cout << key << ": " << val << std::endl;
headers[key] = val;
}
return headers;
}
// //
// Useful endpoint to test HTTP post // Useful endpoint to test HTTP post
// https://postman-echo.com/post // https://postman-echo.com/post
@ -18,7 +44,7 @@ namespace ix
{ {
HttpParameters httpParameters; HttpParameters httpParameters;
// Split by ; // Split by \n
std::string token; std::string token;
std::stringstream tokenStream(data); std::stringstream tokenStream(data);
@ -40,27 +66,29 @@ namespace ix
} }
int ws_http_client_main(const std::string& url, int ws_http_client_main(const std::string& url,
const std::string& headersData,
const std::string& data) const std::string& data)
{ {
HttpParameters httpParameters = parsePostParameters(data); HttpParameters httpParameters = parsePostParameters(data);
WebSocketHttpHeaders headers = parseHeaders(headersData);
HttpClient httpClient; HttpClient httpClient;
bool verbose = true; bool verbose = true;
HttpResponse out; HttpResponse out;
if (data.empty()) if (data.empty())
{ {
out = httpClient.get(url, verbose); out = httpClient.get(url, headers, verbose);
} }
else else
{ {
out = httpClient.post(url, httpParameters, verbose); out = httpClient.post(url, headers, httpParameters, verbose);
} }
auto errorCode = std::get<0>(out); auto errorCode = std::get<0>(out);
auto headers = std::get<1>(out); auto responseHeaders = std::get<1>(out);
auto payload = std::get<2>(out); auto payload = std::get<2>(out);
auto errorMsg = std::get<3>(out); auto errorMsg = std::get<3>(out);
for (auto it : headers) for (auto it : responseHeaders)
{ {
std::cout << it.first << ": " << it.second << std::endl; std::cout << it.first << ": " << it.second << std::endl;
} }