From 569f1677ce0ba550a74619215bdb3bf5c90a3365 Mon Sep 17 00:00:00 2001 From: An Tao Date: Mon, 23 Sep 2019 18:14:58 +0800 Subject: [PATCH] Fix bug with parsing json (#253) --- lib/src/HttpRequestImpl.cc | 69 +++++++++++++++++++++++++++++++------- lib/src/HttpRequestImpl.h | 15 ++++----- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/lib/src/HttpRequestImpl.cc b/lib/src/HttpRequestImpl.cc index 0bcd3462..70da90c0 100644 --- a/lib/src/HttpRequestImpl.cc +++ b/lib/src/HttpRequestImpl.cc @@ -26,14 +26,7 @@ using namespace drogon; void HttpRequestImpl::parseParameters() const { auto input = queryView(); - if (input.empty()) - return; - std::string type = getHeaderBy("content-type"); - std::transform(type.begin(), type.end(), type.begin(), tolower); - if (_method == Get || - (_method == Post && - (type.empty() || - type.find("application/x-www-form-urlencoded") != std::string::npos))) + if (!input.empty()) { string_view::size_type pos = 0; while ((input[pos] == '?' || isspace(input[pos])) && @@ -78,12 +71,64 @@ void HttpRequestImpl::parseParameters() const } } } - if (type.find("application/json") != std::string::npos) + + input = contentView(); + if (input.empty()) + return; + std::string type = getHeaderBy("content-type"); + std::transform(type.begin(), type.end(), type.begin(), tolower); + if (type.empty() || + type.find("application/x-www-form-urlencoded") != std::string::npos) { - // parse json data in request + string_view::size_type pos = 0; + while ((input[pos] == '?' || isspace(input[pos])) && + pos < input.length()) + { + pos++; + } + auto value = input.substr(pos); + while ((pos = value.find('&')) != string_view::npos) + { + auto coo = value.substr(0, pos); + auto epos = coo.find('='); + if (epos != string_view::npos) + { + auto key = coo.substr(0, epos); + string_view::size_type cpos = 0; + while (cpos < key.length() && isspace(key[cpos])) + cpos++; + key = key.substr(cpos); + auto pvalue = coo.substr(epos + 1); + std::string pdecode = utils::urlDecode(pvalue); + std::string keydecode = utils::urlDecode(key); + _parameters[keydecode] = pdecode; + } + value = value.substr(pos + 1); + } + if (value.length() > 0) + { + auto &coo = value; + auto epos = coo.find('='); + if (epos != string_view::npos) + { + auto key = coo.substr(0, epos); + string_view::size_type cpos = 0; + while (cpos < key.length() && isspace(key[cpos])) + cpos++; + key = key.substr(cpos); + auto pvalue = coo.substr(epos + 1); + std::string pdecode = utils::urlDecode(pvalue); + std::string keydecode = utils::urlDecode(key); + _parameters[keydecode] = pdecode; + } + } + } + else if (type.find("application/json") != std::string::npos) + { + static std::once_flag once; + static Json::CharReaderBuilder builder; + std::call_once(once, []() { builder["collectComments"] = false; }); _jsonPtr = std::make_shared(); - Json::CharReaderBuilder builder; - builder["collectComments"] = false; JSONCPP_STRING errs; std::unique_ptr reader(builder.newCharReader()); if (!reader->parse(input.data(), diff --git a/lib/src/HttpRequestImpl.h b/lib/src/HttpRequestImpl.h index adaf4b7e..de5f5b67 100644 --- a/lib/src/HttpRequestImpl.h +++ b/lib/src/HttpRequestImpl.h @@ -192,17 +192,16 @@ class HttpRequestImpl : public HttpRequest string_view queryView() const { - if (!_query.empty()) - return _query; - if (_method == Post || _method == Put) - { - if (_cacheFilePtr) - return _cacheFilePtr->getStringView(); - return _content; - } return _query; } + string_view contentView() const + { + if (_cacheFilePtr) + return _cacheFilePtr->getStringView(); + return _content; + } + virtual const std::string &query() const override { return _query;