improve some websocket error messages + add a utility function with unittest to parse status line and stop using scanf which triggers warnings on Windows
This commit is contained in:
parent
6c0890594b
commit
64d3c99f99
@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
|
|||||||
## [6.2.0] - 2019-09-09
|
## [6.2.0] - 2019-09-09
|
||||||
|
|
||||||
- websocket and http server: server does not close the bound client socket in many cases
|
- websocket and http server: server does not close the bound client socket in many cases
|
||||||
|
- improve some websocket error messages
|
||||||
|
- add a utility function with unittest to parse status line and stop using scanf which triggers warnings on Windows
|
||||||
|
|
||||||
## [6.1.0] - 2019-09-08
|
## [6.1.0] - 2019-09-08
|
||||||
|
|
||||||
|
@ -27,6 +27,36 @@ namespace ix
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<std::string, int> Http::parseStatusLine(const std::string& line)
|
||||||
|
{
|
||||||
|
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF
|
||||||
|
std::string token;
|
||||||
|
std::stringstream tokenStream(line);
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
|
||||||
|
// Split by ' '
|
||||||
|
while (std::getline(tokenStream, token, ' '))
|
||||||
|
{
|
||||||
|
tokens.push_back(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string httpVersion;
|
||||||
|
if (tokens.size() >= 1)
|
||||||
|
{
|
||||||
|
httpVersion = trim(tokens[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int statusCode = -1;
|
||||||
|
if (tokens.size() >= 2)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << trim(tokens[1]);
|
||||||
|
ss >> statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_pair(httpVersion, statusCode);
|
||||||
|
}
|
||||||
|
|
||||||
std::tuple<std::string, std::string, std::string> Http::parseRequestLine(const std::string& line)
|
std::tuple<std::string, std::string, std::string> Http::parseRequestLine(const std::string& line)
|
||||||
{
|
{
|
||||||
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF
|
// Request-Line = Method SP Request-URI SP HTTP-Version CRLF
|
||||||
|
@ -115,6 +115,8 @@ namespace ix
|
|||||||
std::shared_ptr<Socket> socket);
|
std::shared_ptr<Socket> socket);
|
||||||
static bool sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket);
|
static bool sendResponse(HttpResponsePtr response, std::shared_ptr<Socket> socket);
|
||||||
|
|
||||||
|
static std::pair<std::string, int> parseStatusLine(
|
||||||
|
const std::string& line);
|
||||||
static std::tuple<std::string, std::string, std::string> parseRequestLine(
|
static std::tuple<std::string, std::string, std::string> parseRequestLine(
|
||||||
const std::string& line);
|
const std::string& line);
|
||||||
static std::string trim(const std::string& str);
|
static std::string trim(const std::string& str);
|
||||||
|
@ -164,20 +164,23 @@ namespace ix
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate status
|
// Validate status
|
||||||
int status;
|
auto statusLine = Http::parseStatusLine(line);
|
||||||
|
std::string httpVersion = statusLine.first;
|
||||||
|
int status = statusLine.second;
|
||||||
|
|
||||||
// HTTP/1.0 is too old.
|
// HTTP/1.0 is too old.
|
||||||
if (sscanf(line.c_str(), "HTTP/1.0 %d", &status) == 1)
|
if (httpVersion != "HTTP/1.1")
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Server version is HTTP/1.0. Rejecting connection to " << host
|
ss << "Expecting HTTP/1.1, got " << httpVersion << ". "
|
||||||
|
<< "Rejecting connection to " << host
|
||||||
<< ", status: " << status
|
<< ", 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
|
// We want an 101 HTTP status
|
||||||
if (sscanf(line.c_str(), "HTTP/1.1 %d", &status) != 1 || status != 101)
|
if (status != 101)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Got bad status connecting to " << host
|
ss << "Got bad status connecting to " << host
|
||||||
@ -295,9 +298,15 @@ namespace ix
|
|||||||
return sendErrorResponse(400, "Missing Sec-WebSocket-Key value");
|
return sendErrorResponse(400, "Missing Sec-WebSocket-Key value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headers.find("upgrade") == headers.end())
|
||||||
|
{
|
||||||
|
return sendErrorResponse(400, "Missing Upgrade header");
|
||||||
|
}
|
||||||
|
|
||||||
if (!insensitiveStringCompare(headers["upgrade"], "WebSocket"))
|
if (!insensitiveStringCompare(headers["upgrade"], "WebSocket"))
|
||||||
{
|
{
|
||||||
return sendErrorResponse(400, "Invalid or missing Upgrade header");
|
return sendErrorResponse(400, "Invalid Upgrade header, "
|
||||||
|
"need WebSocket, got " + headers["upgrade"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.find("sec-websocket-version") == headers.end())
|
if (headers.find("sec-websocket-version") == headers.end())
|
||||||
@ -314,7 +323,7 @@ namespace ix
|
|||||||
if (version != 13)
|
if (version != 13)
|
||||||
{
|
{
|
||||||
return sendErrorResponse(400, "Invalid Sec-WebSocket-Version, "
|
return sendErrorResponse(400, "Invalid Sec-WebSocket-Version, "
|
||||||
"need 13, got" + ss.str());
|
"need 13, got " + ss.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,8 +681,12 @@ namespace ix
|
|||||||
reason = WebSocketCloseConstants::kInvalidFramePayloadDataMessage;
|
reason = WebSocketCloseConstants::kInvalidFramePayloadDataMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// Validate close codes. Autobahn 7.9.*
|
// Validate close codes. Autobahn 7.9.*
|
||||||
// 1014, 1015 are debattable. The firefox MSDN has a description for them
|
// 1014, 1015 are debattable. The firefox MSDN has a description for them.
|
||||||
|
// Full list of status code and status range is defined in the dedicated
|
||||||
|
// RFC section at https://tools.ietf.org/html/rfc6455#page-45
|
||||||
|
//
|
||||||
if (code < 1000 || code == 1004 || code == 1006 ||
|
if (code < 1000 || code == 1004 || code == 1006 ||
|
||||||
(code > 1013 && code < 3000))
|
(code > 1013 && code < 3000))
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,7 @@ set (SOURCES
|
|||||||
IXHttpClientTest.cpp
|
IXHttpClientTest.cpp
|
||||||
IXHttpServerTest.cpp
|
IXHttpServerTest.cpp
|
||||||
IXUnityBuildsTest.cpp
|
IXUnityBuildsTest.cpp
|
||||||
|
IXHttpTest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Some unittest don't work on windows yet
|
# Some unittest don't work on windows yet
|
||||||
|
Loading…
Reference in New Issue
Block a user