cleanup argument parsing + add socket creation factory
This commit is contained in:
		
							
								
								
									
										50
									
								
								ws/ws.cpp
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								ws/ws.cpp
									
									
									
									
									
								
							| @@ -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; | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user