From 9ee00da431b49694360d03d45e8d184e06e696d2 Mon Sep 17 00:00:00 2001 From: An Tao Date: Sat, 14 Mar 2020 11:36:21 +0800 Subject: [PATCH] Fix crash with partial matched url (#386) --- examples/simple_example_test/main.cc | 37 ++++++++++++++++++++++- lib/inc/drogon/HttpBinder.h | 10 +++---- lib/src/HttpControllersRouter.cc | 44 +++++++++++++--------------- lib/src/HttpControllersRouter.h | 2 +- 4 files changed, 63 insertions(+), 30 deletions(-) diff --git a/examples/simple_example_test/main.cc b/examples/simple_example_test/main.cc index efdd5171..05b52b67 100644 --- a/examples/simple_example_test/main.cc +++ b/examples/simple_example_test/main.cc @@ -704,7 +704,42 @@ void doTest(const HttpClientPtr &client, exit(1); } }); - + /// Test Incomplete URL + req = HttpRequest::newHttpRequest(); + req->setMethod(drogon::Get); + req->setPath("/api/v1/handle11/11/2 2/"); + client->sendRequest( + req, [=](ReqResult result, const HttpResponsePtr &resp) { + if (result == ReqResult::Ok) + { + if (resp->getBody().find( + "int p1\n 11") != + std::string::npos && + resp->getBody().find( + "int p4\n 0") != + std::string::npos && + resp->getBody().find( + "string p2\n 2 2") != + std::string::npos && + resp->getBody().find( + "string p3\n ") != + std::string::npos) + { + outputGood(req, isHttps); + } + else + { + LOG_DEBUG << resp->getBody(); + LOG_ERROR << "Error!"; + exit(1); + } + } + else + { + LOG_ERROR << "Error!"; + exit(1); + } + }); /// Test lambda req = HttpRequest::newHttpRequest(); req->setMethod(drogon::Get); diff --git a/lib/inc/drogon/HttpBinder.h b/lib/inc/drogon/HttpBinder.h index b930cd11..9b179c14 100644 --- a/lib/inc/drogon/HttpBinder.h +++ b/lib/inc/drogon/HttpBinder.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -67,7 +67,7 @@ class HttpBinderBase { public: virtual void handleHttpRequest( - std::list &pathArguments, + std::deque &pathArguments, const HttpRequestPtr &req, std::function &&callback) = 0; virtual size_t paramCount() = 0; @@ -95,7 +95,7 @@ class HttpBinder : public HttpBinderBase public: using FunctionType = FUNCTION; virtual void handleHttpRequest( - std::list &pathArguments, + std::deque &pathArguments, const HttpRequestPtr &req, std::function &&callback) override { @@ -215,7 +215,7 @@ class HttpBinder : public HttpBinderBase template typename std::enable_if<(sizeof...(Values) < Boundary), void>::type run( - std::list &pathArguments, + std::deque &pathArguments, const HttpRequestPtr &req, std::function &&callback, Values &&... values) @@ -265,7 +265,7 @@ class HttpBinder : public HttpBinderBase } template typename std::enable_if<(sizeof...(Values) == Boundary), void>::type run( - std::list &, + std::deque &, const HttpRequestPtr &req, std::function &&callback, Values &&... values) diff --git a/lib/src/HttpControllersRouter.cc b/lib/src/HttpControllersRouter.cc index 59df70ed..74e7d667 100644 --- a/lib/src/HttpControllersRouter.cc +++ b/lib/src/HttpControllersRouter.cc @@ -21,6 +21,7 @@ #include "FiltersFunction.h" #include #include +#include using namespace drogon; @@ -241,7 +242,7 @@ void HttpControllersRouter::addHttpPath( } tmpPath = results.suffix(); } - std::map parametersPlaces; + std::vector> parametersPlaces; if (!paras.empty()) { std::regex pregex("([^&]*)=\\{([^&]*)\\}&*"); @@ -282,7 +283,7 @@ void HttpControllersRouter::addHttpPath( LOG_ERROR << "Path pattern: " << path; exit(1); } - parametersPlaces[results[1].str()] = place; + parametersPlaces.emplace_back(results[1].str(), place); } else { @@ -320,7 +321,7 @@ void HttpControllersRouter::addHttpPath( LOG_ERROR << "Path pattern: " << path; exit(1); } - parametersPlaces[results[1].str()] = place; + parametersPlaces.emplace_back(results[1].str(), place); } else { @@ -343,7 +344,8 @@ void HttpControllersRouter::addHttpPath( LOG_ERROR << "Path pattern: " << path; exit(1); } - parametersPlaces[results[1].str()] = placeIndex; + parametersPlaces.emplace_back(results[1].str(), + placeIndex); } } ++placeIndex; @@ -554,7 +556,7 @@ void HttpControllersRouter::doControllerHandler( } } - std::vector params(ctrlBinderPtr->parameterPlaces_.size()); + std::deque params(ctrlBinderPtr->parameterPlaces_.size()); for (size_t j = 1; j < matchResult.size(); ++j) { @@ -571,31 +573,27 @@ void HttpControllersRouter::doControllerHandler( LOG_TRACE << "place=" << place << " para:" << params[place - 1]; } - if (ctrlBinderPtr->queryParametersPlaces_.size() > 0) + if (!ctrlBinderPtr->queryParametersPlaces_.empty()) { - auto qureyPara = req->getParameters(); - for (auto const ¶meter : qureyPara) + auto &queryPara = req->getParameters(); + for (auto const ¶Place : ctrlBinderPtr->queryParametersPlaces_) { - if (ctrlBinderPtr->queryParametersPlaces_.find(parameter.first) != - ctrlBinderPtr->queryParametersPlaces_.end()) + auto place = paraPlace.second; + if (place > params.size()) + params.resize(place); + auto iter = queryPara.find(paraPlace.first); + if (iter != queryPara.end()) { - auto place = - ctrlBinderPtr->queryParametersPlaces_.find(parameter.first) - ->second; - if (place > params.size()) - params.resize(place); - params[place - 1] = parameter.second; + params[place - 1] = iter->second; + } + else + { + params[place - 1] = std::string{}; } } } - std::list paraList; - for (auto &p : params) /// Use reference - { - LOG_TRACE << p; - paraList.push_back(std::move(p)); - } ctrlBinderPtr->binderPtr_->handleHttpRequest( - paraList, + params, req, [=, callback = std::move(callback)](const HttpResponsePtr &resp) { if (resp->expiredTime() >= 0 && resp->statusCode() != k404NotFound) diff --git a/lib/src/HttpControllersRouter.h b/lib/src/HttpControllersRouter.h index 7286dbf2..3b19610e 100644 --- a/lib/src/HttpControllersRouter.h +++ b/lib/src/HttpControllersRouter.h @@ -83,7 +83,7 @@ class HttpControllersRouter : public trantor::NonCopyable std::vector filterNames_; std::vector> filters_; std::vector parameterPlaces_; - std::map queryParametersPlaces_; + std::vector> queryParametersPlaces_; IOThreadStorage responseCache_; bool isCORS_{false}; };