diff --git a/CMakeLists.txt b/CMakeLists.txt index 84e7124f8..f032a5418 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") endif() -option(PISTACHE_BUILD_TESTS "build tests alongside the project" OFF) +option(PISTACHE_BUILD_TESTS "build tests alongside the project" ON) option(PISTACHE_ENABLE_NETWORK_TESTS "if tests are built, run ones needing network access" ON) option(PISTACHE_BUILD_EXAMPLES "build examples alongside the project" OFF) option(PISTACHE_BUILD_DOCS "build docs alongside the project" OFF) diff --git a/include/pistache/http.h b/include/pistache/http.h index bb6172ffe..209ab7fdc 100644 --- a/include/pistache/http.h +++ b/include/pistache/http.h @@ -100,6 +100,7 @@ namespace Uri { Query(std::initializer_list> params); void add(std::string name, std::string value); + void update(std::string& name, std::string value); Optional get(const std::string& name) const; bool has(const std::string& name) const; // Return empty string or "?key1=value1&key2=value2" if query exist @@ -163,6 +164,7 @@ class Request : public Message { const Header::Collection& headers() const; const Uri::Query& query() const; + const std::vector>& rawParams() const; const CookieJar& cookies() const; @@ -198,6 +200,7 @@ class Request : public Message { Method method_; std::string resource_; Uri::Query query_; + std::vector> raw_params_; #ifdef LIBSTDCPP_SMARTPTR_LOCK_FIXME std::weak_ptr peer_; diff --git a/src/common/http.cc b/src/common/http.cc index e67e186b9..2d7b4bab0 100644 --- a/src/common/http.cc +++ b/src/common/http.cc @@ -166,8 +166,10 @@ namespace Private { auto c = cursor.current(); if (c == ' ') { + request->raw_params_.emplace_back(std::make_pair(std::string(key), std::string())); request->query_.add(std::move(key), ""); } else if (c == '&') { + request->raw_params_.emplace_back(std::make_pair(std::string(key), std::string())); request->query_.add(std::move(key), ""); if (!cursor.advance(1)) return State::Again; } @@ -179,7 +181,14 @@ namespace Private { return State::Again; std::string value = valueToken.text(); - request->query_.add(std::move(key), std::move(value)); + request->raw_params_.emplace_back(std::make_pair(std::string(key), std::string(value))); + if (!request->query_.has(key)) { + request->query_.add(std::move(key), std::move(value)); + } else { + std::string newValue = request->query_.get(key).get(); + newValue += "," + value; + request->query_.update(key, std::move(newValue)); + } if (cursor.current() == '&') { if (!cursor.advance(1)) return State::Again; } @@ -499,6 +508,11 @@ namespace Uri { params.insert(std::make_pair(std::move(name), std::move(value))); } + void + Query::update(std::string& name, std::string value) { + params[name] = std::move(value); + } + Optional Query::get(const std::string& name) const { auto it = params.find(name); @@ -559,6 +573,11 @@ Request::query() const { return query_; } +const std::vector>& +Request::rawParams() const { + return raw_params_; +} + const CookieJar& Request::cookies() const { return cookies_;