From 0c9cb000b45f20e16f304bc57942f6d0e42c1d35 Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 3 Jul 2017 11:44:46 +0200 Subject: [PATCH] Server::Request::path is split into path and query_string --- server_http.hpp | 42 +++++++++++++++++++++++++++--------------- tests/io_test.cpp | 17 +++++++++++++++++ tests/parse_test.cpp | 13 ++++--------- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/server_http.hpp b/server_http.hpp index 7862835..f3e5848 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -155,7 +155,7 @@ namespace SimpleWeb { friend class Server; public: - std::string method, path, http_version; + std::string method, path, query_string, http_version; Content content; @@ -168,11 +168,7 @@ namespace SimpleWeb { /// Returns query keys with percent-decoded values. CaseInsensitiveMultimap parse_query_string() { - auto pos = path.find('?'); - if(pos != std::string::npos && pos + 1 < path.size()) - return SimpleWeb::QueryString::parse(path.substr(pos + 1)); - else - return CaseInsensitiveMultimap(); + return SimpleWeb::QueryString::parse(query_string); } private: @@ -382,14 +378,29 @@ namespace SimpleWeb { getline(request->content, line); size_t method_end; if((method_end = line.find(' ')) != std::string::npos) { - size_t path_end; - if((path_end = line.find(' ', method_end + 1)) != std::string::npos) { - request->method = line.substr(0, method_end); - request->path = line.substr(method_end + 1, path_end - method_end - 1); + request->method = line.substr(0, method_end); + + size_t query_start = std::string::npos; + size_t path_and_query_string_end = std::string::npos; + for(size_t i = method_end + 1; i < line.size(); ++i) { + if(line[i] == '?' && (i + 1) < line.size()) + query_start = i + 1; + else if(line[i] == ' ') { + path_and_query_string_end = i; + break; + } + } + if(path_and_query_string_end != std::string::npos) { + if(query_start != std::string::npos) { + request->path = line.substr(method_end + 1, query_start - method_end - 2); + request->query_string = line.substr(query_start, path_and_query_string_end - query_start); + } + else + request->path = line.substr(method_end + 1, path_and_query_string_end - method_end - 1); size_t protocol_end; - if((protocol_end = line.find('/', path_end + 1)) != std::string::npos) { - if(line.compare(path_end + 1, protocol_end - path_end - 1, "HTTP") != 0) + if((protocol_end = line.find('/', path_and_query_string_end + 1)) != std::string::npos) { + if(line.compare(path_and_query_string_end + 1, protocol_end - path_and_query_string_end - 1, "HTTP") != 0) return false; request->http_version = line.substr(protocol_end + 1, line.size() - protocol_end - 2); } @@ -400,7 +411,7 @@ namespace SimpleWeb { size_t param_end; while((param_end = line.find(':')) != std::string::npos) { size_t value_start = param_end + 1; - if((value_start) < line.size()) { + if(value_start < line.size()) { if(line[value_start] == ' ') value_start++; if(value_start < line.size()) @@ -418,7 +429,8 @@ namespace SimpleWeb { return true; } - void find_resource(const std::shared_ptr &socket, const std::shared_ptr &request) { + void + find_resource(const std::shared_ptr &socket, const std::shared_ptr &request) { //Upgrade connection if(on_upgrade) { auto it = request->header.find("Upgrade"); @@ -486,7 +498,7 @@ namespace SimpleWeb { return; } } - }; + }; // namespace SimpleWeb template class Server : public ServerBase {}; diff --git a/tests/io_test.cpp b/tests/io_test.cpp index d0d75ef..5803d6b 100644 --- a/tests/io_test.cpp +++ b/tests/io_test.cpp @@ -57,6 +57,15 @@ int main() { << content; }; + server.resource["^/query_string$"]["GET"] = [](shared_ptr response, shared_ptr request) { + assert(request->path == "/query_string"); + assert(request->query_string == "testing"); + auto queries = request->parse_query_string(); + auto it = queries.find("Testing"); + assert(it != queries.end() && it->first == "testing" && it->second == ""); + response->write(request->query_string); + }; + thread server_thread([&server]() { //Start server server.start(); @@ -163,6 +172,14 @@ int main() { assert(client.connections->size() == 1); assert(connection == client.connections->front().get()); } + + { + stringstream output; + auto r = client.request("GET", "/query_string?testing"); + assert(r->content.string() == "testing"); + assert(client.connections->size() == 1); + assert(connection == client.connections->front().get()); + } } { diff --git a/tests/parse_test.cpp b/tests/parse_test.cpp index cfb38bc..a08a478 100644 --- a/tests/parse_test.cpp +++ b/tests/parse_test.cpp @@ -152,27 +152,22 @@ int main() { asio::ip::tcp::socket socket(io_service); SimpleWeb::Server::Request request(socket); { - request.path = "/?"; + request.query_string = ""; auto queries = request.parse_query_string(); assert(queries.empty()); } { - request.path = "/"; + request.query_string = "="; auto queries = request.parse_query_string(); assert(queries.empty()); } { - request.path = "/?="; + request.query_string = "=test"; auto queries = request.parse_query_string(); assert(queries.empty()); } { - request.path = "/?=test"; - auto queries = request.parse_query_string(); - assert(queries.empty()); - } - { - request.path = "/?a=1%202%20%203&b=3+4&c&d=æ%25ø%26å%3F"; + request.query_string = "a=1%202%20%203&b=3+4&c&d=æ%25ø%26å%3F"; auto queries = request.parse_query_string(); { auto range = queries.equal_range("a");