From ad847f00529926a2aff64766ee96e39ea65db221 Mon Sep 17 00:00:00 2001 From: Fred Nicolson Date: Fri, 26 Jan 2018 13:18:45 +0000 Subject: [PATCH] HTTP parsing bug fixes, added tests Fixed HTTP request parse failing if the URI was too short. Fixed HTTP parser not converting POST/GET data to lowercase before storing it, making post and get data which contained capitals impossible to access. --- src/HttpRequest.cpp | 12 +++++++----- src/TcpSocket.cpp | 2 +- tests/HttpRequestTest.cpp | 26 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/HttpRequest.cpp b/src/HttpRequest.cpp index ddf1eee..a3b21e8 100644 --- a/src/HttpRequest.cpp +++ b/src/HttpRequest.cpp @@ -171,7 +171,10 @@ namespace fr //Split up the body and store each argument name and value auto post = parse_argument_list(body.substr(post_begin, body.size() - post_begin - (body.size() - post_end))); for(auto &c : post) + { + std::transform(c.first.begin(), c.first.end(), c.first.begin(), ::tolower); post_data.emplace(std::move(c.first), std::move(c.second)); + } } void HttpRequest::parse_header_type(const std::string &str) @@ -205,22 +208,21 @@ namespace fr auto uri_end = str.find("HTTP") - 1; if(uri_begin != std::string::npos) { - //Extract URI - std::string uri = str.substr(uri_begin, uri_end - uri_begin); - //Parse GET variables auto get_begin = str.find('?'); if(get_begin != std::string::npos) { auto get_vars = parse_argument_list(str.substr(get_begin, uri_end - get_begin)); for(auto &c : get_vars) + { + std::transform(c.first.begin(), c.first.end(), c.first.begin(), ::tolower); get_data.emplace(std::move(c.first), std::move(c.second)); + } set_uri(str.substr(uri_begin, get_begin - uri_begin)); - uri.erase(get_begin, uri.size() - get_begin); } else { - set_uri(uri); + set_uri(str.substr(uri_begin, uri_end - uri_begin)); } return; } diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp index e251a8e..7890cab 100644 --- a/src/TcpSocket.cpp +++ b/src/TcpSocket.cpp @@ -139,7 +139,7 @@ namespace fr //Verify that we're connected socklen_t len = sizeof(ret); - if(getsockopt(socket_descriptor, SOL_SOCKET, SO_ERROR, &ret, &len) == -1) + if(getsockopt(socket_descriptor, SOL_SOCKET, SO_ERROR, (char*)&ret, &len) == -1) continue; if(ret != 0) continue; diff --git a/tests/HttpRequestTest.cpp b/tests/HttpRequestTest.cpp index 0dc225d..bcb0dc3 100644 --- a/tests/HttpRequestTest.cpp +++ b/tests/HttpRequestTest.cpp @@ -185,4 +185,30 @@ TEST(HttpRequestTest, partial_parse) ASSERT_EQ(request.get_type(), fr::Http::Get); ASSERT_EQ(request.header("content-type"), "application/x-www-form-urlencoded"); ASSERT_EQ(request.header("Cache-Control"), "no-cache"); +} + +TEST(HttpRequestTest, awkward_parse) +{ + std::string request_data = "" + "POST /my/url? HTTP/1.1\n" + "\n" + "Test=bob\n" + "\n"; + fr::HttpRequest request; + ASSERT_EQ(request.parse(request_data.c_str(), request_data.size()), fr::Socket::Success); + ASSERT_EQ(request.get_uri(), "/my/url"); + ASSERT_EQ(request.post("Test"), "bob"); +} + +TEST(HttpRequestTest, awkward_parse2) +{ + std::string request_data = "POST /my/url?Bob=10 HTTP/1.1\n" + "\n" + "Test=bob"; + + fr::HttpRequest request; + ASSERT_EQ(request.parse(request_data.c_str(), request_data.size()), fr::Socket::Success); + ASSERT_EQ(request.get_uri(), "/my/url"); + ASSERT_EQ(request.get("Bob"), "10"); + ASSERT_EQ(request.post("Test"), "bob"); } \ No newline at end of file