cleanup argument parsing + add socket creation factory

This commit is contained in:
Benjamin Sergeant
2019-02-27 16:35:00 -08:00
parent 7c2bc2cf7e
commit 0a752e7d18
9 changed files with 289 additions and 194 deletions

View File

@ -1,12 +1,13 @@
/*
* ws.cpp
* Author: Benjamin Sergeant
* Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved.
* Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
*/
//
// Main drive for websocket utilities
// Main driver for websocket utilities
//
#include "ws.h"
#include <string>
#include <sstream>
@ -15,34 +16,6 @@
#include <cli11/CLI11.hpp>
#include <ixwebsocket/IXSocket.h>
namespace ix
{
int ws_http_client_main(const std::string& url,
const std::string& headers,
const std::string& data,
bool headersOnly,
bool followRedirects);
int ws_ping_pong_main(const std::string& url);
int ws_echo_server_main(int port);
int ws_broadcast_server_main(int port);
int ws_chat_main(const std::string& url,
const std::string& user);
int ws_connect_main(const std::string& url);
int ws_receive_main(const std::string& url,
bool enablePerMessageDeflate);
int ws_transfer_main(int port);
int ws_send_main(const std::string& url,
const std::string& path);
}
int main(int argc, char** argv)
{
CLI::App app{"ws is a websocket tool"};
@ -53,9 +26,13 @@ int main(int argc, char** argv)
std::string user;
std::string data;
std::string headers;
std::string output;
bool headersOnly = false;
bool followRedirects = false;
bool verbose = false;
bool save = false;
int port = 8080;
int connectTimeOutSeconds = 3;
CLI::App* sendApp = app.add_subcommand("send", "Send a file");
sendApp->add_option("url", url, "Connection url")->required();
@ -84,13 +61,17 @@ int main(int argc, char** argv)
CLI::App* pingPongApp = app.add_subcommand("ping", "Ping pong");
pingPongApp->add_option("url", url, "Connection url")->required();
CLI::App* httpClientApp = app.add_subcommand("http_client", "HTTP Client");
CLI::App* httpClientApp = app.add_subcommand("curl", "HTTP Client");
httpClientApp->add_option("url", url, "Connection url")->required();
httpClientApp->add_option("-d", data, "Form data")->join();
httpClientApp->add_option("-F", data, "Form data")->join();
httpClientApp->add_option("-H", headers, "Header")->join();
httpClientApp->add_option("--output", output, "Output file");
httpClientApp->add_flag("-I", headersOnly, "Header");
httpClientApp->add_flag("-L", followRedirects, "Header");
httpClientApp->add_flag("-v", verbose, "Verbose");
httpClientApp->add_flag("-O", save, "Save to disk");
httpClientApp->add_option("--connect-timeout", connectTimeOutSeconds, "Connection timeout");
CLI11_PARSE(app, argc, argv);
@ -129,10 +110,11 @@ int main(int argc, char** argv)
{
return ix::ws_ping_pong_main(url);
}
else if (app.got_subcommand("http_client"))
else if (app.got_subcommand("curl"))
{
std::cout << "data: " << data << std::endl;
return ix::ws_http_client_main(url, headers, data, headersOnly, followRedirects);
return ix::ws_http_client_main(url, headers, data,
headersOnly, connectTimeOutSeconds,
followRedirects, verbose, save, output);
}
return 1;

View File

@ -6,11 +6,28 @@
#include <iostream>
#include <sstream>
#include <fstream>
#include <ixwebsocket/IXHttpClient.h>
#include <ixwebsocket/IXWebSocketHttpHeaders.h>
namespace ix
{
std::string extractFilename(const std::string& path)
{
std::string::size_type idx;
idx = path.rfind('/');
if (idx != std::string::npos)
{
std::string filename = path.substr(idx+1);
return filename;
}
else
{
return path;
}
}
WebSocketHttpHeaders parseHeaders(const std::string& data)
{
WebSocketHttpHeaders headers;
@ -29,7 +46,7 @@ namespace ix
auto key = token.substr(0, pos);
auto val = token.substr(pos+2);
std::cout << key << ": " << val << std::endl;
std::cerr << key << ": " << val << std::endl;
headers[key] = val;
}
@ -58,7 +75,7 @@ namespace ix
auto key = token.substr(0, pos);
auto val = token.substr(pos+1);
std::cout << key << ": " << val << std::endl;
std::cerr << key << ": " << val << std::endl;
httpParameters[key] = val;
}
@ -69,31 +86,36 @@ namespace ix
const std::string& headersData,
const std::string& data,
bool headersOnly,
bool followRedirects)
int timeoutSecs,
bool followRedirects,
bool verbose,
bool save,
const std::string& output)
{
HttpRequestArgs args;
args.url = url;
args.extraHeaders = parseHeaders(headersData);
args.timeoutSecs = timeoutSecs;
args.followRedirects = followRedirects;
args.verbose = verbose;
HttpParameters httpParameters = parsePostParameters(data);
WebSocketHttpHeaders headers = parseHeaders(headersData);
HttpClient httpClient;
bool verbose = true;
HttpResponse out;
if (headersOnly)
{
out = httpClient.head(url, headers,
followRedirects, verbose);
out = httpClient.head(args);
}
else if (data.empty())
{
out = httpClient.get(url, headers,
followRedirects, verbose);
out = httpClient.get(args);
}
else
{
out = httpClient.post(url, headers,
httpParameters,
followRedirects,
verbose);
out = httpClient.post(httpParameters, args);
}
auto errorCode = std::get<0>(out);
auto responseHeaders = std::get<1>(out);
auto payload = std::get<2>(out);
@ -101,18 +123,42 @@ namespace ix
for (auto it : responseHeaders)
{
std::cout << it.first << ": " << it.second << std::endl;
std::cerr << it.first << ": " << it.second << std::endl;
}
std::cout << "error code: " << errorCode << std::endl;
std::cerr << "error code: " << errorCode << std::endl;
if (!errorMsg.empty())
{
std::cout << "error message: " << errorMsg << std::endl;
std::cerr << "error message: " << errorMsg << std::endl;
}
if (!headersOnly)
if (!headersOnly && errorCode == 200)
{
std::cout << "payload: " << payload << std::endl;
if (responseHeaders["Content-Type"] != "application/octet-stream")
{
std::cout << "payload: " << payload << std::endl;
}
else
{
std::cerr << "Binary output can mess up your terminal." << std::endl;
std::cerr << "Use the -O flag to save the file to disk." << std::endl;
std::cerr << "You can also use the --output option to specify a filename." << std::endl;
}
if (save || !output.empty())
{
// FIMXE we should decode the url first
std::string filename = extractFilename(url);
if (!output.empty())
{
filename = output;
}
std::cout << "Writing to disk: " << filename << std::endl;
std::ofstream out(filename);
out.write((char*)&payload.front(), payload.size());
out.close();
}
}
return 0;