Fix crash with partial matched url (#386)

This commit is contained in:
An Tao 2020-03-14 11:36:21 +08:00 committed by GitHub
parent 2d87434bfb
commit 9ee00da431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 30 deletions

View File

@ -704,7 +704,42 @@ void doTest(const HttpClientPtr &client,
exit(1); 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(
"<td>int p1</td>\n <td>11</td>") !=
std::string::npos &&
resp->getBody().find(
"<td>int p4</td>\n <td>0</td>") !=
std::string::npos &&
resp->getBody().find(
"<td>string p2</td>\n <td>2 2</td>") !=
std::string::npos &&
resp->getBody().find(
"<td>string p3</td>\n <td></td>") !=
std::string::npos)
{
outputGood(req, isHttps);
}
else
{
LOG_DEBUG << resp->getBody();
LOG_ERROR << "Error!";
exit(1);
}
}
else
{
LOG_ERROR << "Error!";
exit(1);
}
});
/// Test lambda /// Test lambda
req = HttpRequest::newHttpRequest(); req = HttpRequest::newHttpRequest();
req->setMethod(drogon::Get); req->setMethod(drogon::Get);

View File

@ -21,7 +21,7 @@
#include <drogon/DrObject.h> #include <drogon/DrObject.h>
#include <drogon/utils/FunctionTraits.h> #include <drogon/utils/FunctionTraits.h>
#include <drogon/HttpRequest.h> #include <drogon/HttpRequest.h>
#include <list> #include <deque>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include <string> #include <string>
@ -67,7 +67,7 @@ class HttpBinderBase
{ {
public: public:
virtual void handleHttpRequest( virtual void handleHttpRequest(
std::list<std::string> &pathArguments, std::deque<std::string> &pathArguments,
const HttpRequestPtr &req, const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) = 0; std::function<void(const HttpResponsePtr &)> &&callback) = 0;
virtual size_t paramCount() = 0; virtual size_t paramCount() = 0;
@ -95,7 +95,7 @@ class HttpBinder : public HttpBinderBase
public: public:
using FunctionType = FUNCTION; using FunctionType = FUNCTION;
virtual void handleHttpRequest( virtual void handleHttpRequest(
std::list<std::string> &pathArguments, std::deque<std::string> &pathArguments,
const HttpRequestPtr &req, const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback) override std::function<void(const HttpResponsePtr &)> &&callback) override
{ {
@ -215,7 +215,7 @@ class HttpBinder : public HttpBinderBase
template <typename... Values, std::size_t Boundary = argument_count> template <typename... Values, std::size_t Boundary = argument_count>
typename std::enable_if<(sizeof...(Values) < Boundary), void>::type run( typename std::enable_if<(sizeof...(Values) < Boundary), void>::type run(
std::list<std::string> &pathArguments, std::deque<std::string> &pathArguments,
const HttpRequestPtr &req, const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback, std::function<void(const HttpResponsePtr &)> &&callback,
Values &&... values) Values &&... values)
@ -265,7 +265,7 @@ class HttpBinder : public HttpBinderBase
} }
template <typename... Values, std::size_t Boundary = argument_count> template <typename... Values, std::size_t Boundary = argument_count>
typename std::enable_if<(sizeof...(Values) == Boundary), void>::type run( typename std::enable_if<(sizeof...(Values) == Boundary), void>::type run(
std::list<std::string> &, std::deque<std::string> &,
const HttpRequestPtr &req, const HttpRequestPtr &req,
std::function<void(const HttpResponsePtr &)> &&callback, std::function<void(const HttpResponsePtr &)> &&callback,
Values &&... values) Values &&... values)

View File

@ -21,6 +21,7 @@
#include "FiltersFunction.h" #include "FiltersFunction.h"
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <deque>
using namespace drogon; using namespace drogon;
@ -241,7 +242,7 @@ void HttpControllersRouter::addHttpPath(
} }
tmpPath = results.suffix(); tmpPath = results.suffix();
} }
std::map<std::string, size_t> parametersPlaces; std::vector<std::pair<std::string, size_t>> parametersPlaces;
if (!paras.empty()) if (!paras.empty())
{ {
std::regex pregex("([^&]*)=\\{([^&]*)\\}&*"); std::regex pregex("([^&]*)=\\{([^&]*)\\}&*");
@ -282,7 +283,7 @@ void HttpControllersRouter::addHttpPath(
LOG_ERROR << "Path pattern: " << path; LOG_ERROR << "Path pattern: " << path;
exit(1); exit(1);
} }
parametersPlaces[results[1].str()] = place; parametersPlaces.emplace_back(results[1].str(), place);
} }
else else
{ {
@ -320,7 +321,7 @@ void HttpControllersRouter::addHttpPath(
LOG_ERROR << "Path pattern: " << path; LOG_ERROR << "Path pattern: " << path;
exit(1); exit(1);
} }
parametersPlaces[results[1].str()] = place; parametersPlaces.emplace_back(results[1].str(), place);
} }
else else
{ {
@ -343,7 +344,8 @@ void HttpControllersRouter::addHttpPath(
LOG_ERROR << "Path pattern: " << path; LOG_ERROR << "Path pattern: " << path;
exit(1); exit(1);
} }
parametersPlaces[results[1].str()] = placeIndex; parametersPlaces.emplace_back(results[1].str(),
placeIndex);
} }
} }
++placeIndex; ++placeIndex;
@ -554,7 +556,7 @@ void HttpControllersRouter::doControllerHandler(
} }
} }
std::vector<std::string> params(ctrlBinderPtr->parameterPlaces_.size()); std::deque<std::string> params(ctrlBinderPtr->parameterPlaces_.size());
for (size_t j = 1; j < matchResult.size(); ++j) for (size_t j = 1; j < matchResult.size(); ++j)
{ {
@ -571,31 +573,27 @@ void HttpControllersRouter::doControllerHandler(
LOG_TRACE << "place=" << place << " para:" << params[place - 1]; LOG_TRACE << "place=" << place << " para:" << params[place - 1];
} }
if (ctrlBinderPtr->queryParametersPlaces_.size() > 0) if (!ctrlBinderPtr->queryParametersPlaces_.empty())
{ {
auto qureyPara = req->getParameters(); auto &queryPara = req->getParameters();
for (auto const &parameter : qureyPara) for (auto const &paraPlace : ctrlBinderPtr->queryParametersPlaces_)
{ {
if (ctrlBinderPtr->queryParametersPlaces_.find(parameter.first) != auto place = paraPlace.second;
ctrlBinderPtr->queryParametersPlaces_.end()) if (place > params.size())
params.resize(place);
auto iter = queryPara.find(paraPlace.first);
if (iter != queryPara.end())
{ {
auto place = params[place - 1] = iter->second;
ctrlBinderPtr->queryParametersPlaces_.find(parameter.first) }
->second; else
if (place > params.size()) {
params.resize(place); params[place - 1] = std::string{};
params[place - 1] = parameter.second;
} }
} }
} }
std::list<std::string> paraList;
for (auto &p : params) /// Use reference
{
LOG_TRACE << p;
paraList.push_back(std::move(p));
}
ctrlBinderPtr->binderPtr_->handleHttpRequest( ctrlBinderPtr->binderPtr_->handleHttpRequest(
paraList, params,
req, req,
[=, callback = std::move(callback)](const HttpResponsePtr &resp) { [=, callback = std::move(callback)](const HttpResponsePtr &resp) {
if (resp->expiredTime() >= 0 && resp->statusCode() != k404NotFound) if (resp->expiredTime() >= 0 && resp->statusCode() != k404NotFound)

View File

@ -83,7 +83,7 @@ class HttpControllersRouter : public trantor::NonCopyable
std::vector<std::string> filterNames_; std::vector<std::string> filterNames_;
std::vector<std::shared_ptr<HttpFilterBase>> filters_; std::vector<std::shared_ptr<HttpFilterBase>> filters_;
std::vector<size_t> parameterPlaces_; std::vector<size_t> parameterPlaces_;
std::map<std::string, size_t> queryParametersPlaces_; std::vector<std::pair<std::string, size_t>> queryParametersPlaces_;
IOThreadStorage<HttpResponsePtr> responseCache_; IOThreadStorage<HttpResponsePtr> responseCache_;
bool isCORS_{false}; bool isCORS_{false};
}; };