asio: Make redirect_handler use passed uri as is and percent-encode path part
This commit is contained in:
parent
6020b727d8
commit
c64bb62ffe
|
@ -49,22 +49,15 @@ std::string create_html(int status_code) {
|
|||
} // namespace
|
||||
|
||||
namespace {
|
||||
request_cb redirect_handler(int status_code, std::string path) {
|
||||
return [status_code, path](const request &req, const response &res) {
|
||||
auto &uref = req.impl().uri();
|
||||
auto newloc = uref.scheme;
|
||||
newloc += "://";
|
||||
newloc += uref.host;
|
||||
newloc += path;
|
||||
if (!uref.raw_query.empty()) {
|
||||
newloc += "?";
|
||||
newloc += uref.raw_query;
|
||||
}
|
||||
auto html = create_html(status_code);
|
||||
request_cb redirect_handler(int status_code, std::string uri) {
|
||||
return [status_code, uri](const request &req, const response &res) {
|
||||
header_map h;
|
||||
h.emplace("location", header_value{std::move(newloc)});
|
||||
h.emplace("location", header_value{std::move(uri)});
|
||||
std::string html;
|
||||
if (req.method() == "GET") {
|
||||
html = create_html(status_code);
|
||||
}
|
||||
h.emplace("content-length", header_value{util::utos(html.size())});
|
||||
h.emplace("content-type", header_value{"text/html; charset=utf-8"});
|
||||
|
||||
res.write_head(status_code, std::move(h));
|
||||
res.end(std::move(html));
|
||||
|
@ -131,7 +124,14 @@ request_cb serve_mux::handler(request_impl &req) const {
|
|||
auto clean_path = ::nghttp2::http2::path_join(
|
||||
nullptr, 0, nullptr, 0, path.c_str(), path.size(), nullptr, 0);
|
||||
if (clean_path != path) {
|
||||
return redirect_handler(301, std::move(clean_path));
|
||||
auto new_uri = util::percent_encode_path(clean_path);
|
||||
auto &uref = req.uri();
|
||||
if (!uref.raw_query.empty()) {
|
||||
new_uri += "?";
|
||||
new_uri += uref.raw_query;
|
||||
}
|
||||
|
||||
return redirect_handler(301, std::move(new_uri));
|
||||
}
|
||||
}
|
||||
auto &host = req.uri().host;
|
||||
|
|
|
@ -126,6 +126,8 @@ int main(int argc, char *argv[]) {
|
|||
!CU_add_test(pSuite, "util_to_token68", shrpx::test_util_to_token68) ||
|
||||
!CU_add_test(pSuite, "util_percent_encode_token",
|
||||
shrpx::test_util_percent_encode_token) ||
|
||||
!CU_add_test(pSuite, "util_percent_encode_path",
|
||||
shrpx::test_util_percent_encode_path) ||
|
||||
!CU_add_test(pSuite, "util_percent_decode",
|
||||
shrpx::test_util_percent_decode) ||
|
||||
!CU_add_test(pSuite, "util_quote_string",
|
||||
|
|
22
src/util.cc
22
src/util.cc
|
@ -70,6 +70,13 @@ bool inRFC3986UnreservedChars(const char c) {
|
|||
std::find(&unreserved[0], &unreserved[4], c) != &unreserved[4];
|
||||
}
|
||||
|
||||
bool in_rfc3986_sub_delims(const char c) {
|
||||
static const char sub_delims[] = {'!', '$', '&', '\'', '(', ')',
|
||||
'*', '+', ',', ';', '='};
|
||||
return std::find(std::begin(sub_delims), std::end(sub_delims), c) !=
|
||||
std::end(sub_delims);
|
||||
}
|
||||
|
||||
std::string percentEncode(const unsigned char *target, size_t len) {
|
||||
std::string dest;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
|
@ -91,6 +98,21 @@ std::string percentEncode(const std::string &target) {
|
|||
target.size());
|
||||
}
|
||||
|
||||
std::string percent_encode_path(const std::string &s) {
|
||||
std::string dest;
|
||||
for (auto c : s) {
|
||||
if (inRFC3986UnreservedChars(c) || in_rfc3986_sub_delims(c) || c == '/') {
|
||||
dest += c;
|
||||
continue;
|
||||
}
|
||||
|
||||
dest += "%";
|
||||
dest += UPPER_XDIGITS[(c >> 4) & 0x0f];
|
||||
dest += UPPER_XDIGITS[(c & 0x0f)];
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
bool in_token(char c) {
|
||||
static const char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+',
|
||||
'-', '.', '^', '_', '`', '|', '~'};
|
||||
|
|
|
@ -162,6 +162,8 @@ bool isHexDigit(const char c);
|
|||
|
||||
bool inRFC3986UnreservedChars(const char c);
|
||||
|
||||
bool in_rfc3986_sub_delims(const char c);
|
||||
|
||||
// Returns true if |c| is in token (HTTP-p1, Section 3.2.6)
|
||||
bool in_token(char c);
|
||||
|
||||
|
@ -175,6 +177,9 @@ std::string percentEncode(const unsigned char *target, size_t len);
|
|||
|
||||
std::string percentEncode(const std::string &target);
|
||||
|
||||
// percent-encode path component of URI |s|.
|
||||
std::string percent_encode_path(const std::string &s);
|
||||
|
||||
template <typename InputIt>
|
||||
std::string percentDecode(InputIt first, InputIt last) {
|
||||
std::string result;
|
||||
|
|
|
@ -139,6 +139,11 @@ void test_util_percent_encode_token(void) {
|
|||
CU_ASSERT("http%202" == util::percent_encode_token("http 2"));
|
||||
}
|
||||
|
||||
void test_util_percent_encode_path(void) {
|
||||
CU_ASSERT("/foo1/bar%3F&/%0A" == util::percent_encode_path("/foo1/bar?&/"
|
||||
"\x0a"));
|
||||
}
|
||||
|
||||
void test_util_percent_decode(void) {
|
||||
{
|
||||
std::string s = "%66%6F%6f%62%61%72";
|
||||
|
|
|
@ -33,6 +33,7 @@ void test_util_inp_strlower(void);
|
|||
void test_util_to_base64(void);
|
||||
void test_util_to_token68(void);
|
||||
void test_util_percent_encode_token(void);
|
||||
void test_util_percent_encode_path(void);
|
||||
void test_util_percent_decode(void);
|
||||
void test_util_quote_string(void);
|
||||
void test_util_utox(void);
|
||||
|
|
Loading…
Reference in New Issue