http gzip compression
This commit is contained in:
		@@ -14,6 +14,8 @@
 | 
				
			|||||||
#include <iomanip>
 | 
					#include <iomanip>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <zlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ix
 | 
					namespace ix
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    HttpClient::HttpClient()
 | 
					    HttpClient::HttpClient()
 | 
				
			||||||
@@ -71,6 +73,11 @@ namespace ix
 | 
				
			|||||||
        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";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (args.compress)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ss << "Accept-Encoding: gzip" << "\r\n";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Append extra headers
 | 
					        // Append extra headers
 | 
				
			||||||
        for (auto&& it : args.extraHeaders)
 | 
					        for (auto&& it : args.extraHeaders)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -193,11 +200,13 @@ namespace ix
 | 
				
			|||||||
                {
 | 
					                {
 | 
				
			||||||
                    ss.str("");
 | 
					                    ss.str("");
 | 
				
			||||||
                    ss << "Cannot read byte";
 | 
					                    ss << "Cannot read byte";
 | 
				
			||||||
                    return std::make_tuple(-1, headers, payload, ss.str());
 | 
					                    return std::make_tuple(-1, headers, payload, "Cannot read byte");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                payload += c;
 | 
					                payload += c;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::cout << "I WAS HERE" << std::endl;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (headers.find("transfer-encoding") != headers.end() &&
 | 
					        else if (headers.find("transfer-encoding") != headers.end() &&
 | 
				
			||||||
                 headers["transfer-encoding"] == "chunked")
 | 
					                 headers["transfer-encoding"] == "chunked")
 | 
				
			||||||
@@ -264,7 +273,21 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            code = 0; // 0 ?
 | 
					            code = 0; // 0 ?
 | 
				
			||||||
            std::string errorMsg("Cannot read http body");
 | 
					            std::string errorMsg("Cannot read http body");
 | 
				
			||||||
            return std::make_tuple(code, headers, payload, errorMsg);
 | 
					            return std::make_tuple(-1, headers, payload, errorMsg);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If the content was compressed with gzip, decode it
 | 
				
			||||||
 | 
					        if (headers["Content-Encoding"] == "gzip")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (args.verbose) std::cout << "Decoding gzip..." << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::string decompressedPayload;
 | 
				
			||||||
 | 
					            if (!gzipInflate(payload, decompressedPayload))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                std::string errorMsg("Error decompressing payload");
 | 
				
			||||||
 | 
					                return std::make_tuple(-1, headers, payload, errorMsg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            payload = decompressedPayload;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return std::make_tuple(code, headers, payload, "");
 | 
					        return std::make_tuple(code, headers, payload, "");
 | 
				
			||||||
@@ -338,4 +361,53 @@ namespace ix
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return ss.str();
 | 
					        return ss.str();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool HttpClient::gzipInflate(
 | 
				
			||||||
 | 
					        const std::string& in,
 | 
				
			||||||
 | 
					        std::string& out)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        z_stream inflateState;
 | 
				
			||||||
 | 
					        memset(&inflateState, 0, sizeof(inflateState));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inflateState.zalloc = Z_NULL;
 | 
				
			||||||
 | 
					        inflateState.zfree = Z_NULL;
 | 
				
			||||||
 | 
					        inflateState.opaque = Z_NULL;
 | 
				
			||||||
 | 
					        inflateState.avail_in = 0;
 | 
				
			||||||
 | 
					        inflateState.next_in = Z_NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (inflateInit2(&inflateState, 16+MAX_WBITS) != Z_OK)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inflateState.avail_in = (uInt) in.size();
 | 
				
			||||||
 | 
					        inflateState.next_in = (unsigned char *)(const_cast<char *>(in.data()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const int kBufferSize = 1 << 14;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::unique_ptr<unsigned char[]> compressBuffer = 
 | 
				
			||||||
 | 
					            std::make_unique<unsigned char[]>(kBufferSize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            inflateState.avail_out = (uInt) kBufferSize;
 | 
				
			||||||
 | 
					            inflateState.next_out = compressBuffer.get();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int ret = inflate(&inflateState, Z_SYNC_FLUSH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (ret == Z_NEED_DICT || ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                inflateEnd(&inflateState);
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            out.append(
 | 
				
			||||||
 | 
					                reinterpret_cast<char *>(compressBuffer.get()),
 | 
				
			||||||
 | 
					                kBufferSize - inflateState.avail_out
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        } while (inflateState.avail_out == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inflateEnd(&inflateState);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,6 +30,7 @@ namespace ix
 | 
				
			|||||||
        int timeoutSecs;
 | 
					        int timeoutSecs;
 | 
				
			||||||
        bool followRedirects;
 | 
					        bool followRedirects;
 | 
				
			||||||
        bool verbose;
 | 
					        bool verbose;
 | 
				
			||||||
 | 
					        bool compress;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class HttpClient {
 | 
					    class HttpClient {
 | 
				
			||||||
@@ -54,6 +55,10 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        std::string urlEncode(const std::string& value);
 | 
					        std::string urlEncode(const std::string& value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool gzipInflate(
 | 
				
			||||||
 | 
					            const std::string& in,
 | 
				
			||||||
 | 
					            std::string& out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::shared_ptr<Socket> _socket;
 | 
					        std::shared_ptr<Socket> _socket;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,9 +57,6 @@ namespace ix
 | 
				
			|||||||
                std::string name(lineStr.substr(0, colon));
 | 
					                std::string name(lineStr.substr(0, colon));
 | 
				
			||||||
                std::string value(lineStr.substr(colon + 2, i - colon - 4));
 | 
					                std::string value(lineStr.substr(colon + 2, i - colon - 4));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Make the name lower case.
 | 
					 | 
				
			||||||
                std::transform(name.begin(), name.end(), name.begin(), ::tolower);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                headers[name] = value;
 | 
					                headers[name] = value;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,7 @@ int main(int argc, char** argv)
 | 
				
			|||||||
    bool followRedirects = false;
 | 
					    bool followRedirects = false;
 | 
				
			||||||
    bool verbose = false;
 | 
					    bool verbose = false;
 | 
				
			||||||
    bool save = false;
 | 
					    bool save = false;
 | 
				
			||||||
 | 
					    bool compress = false;
 | 
				
			||||||
    int port = 8080;
 | 
					    int port = 8080;
 | 
				
			||||||
    int connectTimeOutSeconds = 3;
 | 
					    int connectTimeOutSeconds = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -71,6 +72,7 @@ int main(int argc, char** argv)
 | 
				
			|||||||
    httpClientApp->add_flag("-L", followRedirects, "Header");
 | 
					    httpClientApp->add_flag("-L", followRedirects, "Header");
 | 
				
			||||||
    httpClientApp->add_flag("-v", verbose, "Verbose");
 | 
					    httpClientApp->add_flag("-v", verbose, "Verbose");
 | 
				
			||||||
    httpClientApp->add_flag("-O", save, "Save to disk");
 | 
					    httpClientApp->add_flag("-O", save, "Save to disk");
 | 
				
			||||||
 | 
					    httpClientApp->add_flag("--compress", compress, "gzip compression");
 | 
				
			||||||
    httpClientApp->add_option("--connect-timeout", connectTimeOutSeconds, "Connection timeout");
 | 
					    httpClientApp->add_option("--connect-timeout", connectTimeOutSeconds, "Connection timeout");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CLI11_PARSE(app, argc, argv);
 | 
					    CLI11_PARSE(app, argc, argv);
 | 
				
			||||||
@@ -114,7 +116,8 @@ int main(int argc, char** argv)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return ix::ws_http_client_main(url, headers, data,
 | 
					        return ix::ws_http_client_main(url, headers, data,
 | 
				
			||||||
                                       headersOnly, connectTimeOutSeconds,
 | 
					                                       headersOnly, connectTimeOutSeconds,
 | 
				
			||||||
                                       followRedirects, verbose, save, output);
 | 
					                                       followRedirects, verbose, save, output,
 | 
				
			||||||
 | 
					                                       compress);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 1;
 | 
					    return 1;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								ws/ws.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								ws/ws.h
									
									
									
									
									
								
							@@ -17,7 +17,8 @@ namespace ix
 | 
				
			|||||||
                            bool followRedirects,
 | 
					                            bool followRedirects,
 | 
				
			||||||
                            bool verbose,
 | 
					                            bool verbose,
 | 
				
			||||||
                            bool save,
 | 
					                            bool save,
 | 
				
			||||||
                            const std::string& output);
 | 
					                            const std::string& output,
 | 
				
			||||||
 | 
					                            bool compress);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int ws_ping_pong_main(const std::string& url);
 | 
					    int ws_ping_pong_main(const std::string& url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,8 @@ namespace ix
 | 
				
			|||||||
                            bool followRedirects,
 | 
					                            bool followRedirects,
 | 
				
			||||||
                            bool verbose,
 | 
					                            bool verbose,
 | 
				
			||||||
                            bool save,
 | 
					                            bool save,
 | 
				
			||||||
                            const std::string& output)
 | 
					                            const std::string& output,
 | 
				
			||||||
 | 
					                            bool compress)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        HttpRequestArgs args;
 | 
					        HttpRequestArgs args;
 | 
				
			||||||
        args.url = url;
 | 
					        args.url = url;
 | 
				
			||||||
@@ -98,6 +99,7 @@ namespace ix
 | 
				
			|||||||
        args.timeoutSecs = timeoutSecs;
 | 
					        args.timeoutSecs = timeoutSecs;
 | 
				
			||||||
        args.followRedirects = followRedirects;
 | 
					        args.followRedirects = followRedirects;
 | 
				
			||||||
        args.verbose = verbose;
 | 
					        args.verbose = verbose;
 | 
				
			||||||
 | 
					        args.compress = compress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        HttpParameters httpParameters = parsePostParameters(data);
 | 
					        HttpParameters httpParameters = parsePostParameters(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -127,24 +129,13 @@ namespace ix
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::cerr << "error code: " << errorCode << std::endl;
 | 
					        std::cerr << "error code: " << errorCode << std::endl;
 | 
				
			||||||
        if (!errorMsg.empty())
 | 
					        if (errorCode != 200)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::cerr << "error message: " << errorMsg << std::endl;
 | 
					            std::cerr << "error message: " << errorMsg << std::endl;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!headersOnly && errorCode == 200)
 | 
					        if (!headersOnly && errorCode == 200)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            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())
 | 
					            if (save || !output.empty())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // FIMXE we should decode the url first
 | 
					                // FIMXE we should decode the url first
 | 
				
			||||||
@@ -159,6 +150,19 @@ namespace ix
 | 
				
			|||||||
                out.write((char*)&payload.front(), payload.size());
 | 
					                out.write((char*)&payload.front(), payload.size());
 | 
				
			||||||
                out.close();
 | 
					                out.close();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                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;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user