From 0bd41ec6bd67a4df84f2a2612d1b952c153bea9c Mon Sep 17 00:00:00 2001 From: Fred Nicolson Date: Wed, 2 Aug 2017 17:32:16 +0100 Subject: [PATCH] get_remote_address() now works on SSL sockets accepted through SSLListener Post/get/... data is no longer case insensitive. --- include/frnetlib/Http.h | 13 ++++++------- src/Http.cpp | 38 ++++++++++++++++---------------------- src/SSLListener.cpp | 20 ++++++++++++++++++-- tests/HttpRequestTest.cpp | 18 +++++++++--------- 4 files changed, 49 insertions(+), 40 deletions(-) diff --git a/include/frnetlib/Http.h b/include/frnetlib/Http.h index 09a3299..1a542a3 100644 --- a/include/frnetlib/Http.h +++ b/include/frnetlib/Http.h @@ -138,7 +138,7 @@ namespace fr * @param key The name of the GET variable * @return A reference to the GET variable */ - std::string &get(std::string &&key); + std::string &get(const std::string &key); /*! * Returns a reference to a POST variable. @@ -149,7 +149,7 @@ namespace fr * @param key The name of the POST variable * @return A reference to the POST variable */ - std::string &post(std::string &&key); + std::string &post(const std::string &key); /*! * Returns a reference to a header. @@ -160,7 +160,7 @@ namespace fr * @param key The name of the header * @return A reference to the header */ - std::string &header(std::string &&key); + std::string &header(const std::string &key); /*! @@ -169,7 +169,7 @@ namespace fr * @param key The name of the GET variable * @return True if it does. False otherwise. */ - bool get_exists(std::string &&key) const; + bool get_exists(const std::string &key) const; /*! * Checks to see if a given POST variable exists @@ -177,16 +177,15 @@ namespace fr * @param key The name of the POST variable * @return True if it does. False otherwise. */ - bool post_exists(std::string &&key) const; + bool post_exists(const std::string &key) const; /*! * Checks to see if a given header exists. - * Note: key will be converted to lower case * * @param key The name of the header * @return True if it does. False otherwise. */ - bool header_exists(std::string &&key) const; + bool header_exists(const std::string &key) const; /*! * Returns the requested URI diff --git a/src/Http.cpp b/src/Http.cpp index 2f35733..ce24504 100644 --- a/src/Http.cpp +++ b/src/Http.cpp @@ -48,30 +48,37 @@ namespace fr body = body_; } - std::string &Http::get(std::string &&key) + std::string &Http::get(const std::string &key) { - std::transform(key.begin(), key.end(), key.begin(), ::tolower); return get_data[key]; } - std::string &Http::post(std::string &&key) + std::string &Http::post(const std::string &key) { - std::transform(key.begin(), key.end(), key.begin(), ::tolower); return post_data[key]; } - bool Http::get_exists(std::string &&key) const + bool Http::get_exists(const std::string &key) const { - std::transform(key.begin(), key.end(), key.begin(), ::tolower); return get_data.find(key) != get_data.end(); } - bool Http::post_exists(std::string &&key) const + bool Http::post_exists(const std::string &key) const { - std::transform(key.begin(), key.end(), key.begin(), ::tolower); return post_data.find(key) != post_data.end(); } + std::string &Http::header(const std::string &key) + { + return header_data[key]; + } + + bool Http::header_exists(const std::string &key) const + { + return header_data.find(key) != header_data.end(); + } + + const std::string &Http::get_uri() const { return uri; @@ -155,18 +162,6 @@ namespace fr return result; } - std::string &Http::header(std::string &&key) - { - std::transform(key.begin(), key.end(), key.begin(), ::tolower); - return header_data[key]; - } - - bool Http::header_exists(std::string &&key) const - { - std::transform(key.begin(), key.end(), key.begin(), ::tolower); - return header_data.find(key) != header_data.end(); - } - std::vector> Http::parse_argument_list(const std::string &str) { std::vector> list; @@ -228,8 +223,7 @@ namespace fr } std::string header_name = str.substr(0, colon_pos); std::string header_value = str.substr(data_begin, data_len); - - std::transform(header_name.begin(), header_name.end(), header_name.begin(), ::tolower); + header_data.emplace(std::move(header_name), std::move(header_value)); } diff --git a/src/SSLListener.cpp b/src/SSLListener.cpp index e6db304..f629723 100644 --- a/src/SSLListener.cpp +++ b/src/SSLListener.cpp @@ -4,7 +4,8 @@ #include #include -#include +#include "frnetlib/NetworkEncoding.h" +#include "frnetlib/TcpListener.h" #include "frnetlib/SSLListener.h" #ifdef SSL_ENABLED @@ -110,7 +111,9 @@ namespace fr } //Accept a connection - if((error = mbedtls_net_accept(&listen_fd, client_fd.get(), nullptr, 0, nullptr)) != 0) + char client_ip[INET6_ADDRSTRLEN] = {0}; + size_t ip_len = 0; + if((error = mbedtls_net_accept(&listen_fd, client_fd.get(), client_ip, sizeof(client_ip), &ip_len)) != 0) { std::cout << "Accept error: " << error << std::endl; free_contexts(); @@ -130,8 +133,21 @@ namespace fr } } + //Get remote address and port. We could get the IP from the accept args, but we also want the port + //Which mbedtls doesn't provide + //Get printable address. If we failed then set it as just 'unknown' + char client_printable_addr[INET6_ADDRSTRLEN]; + struct sockaddr_storage socket_address{}; + socklen_t socket_length; + error = getpeername(client_fd->fd, (struct sockaddr*)&socket_address, &socket_length); + if(error == 0) + error = getnameinfo((sockaddr*)&socket_address, socket_length, client_printable_addr, sizeof(client_printable_addr), nullptr,0,NI_NUMERICHOST); + if(error != 0) + strcpy(client_printable_addr, "unknown"); + client.set_ssl_context(std::move(ssl)); client.set_net_context(std::move(client_fd)); + client.set_remote_address(client_printable_addr); return Socket::Success; } diff --git a/tests/HttpRequestTest.cpp b/tests/HttpRequestTest.cpp index e80343f..3783019 100644 --- a/tests/HttpRequestTest.cpp +++ b/tests/HttpRequestTest.cpp @@ -23,16 +23,16 @@ TEST(HttpRequestTest, get_request_parse) ASSERT_EQ(request.get_uri(), "/index.html"); //Test that headers exist - ASSERT_EQ(request.header_exists("host"), true); - ASSERT_EQ(request.header_exists("contEnt-type"), true); - ASSERT_EQ(request.header_exists("my-HeadEr"), true); - ASSERT_EQ(request.header_exists("my-other-header"), true); - ASSERT_EQ(request.header_exists("cache-control"), true); + ASSERT_EQ(request.header_exists("Host"), true); + ASSERT_EQ(request.header_exists("Content-Type"), true); + ASSERT_EQ(request.header_exists("My-Header"), true); + ASSERT_EQ(request.header_exists("My-Other-Header"), true); + ASSERT_EQ(request.header_exists("Cache-Control"), true); ASSERT_EQ(request.header_exists("non-existant"), false); //Check that headers are intact - ASSERT_EQ(request.header("host"), "frednicolson.co.uk"); - ASSERT_EQ(request.header("content-type"), "application/x-www-form-urlencoded"); + ASSERT_EQ(request.header("Host"), "frednicolson.co.uk"); + ASSERT_EQ(request.header("Content-Type"), "application/x-www-form-urlencoded"); ASSERT_EQ(request.header("My-Other-Header"), "header2"); ASSERT_EQ(request.header("My-Header"), "header1"); @@ -66,11 +66,11 @@ TEST(HttpRequestTest, post_request_parse) //Parse code is the same for GET, so skip header checks. Test if POST data exists. ASSERT_EQ(request.post_exists("post_data"), true); - ASSERT_EQ(request.post_exists("some_mOre_posT_data"), true); + ASSERT_EQ(request.post_exists("some_more_post_data"), true); ASSERT_EQ(request.post_exists("non_existant"), false); //Check that the POST data is valid - ASSERT_EQ(request.post("post_dAta"), "data1"); + ASSERT_EQ(request.post("post_data"), "data1"); ASSERT_EQ(request.post("some_more_post_data"), "data23"); }