mirror of
https://github.com/drogonframework/drogon.git
synced 2025-07-19 00:00:43 -04:00
Compare commits
3 Commits
269399b701
...
61073b4f74
Author | SHA1 | Date | |
---|---|---|---|
|
61073b4f74 | ||
|
eea916315e | ||
|
8e4474bf4c |
@ -151,7 +151,7 @@ class DROGON_EXPORT HttpClient : public trantor::NonCopyable
|
|||||||
*
|
*
|
||||||
* @param req
|
* @param req
|
||||||
* @param timeout In seconds. If the response is not received within the
|
* @param timeout In seconds. If the response is not received within the
|
||||||
* timeout, A `std::runtime_error` with the message "Timeout" is thrown.
|
* timeout, A `drogon::HttpException` with `ReqResult::Timeout` is thrown.
|
||||||
* The zero value by default disables the timeout.
|
* The zero value by default disables the timeout.
|
||||||
*
|
*
|
||||||
* @return internal::HttpRespAwaiter. Await on it to get the response
|
* @return internal::HttpRespAwaiter. Await on it to get the response
|
||||||
@ -346,6 +346,29 @@ class DROGON_EXPORT HttpClient : public trantor::NonCopyable
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cpp_impl_coroutine
|
#ifdef __cpp_impl_coroutine
|
||||||
|
|
||||||
|
class HttpException : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HttpException() = delete;
|
||||||
|
explicit HttpException(ReqResult res)
|
||||||
|
: resultCode_(res), message_(to_string_view(res))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const char *what() const noexcept override
|
||||||
|
{
|
||||||
|
return message_.data();
|
||||||
|
}
|
||||||
|
ReqResult code() const
|
||||||
|
{
|
||||||
|
return resultCode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReqResult resultCode_;
|
||||||
|
std::string_view message_;
|
||||||
|
};
|
||||||
|
|
||||||
inline void internal::HttpRespAwaiter::await_suspend(
|
inline void internal::HttpRespAwaiter::await_suspend(
|
||||||
std::coroutine_handle<> handle)
|
std::coroutine_handle<> handle)
|
||||||
{
|
{
|
||||||
@ -353,17 +376,11 @@ inline void internal::HttpRespAwaiter::await_suspend(
|
|||||||
assert(req_ != nullptr);
|
assert(req_ != nullptr);
|
||||||
client_->sendRequest(
|
client_->sendRequest(
|
||||||
req_,
|
req_,
|
||||||
[handle = std::move(handle), this](ReqResult result,
|
[handle, this](ReqResult result, const HttpResponsePtr &resp) {
|
||||||
const HttpResponsePtr &resp) {
|
|
||||||
if (result == ReqResult::Ok)
|
if (result == ReqResult::Ok)
|
||||||
setValue(resp);
|
setValue(resp);
|
||||||
else
|
else
|
||||||
{
|
setException(std::make_exception_ptr(HttpException(result)));
|
||||||
std::stringstream ss;
|
|
||||||
ss << result;
|
|
||||||
setException(
|
|
||||||
std::make_exception_ptr(std::runtime_error(ss.str())));
|
|
||||||
}
|
|
||||||
handle.resume();
|
handle.resume();
|
||||||
},
|
},
|
||||||
timeout_);
|
timeout_);
|
||||||
|
@ -353,6 +353,9 @@ class DROGON_EXPORT HttpResponse
|
|||||||
/// Create a normal response with a status code of 200ok and a content type
|
/// Create a normal response with a status code of 200ok and a content type
|
||||||
/// of text/html.
|
/// of text/html.
|
||||||
static HttpResponsePtr newHttpResponse();
|
static HttpResponsePtr newHttpResponse();
|
||||||
|
/// Create a response with a status code and a content type
|
||||||
|
static HttpResponsePtr newHttpResponse(HttpStatusCode code,
|
||||||
|
ContentType type);
|
||||||
/// Create a response which returns a 404 page.
|
/// Create a response which returns a 404 page.
|
||||||
static HttpResponsePtr newNotFoundResponse();
|
static HttpResponsePtr newNotFoundResponse();
|
||||||
/// Create a response which returns a json object. Its content type is set
|
/// Create a response which returns a json object. Its content type is set
|
||||||
|
@ -60,6 +60,9 @@ namespace utils
|
|||||||
/// Determine if the string is an integer
|
/// Determine if the string is an integer
|
||||||
DROGON_EXPORT bool isInteger(const std::string &str);
|
DROGON_EXPORT bool isInteger(const std::string &str);
|
||||||
|
|
||||||
|
/// Determine if the string is base64 encoded
|
||||||
|
DROGON_EXPORT bool isBase64(const std::string &str);
|
||||||
|
|
||||||
/// Generate random a string
|
/// Generate random a string
|
||||||
/**
|
/**
|
||||||
* @param length The string length
|
* @param length The string length
|
||||||
@ -98,15 +101,46 @@ DROGON_EXPORT std::set<std::string> splitStringToSet(
|
|||||||
/// Get UUID string.
|
/// Get UUID string.
|
||||||
DROGON_EXPORT std::string getUuid();
|
DROGON_EXPORT std::string getUuid();
|
||||||
|
|
||||||
|
/// Get the encoded length of base64.
|
||||||
|
DROGON_EXPORT size_t base64EncodedLength(unsigned int in_len,
|
||||||
|
bool padded = true);
|
||||||
|
|
||||||
/// Encode the string to base64 format.
|
/// Encode the string to base64 format.
|
||||||
DROGON_EXPORT std::string base64Encode(const unsigned char *bytes_to_encode,
|
DROGON_EXPORT std::string base64Encode(const unsigned char *bytes_to_encode,
|
||||||
unsigned int in_len,
|
unsigned int in_len,
|
||||||
bool url_safe = false);
|
bool url_safe = false,
|
||||||
|
bool padded = true);
|
||||||
|
|
||||||
|
/// Encode the string to base64 format.
|
||||||
|
inline std::string base64Encode(string_view data,
|
||||||
|
bool url_safe = false,
|
||||||
|
bool padded = true)
|
||||||
|
{
|
||||||
|
return base64Encode((unsigned char *)data.data(),
|
||||||
|
data.size(),
|
||||||
|
url_safe,
|
||||||
|
padded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encode the string to base64 format with no padding.
|
||||||
|
DROGON_EXPORT std::string base64EncodeUnpadded(
|
||||||
|
const unsigned char *bytes_to_encode,
|
||||||
|
unsigned int in_len,
|
||||||
|
bool url_safe = false);
|
||||||
|
|
||||||
|
/// Encode the string to base64 format with no padding.
|
||||||
|
inline std::string base64EncodeUnpadded(string_view data, bool url_safe = false)
|
||||||
|
{
|
||||||
|
return base64Encode(data, url_safe, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the decoded length of base64.
|
||||||
|
DROGON_EXPORT size_t base64DecodedLength(unsigned int in_len);
|
||||||
|
|
||||||
/// Decode the base64 format string.
|
/// Decode the base64 format string.
|
||||||
DROGON_EXPORT std::string base64Decode(const std::string &encoded_string);
|
DROGON_EXPORT std::string base64Decode(string_view encoded_string);
|
||||||
DROGON_EXPORT std::vector<char> base64DecodeToVector(
|
DROGON_EXPORT std::vector<char> base64DecodeToVector(
|
||||||
const std::string &encoded_string);
|
string_view encoded_string);
|
||||||
|
|
||||||
/// Check if the string need decoding
|
/// Check if the string need decoding
|
||||||
DROGON_EXPORT bool needUrlDecoding(const char *begin, const char *end);
|
DROGON_EXPORT bool needUrlDecoding(const char *begin, const char *end);
|
||||||
|
@ -71,6 +71,14 @@ HttpResponsePtr HttpResponse::newHttpResponse()
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpResponsePtr HttpResponse::newHttpResponse(HttpStatusCode code,
|
||||||
|
ContentType type)
|
||||||
|
{
|
||||||
|
auto res = std::make_shared<HttpResponseImpl>(code, type);
|
||||||
|
doResponseCreateAdvices(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
HttpResponsePtr HttpResponse::newHttpJsonResponse(const Json::Value &data)
|
HttpResponsePtr HttpResponse::newHttpJsonResponse(const Json::Value &data)
|
||||||
{
|
{
|
||||||
auto res = std::make_shared<HttpResponseImpl>(k200OK, CT_APPLICATION_JSON);
|
auto res = std::make_shared<HttpResponseImpl>(k200OK, CT_APPLICATION_JSON);
|
||||||
|
@ -149,6 +149,14 @@ bool isInteger(const std::string &str)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isBase64(const std::string &str)
|
||||||
|
{
|
||||||
|
for (auto c : str)
|
||||||
|
if (!isBase64(c))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string genRandomString(int length)
|
std::string genRandomString(int length)
|
||||||
{
|
{
|
||||||
static const char char_space[] =
|
static const char char_space[] =
|
||||||
@ -387,11 +395,18 @@ std::string getUuid()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t base64EncodedLength(unsigned int in_len, bool padded)
|
||||||
|
{
|
||||||
|
return padded ? ((in_len + 3 - 1) / 3) * 4 : (in_len * 8 + 6 - 1) / 6;
|
||||||
|
}
|
||||||
|
|
||||||
std::string base64Encode(const unsigned char *bytes_to_encode,
|
std::string base64Encode(const unsigned char *bytes_to_encode,
|
||||||
unsigned int in_len,
|
unsigned int in_len,
|
||||||
bool url_safe)
|
bool url_safe,
|
||||||
|
bool padded)
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
ret.reserve(base64EncodedLength(in_len, padded));
|
||||||
int i = 0;
|
int i = 0;
|
||||||
unsigned char char_array_3[3];
|
unsigned char char_array_3[3];
|
||||||
unsigned char char_array_4[4];
|
unsigned char char_array_4[4];
|
||||||
@ -428,27 +443,45 @@ std::string base64Encode(const unsigned char *bytes_to_encode,
|
|||||||
((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||||
|
|
||||||
for (int j = 0; (j < i + 1); ++j)
|
for (int j = 0; (j <= i); ++j)
|
||||||
ret += charSet[char_array_4[j]];
|
ret += charSet[char_array_4[j]];
|
||||||
|
|
||||||
while ((i++ < 3))
|
if (padded)
|
||||||
ret += '=';
|
while ((++i < 4))
|
||||||
|
ret += '=';
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<char> base64DecodeToVector(const std::string &encoded_string)
|
std::string base64EncodeUnpadded(const unsigned char *bytes_to_encode,
|
||||||
|
unsigned int in_len,
|
||||||
|
bool url_safe)
|
||||||
|
{
|
||||||
|
return base64Encode(bytes_to_encode, in_len, url_safe, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t base64DecodedLength(unsigned int in_len)
|
||||||
|
{
|
||||||
|
return (in_len * 3) / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<char> base64DecodeToVector(string_view encoded_string)
|
||||||
{
|
{
|
||||||
auto in_len = encoded_string.size();
|
auto in_len = encoded_string.size();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int in_{0};
|
int in_{0};
|
||||||
char char_array_4[4], char_array_3[3];
|
char char_array_4[4], char_array_3[3];
|
||||||
std::vector<char> ret;
|
std::vector<char> ret;
|
||||||
ret.reserve(in_len);
|
ret.reserve(base64DecodedLength(in_len));
|
||||||
|
|
||||||
while (in_len-- && (encoded_string[in_] != '=') &&
|
while (in_len-- && (encoded_string[in_] != '='))
|
||||||
isBase64(encoded_string[in_]))
|
|
||||||
{
|
{
|
||||||
|
if (!isBase64(encoded_string[in_]))
|
||||||
|
{
|
||||||
|
++in_;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
char_array_4[i++] = encoded_string[in_];
|
char_array_4[i++] = encoded_string[in_];
|
||||||
++in_;
|
++in_;
|
||||||
if (i == 4)
|
if (i == 4)
|
||||||
@ -486,24 +519,31 @@ std::vector<char> base64DecodeToVector(const std::string &encoded_string)
|
|||||||
((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||||
|
|
||||||
for (int j = 0; (j < i - 1); ++j)
|
--i;
|
||||||
|
for (int j = 0; (j < i); ++j)
|
||||||
ret.push_back(char_array_3[j]);
|
ret.push_back(char_array_3[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string base64Decode(const std::string &encoded_string)
|
std::string base64Decode(string_view encoded_string)
|
||||||
{
|
{
|
||||||
auto in_len = encoded_string.size();
|
auto in_len = encoded_string.size();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int in_{0};
|
int in_{0};
|
||||||
unsigned char char_array_4[4], char_array_3[3];
|
unsigned char char_array_4[4], char_array_3[3];
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
ret.reserve(base64DecodedLength(in_len));
|
||||||
|
|
||||||
while (in_len-- && (encoded_string[in_] != '=') &&
|
while (in_len-- && (encoded_string[in_] != '='))
|
||||||
isBase64(encoded_string[in_]))
|
|
||||||
{
|
{
|
||||||
|
if (!isBase64(encoded_string[in_]))
|
||||||
|
{
|
||||||
|
++in_;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
char_array_4[i++] = encoded_string[in_];
|
char_array_4[i++] = encoded_string[in_];
|
||||||
++in_;
|
++in_;
|
||||||
if (i == 4)
|
if (i == 4)
|
||||||
@ -540,7 +580,8 @@ std::string base64Decode(const std::string &encoded_string)
|
|||||||
((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||||
|
|
||||||
for (int j = 0; (j < i - 1); ++j)
|
--i;
|
||||||
|
for (int j = 0; (j < i); ++j)
|
||||||
ret += char_array_3[j];
|
ret += char_array_3[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,34 @@
|
|||||||
DROGON_TEST(Base64)
|
DROGON_TEST(Base64)
|
||||||
{
|
{
|
||||||
std::string in{"drogon framework"};
|
std::string in{"drogon framework"};
|
||||||
auto encoded = drogon::utils::base64Encode((const unsigned char *)in.data(),
|
auto encoded = drogon::utils::base64Encode(in);
|
||||||
(unsigned int)in.length());
|
|
||||||
auto decoded = drogon::utils::base64Decode(encoded);
|
auto decoded = drogon::utils::base64Decode(encoded);
|
||||||
CHECK(encoded == "ZHJvZ29uIGZyYW1ld29yaw==");
|
CHECK(encoded == "ZHJvZ29uIGZyYW1ld29yaw==");
|
||||||
CHECK(decoded == in);
|
CHECK(decoded == in);
|
||||||
|
|
||||||
|
SUBSECTION(InvalidChars)
|
||||||
|
{
|
||||||
|
auto decoded =
|
||||||
|
drogon::utils::base64Decode("ZHJvZ2*9uIGZy**YW1ld2***9yaw*=*=");
|
||||||
|
CHECK(decoded == in);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBSECTION(InvalidCharsNoPadding)
|
||||||
|
{
|
||||||
|
auto decoded =
|
||||||
|
drogon::utils::base64Decode("ZHJvZ2*9uIGZy**YW1ld2***9yaw**");
|
||||||
|
CHECK(decoded == in);
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBSECTION(Unpadded)
|
||||||
|
{
|
||||||
|
std::string in{"drogon framework"};
|
||||||
|
auto encoded = drogon::utils::base64EncodeUnpadded(in);
|
||||||
|
auto decoded = drogon::utils::base64Decode(encoded);
|
||||||
|
CHECK(encoded == "ZHJvZ29uIGZyYW1ld29yaw");
|
||||||
|
CHECK(decoded == in);
|
||||||
|
}
|
||||||
|
|
||||||
SUBSECTION(LongString)
|
SUBSECTION(LongString)
|
||||||
{
|
{
|
||||||
std::string in;
|
std::string in;
|
||||||
@ -19,12 +41,9 @@ DROGON_TEST(Base64)
|
|||||||
{
|
{
|
||||||
in.append(1, char(i));
|
in.append(1, char(i));
|
||||||
}
|
}
|
||||||
auto out = drogon::utils::base64Encode((const unsigned char *)in.data(),
|
auto out = drogon::utils::base64Encode(in);
|
||||||
(unsigned int)in.length());
|
|
||||||
auto out2 = drogon::utils::base64Decode(out);
|
auto out2 = drogon::utils::base64Decode(out);
|
||||||
auto encoded =
|
auto encoded = drogon::utils::base64Encode(in);
|
||||||
drogon::utils::base64Encode((const unsigned char *)in.data(),
|
|
||||||
(unsigned int)in.length());
|
|
||||||
auto decoded = drogon::utils::base64Decode(encoded);
|
auto decoded = drogon::utils::base64Decode(encoded);
|
||||||
CHECK(decoded == in);
|
CHECK(decoded == in);
|
||||||
}
|
}
|
||||||
@ -32,15 +51,21 @@ DROGON_TEST(Base64)
|
|||||||
SUBSECTION(URLSafe)
|
SUBSECTION(URLSafe)
|
||||||
{
|
{
|
||||||
std::string in{"drogon framework"};
|
std::string in{"drogon framework"};
|
||||||
auto encoded =
|
auto encoded = drogon::utils::base64Encode(in, true);
|
||||||
drogon::utils::base64Encode((const unsigned char *)in.data(),
|
|
||||||
(unsigned int)in.length(),
|
|
||||||
true);
|
|
||||||
auto decoded = drogon::utils::base64Decode(encoded);
|
auto decoded = drogon::utils::base64Decode(encoded);
|
||||||
CHECK(encoded == "ZHJvZ29uIGZyYW1ld29yaw==");
|
CHECK(encoded == "ZHJvZ29uIGZyYW1ld29yaw==");
|
||||||
CHECK(decoded == in);
|
CHECK(decoded == in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SUBSECTION(UnpaddedURLSafe)
|
||||||
|
{
|
||||||
|
std::string in{"drogon framework"};
|
||||||
|
auto encoded = drogon::utils::base64EncodeUnpadded(in, true);
|
||||||
|
auto decoded = drogon::utils::base64Decode(encoded);
|
||||||
|
CHECK(encoded == "ZHJvZ29uIGZyYW1ld29yaw");
|
||||||
|
CHECK(decoded == in);
|
||||||
|
}
|
||||||
|
|
||||||
SUBSECTION(LongURLSafe)
|
SUBSECTION(LongURLSafe)
|
||||||
{
|
{
|
||||||
std::string in;
|
std::string in;
|
||||||
@ -49,10 +74,7 @@ DROGON_TEST(Base64)
|
|||||||
{
|
{
|
||||||
in.append(1, char(i));
|
in.append(1, char(i));
|
||||||
}
|
}
|
||||||
auto encoded =
|
auto encoded = drogon::utils::base64Encode(in, true);
|
||||||
drogon::utils::base64Encode((const unsigned char *)in.data(),
|
|
||||||
(unsigned int)in.length(),
|
|
||||||
true);
|
|
||||||
auto decoded = drogon::utils::base64Decode(encoded);
|
auto decoded = drogon::utils::base64Decode(encoded);
|
||||||
CHECK(decoded == in);
|
CHECK(decoded == in);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user