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
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
request_cb redirect_handler(int status_code, std::string path) {
|
request_cb redirect_handler(int status_code, std::string uri) {
|
||||||
return [status_code, path](const request &req, const response &res) {
|
return [status_code, uri](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);
|
|
||||||
header_map h;
|
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-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.write_head(status_code, std::move(h));
|
||||||
res.end(std::move(html));
|
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(
|
auto clean_path = ::nghttp2::http2::path_join(
|
||||||
nullptr, 0, nullptr, 0, path.c_str(), path.size(), nullptr, 0);
|
nullptr, 0, nullptr, 0, path.c_str(), path.size(), nullptr, 0);
|
||||||
if (clean_path != path) {
|
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;
|
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_to_token68", shrpx::test_util_to_token68) ||
|
||||||
!CU_add_test(pSuite, "util_percent_encode_token",
|
!CU_add_test(pSuite, "util_percent_encode_token",
|
||||||
shrpx::test_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",
|
!CU_add_test(pSuite, "util_percent_decode",
|
||||||
shrpx::test_util_percent_decode) ||
|
shrpx::test_util_percent_decode) ||
|
||||||
!CU_add_test(pSuite, "util_quote_string",
|
!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];
|
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 percentEncode(const unsigned char *target, size_t len) {
|
||||||
std::string dest;
|
std::string dest;
|
||||||
for (size_t i = 0; i < len; ++i) {
|
for (size_t i = 0; i < len; ++i) {
|
||||||
|
@ -91,6 +98,21 @@ std::string percentEncode(const std::string &target) {
|
||||||
target.size());
|
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) {
|
bool in_token(char c) {
|
||||||
static const char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+',
|
static const char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+',
|
||||||
'-', '.', '^', '_', '`', '|', '~'};
|
'-', '.', '^', '_', '`', '|', '~'};
|
||||||
|
|
|
@ -162,6 +162,8 @@ bool isHexDigit(const char c);
|
||||||
|
|
||||||
bool inRFC3986UnreservedChars(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)
|
// Returns true if |c| is in token (HTTP-p1, Section 3.2.6)
|
||||||
bool in_token(char c);
|
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);
|
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>
|
template <typename InputIt>
|
||||||
std::string percentDecode(InputIt first, InputIt last) {
|
std::string percentDecode(InputIt first, InputIt last) {
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
|
@ -139,6 +139,11 @@ void test_util_percent_encode_token(void) {
|
||||||
CU_ASSERT("http%202" == util::percent_encode_token("http 2"));
|
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) {
|
void test_util_percent_decode(void) {
|
||||||
{
|
{
|
||||||
std::string s = "%66%6F%6f%62%61%72";
|
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_base64(void);
|
||||||
void test_util_to_token68(void);
|
void test_util_to_token68(void);
|
||||||
void test_util_percent_encode_token(void);
|
void test_util_percent_encode_token(void);
|
||||||
|
void test_util_percent_encode_path(void);
|
||||||
void test_util_percent_decode(void);
|
void test_util_percent_decode(void);
|
||||||
void test_util_quote_string(void);
|
void test_util_quote_string(void);
|
||||||
void test_util_utox(void);
|
void test_util_utox(void);
|
||||||
|
|
Loading…
Reference in New Issue