diff --git a/lib/inc/drogon/HttpRequest.h b/lib/inc/drogon/HttpRequest.h index f3c4dbee..679cf6cd 100644 --- a/lib/inc/drogon/HttpRequest.h +++ b/lib/inc/drogon/HttpRequest.h @@ -245,6 +245,11 @@ class HttpRequest /// Set or get the content type virtual void setContentTypeCode(const ContentType type) = 0; + /// Set the request content-type string, The string + /// must contain the header name and CRLF. + /// For example, "content-type: text/plain\r\n" + virtual void setCustomContentTypeString(const std::string &type) = 0; + /// Add a cookie virtual void addCookie(const std::string &key, const std::string &value) = 0; diff --git a/lib/inc/drogon/utils/Utilities.h b/lib/inc/drogon/utils/Utilities.h index 19f34dd8..f27e67c0 100644 --- a/lib/inc/drogon/utils/Utilities.h +++ b/lib/inc/drogon/utils/Utilities.h @@ -72,7 +72,9 @@ inline std::string urlDecode(const string_view &szToDecode) auto begin = szToDecode.data(); return urlDecode(begin, begin + szToDecode.length()); } -std::string urlEncode(const std::string &str); + +std::string urlEncode(const std::string &); +std::string urlEncodeComponent(const std::string &); /// Commpress or decompress data using gzip lib. /** diff --git a/lib/src/HttpRequestImpl.cc b/lib/src/HttpRequestImpl.cc index 70da90c0..460d0f54 100644 --- a/lib/src/HttpRequestImpl.cc +++ b/lib/src/HttpRequestImpl.cc @@ -187,13 +187,12 @@ void HttpRequestImpl::appendToBuffer(trantor::MsgBuffer *output) const { for (auto const &p : _parameters) { - content.append(p.first); + content.append(utils::urlEncodeComponent(p.first)); content.append("="); - content.append(p.second); + content.append(utils::urlEncodeComponent(p.second)); content.append("&"); } content.resize(content.length() - 1); - content = utils::urlEncode(content); if (_method == Get || _method == Delete || _method == Head) { auto ret = std::find(output->peek(), diff --git a/lib/src/HttpRequestImpl.h b/lib/src/HttpRequestImpl.h index 635b04ae..9607ac66 100644 --- a/lib/src/HttpRequestImpl.h +++ b/lib/src/HttpRequestImpl.h @@ -355,7 +355,11 @@ class HttpRequestImpl : public HttpRequest parseParametersOnce(); return _jsonPtr; } - + virtual void setCustomContentTypeString(const std::string &type) override + { + _contentType = CT_NONE; + _contentTypeString = type; + } virtual void setContentTypeCode(const ContentType type) override { _contentType = type; diff --git a/lib/src/Utilities.cc b/lib/src/Utilities.cc index 9714b120..d0aaba1e 100644 --- a/lib/src/Utilities.cc +++ b/lib/src/Utilities.cc @@ -352,7 +352,102 @@ static std::string charToHex(char c) return result; } +std::string urlEncodeComponent(const std::string &src) +{ + std::string result; + std::string::const_iterator iter; + for (iter = src.begin(); iter != src.end(); ++iter) + { + switch (*iter) + { + case ' ': + result.append(1, '+'); + break; + // alnum + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // mark + case '-': + case '_': + case '.': + case '!': + case '~': + case '*': + case '(': + case ')': + result.append(1, *iter); + break; + // escape + default: + result.append(1, '%'); + result.append(charToHex(*iter)); + break; + } + } + + return result; +} std::string urlEncode(const std::string &src) { std::string result;