(ixwebsocket client) handle HTTP redirects
This commit is contained in:
		@@ -2,6 +2,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
All changes to this project will be documented in this file.
 | 
					All changes to this project will be documented in this file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [10.2.0] - 2020-08-14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(ixwebsocket client) handle HTTP redirects
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## [10.2.0] - 2020-08-13
 | 
					## [10.2.0] - 2020-08-13
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(ws) upgrade to latest version of nlohmann json (3.9.1 from 3.2.0)
 | 
					(ws) upgrade to latest version of nlohmann json (3.9.1 from 3.2.0)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -170,20 +170,11 @@ namespace ix
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            std::stringstream ss;
 | 
					            std::stringstream ss;
 | 
				
			||||||
            ss << "Expecting HTTP/1.1, got " << httpVersion << ". "
 | 
					            ss << "Expecting HTTP/1.1, got " << httpVersion << ". "
 | 
				
			||||||
               << "Rejecting connection to " << host << ":" << port << ", status: " << status
 | 
					               << "Rejecting connection to " << url << ", status: " << status
 | 
				
			||||||
               << ", HTTP Status line: " << line;
 | 
					               << ", HTTP Status line: " << line;
 | 
				
			||||||
            return WebSocketInitResult(false, status, ss.str());
 | 
					            return WebSocketInitResult(false, status, ss.str());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // We want an 101 HTTP status
 | 
					 | 
				
			||||||
        if (status != 101)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            std::stringstream ss;
 | 
					 | 
				
			||||||
            ss << "Expecting status 101 (Switching Protocol), got " << status
 | 
					 | 
				
			||||||
               << " status connecting to " << host << ":" << port << ", HTTP Status line: " << line;
 | 
					 | 
				
			||||||
            return WebSocketInitResult(false, status, ss.str());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto result = parseHttpHeaders(_socket, isCancellationRequested);
 | 
					        auto result = parseHttpHeaders(_socket, isCancellationRequested);
 | 
				
			||||||
        auto headersValid = result.first;
 | 
					        auto headersValid = result.first;
 | 
				
			||||||
        auto headers = result.second;
 | 
					        auto headers = result.second;
 | 
				
			||||||
@@ -193,6 +184,17 @@ namespace ix
 | 
				
			|||||||
            return WebSocketInitResult(false, status, "Error parsing HTTP headers");
 | 
					            return WebSocketInitResult(false, status, "Error parsing HTTP headers");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // We want an 101 HTTP status for websocket, otherwise it could be
 | 
				
			||||||
 | 
					        // a redirection (like 301)
 | 
				
			||||||
 | 
					        if (status != 101)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            std::stringstream ss;
 | 
				
			||||||
 | 
					            ss << "Expecting status 101 (Switching Protocol), got " << status
 | 
				
			||||||
 | 
					               << " status connecting to " << url << ", HTTP Status line: " << line;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return WebSocketInitResult(false, status, ss.str(), headers, path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Check the presence of the connection field
 | 
					        // Check the presence of the connection field
 | 
				
			||||||
        if (headers.find("connection") == headers.end())
 | 
					        if (headers.find("connection") == headers.end())
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,36 +107,62 @@ namespace ix
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        std::string protocol, host, path, query;
 | 
					        std::string protocol, host, path, query;
 | 
				
			||||||
        int port;
 | 
					        int port;
 | 
				
			||||||
 | 
					        std::string remoteUrl(url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!UrlParser::parse(url, protocol, host, path, query, port))
 | 
					        WebSocketInitResult result;
 | 
				
			||||||
 | 
					        const int maxRedirections = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < maxRedirections; ++i)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            std::stringstream ss;
 | 
					            if (!UrlParser::parse(remoteUrl, protocol, host, path, query, port))
 | 
				
			||||||
            ss << "Could not parse url: '" << url << "'";
 | 
					            {
 | 
				
			||||||
            return WebSocketInitResult(false, 0, ss.str());
 | 
					                std::stringstream ss;
 | 
				
			||||||
 | 
					                ss << "Could not parse url: '" << url << "'";
 | 
				
			||||||
 | 
					                return WebSocketInitResult(false, 0, ss.str());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::string errorMsg;
 | 
				
			||||||
 | 
					            bool tls = protocol == "wss";
 | 
				
			||||||
 | 
					            _socket = createSocket(tls, -1, errorMsg, _socketTLSOptions);
 | 
				
			||||||
 | 
					            _perMessageDeflate = std::make_unique<WebSocketPerMessageDeflate>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!_socket)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return WebSocketInitResult(false, 0, errorMsg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            WebSocketHandshake webSocketHandshake(_requestInitCancellation,
 | 
				
			||||||
 | 
					                                                  _socket,
 | 
				
			||||||
 | 
					                                                  _perMessageDeflate,
 | 
				
			||||||
 | 
					                                                  _perMessageDeflateOptions,
 | 
				
			||||||
 | 
					                                                  _enablePerMessageDeflate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            result = webSocketHandshake.clientHandshake(
 | 
				
			||||||
 | 
					                remoteUrl, headers, host, path, port, timeoutSecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (result.http_status >= 300 && result.http_status < 400)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                auto it = result.headers.find("Location");
 | 
				
			||||||
 | 
					                if (it == result.headers.end())
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    std::stringstream ss;
 | 
				
			||||||
 | 
					                    ss << "Missing Location Header for HTTP Redirect response. "
 | 
				
			||||||
 | 
					                       << "Rejecting connection to " << url << ", status: " << result.http_status;
 | 
				
			||||||
 | 
					                    result.errorStr = ss.str();
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                remoteUrl = it->second;
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (result.success)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                setReadyState(ReadyState::OPEN);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string errorMsg;
 | 
					 | 
				
			||||||
        bool tls = protocol == "wss";
 | 
					 | 
				
			||||||
        _socket = createSocket(tls, -1, errorMsg, _socketTLSOptions);
 | 
					 | 
				
			||||||
        _perMessageDeflate = std::make_unique<WebSocketPerMessageDeflate>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!_socket)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return WebSocketInitResult(false, 0, errorMsg);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        WebSocketHandshake webSocketHandshake(_requestInitCancellation,
 | 
					 | 
				
			||||||
                                              _socket,
 | 
					 | 
				
			||||||
                                              _perMessageDeflate,
 | 
					 | 
				
			||||||
                                              _perMessageDeflateOptions,
 | 
					 | 
				
			||||||
                                              _enablePerMessageDeflate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        auto result =
 | 
					 | 
				
			||||||
            webSocketHandshake.clientHandshake(url, headers, host, path, port, timeoutSecs);
 | 
					 | 
				
			||||||
        if (result.success)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            setReadyState(ReadyState::OPEN);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return result;
 | 
					        return result;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,4 +6,4 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IX_WEBSOCKET_VERSION "10.2.0"
 | 
					#define IX_WEBSOCKET_VERSION "10.2.1"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user