(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. | ||||
|  | ||||
| ## [10.2.0] - 2020-08-14 | ||||
|  | ||||
| (ixwebsocket client) handle HTTP redirects | ||||
|  | ||||
| ## [10.2.0] - 2020-08-13 | ||||
|  | ||||
| (ws) upgrade to latest version of nlohmann json (3.9.1 from 3.2.0) | ||||
|   | ||||
| @@ -170,20 +170,11 @@ namespace ix | ||||
|         { | ||||
|             std::stringstream ss; | ||||
|             ss << "Expecting HTTP/1.1, got " << httpVersion << ". " | ||||
|                << "Rejecting connection to " << host << ":" << port << ", status: " << status | ||||
|                << "Rejecting connection to " << url << ", status: " << status | ||||
|                << ", HTTP Status line: " << line; | ||||
|             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 headersValid = result.first; | ||||
|         auto headers = result.second; | ||||
| @@ -193,6 +184,17 @@ namespace ix | ||||
|             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 | ||||
|         if (headers.find("connection") == headers.end()) | ||||
|         { | ||||
|   | ||||
| @@ -107,36 +107,62 @@ namespace ix | ||||
|  | ||||
|         std::string protocol, host, path, query; | ||||
|         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; | ||||
|             ss << "Could not parse url: '" << url << "'"; | ||||
|             return WebSocketInitResult(false, 0, ss.str()); | ||||
|             if (!UrlParser::parse(remoteUrl, protocol, host, path, query, port)) | ||||
|             { | ||||
|                 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; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -6,4 +6,4 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #define IX_WEBSOCKET_VERSION "10.2.0" | ||||
| #define IX_WEBSOCKET_VERSION "10.2.1" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user