From c2b6e4ac044759db71cbd5407904168e6a1e3d44 Mon Sep 17 00:00:00 2001 From: yhirose Date: Fri, 17 Apr 2020 21:48:16 -0400 Subject: [PATCH] Fix #431 --- httplib.h | 16 +++++++++++++--- test/test.cc | 42 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/httplib.h b/httplib.h index e55d14b..f722b40 100644 --- a/httplib.h +++ b/httplib.h @@ -312,7 +312,7 @@ struct Response { void set_header(const char *key, const char *val); void set_header(const char *key, const std::string &val); - void set_redirect(const char *url); + void set_redirect(const char *url, int status = 302); void set_content(const char *s, size_t n, const char *content_type); void set_content(std::string s, const char *content_type); @@ -2048,6 +2048,12 @@ inline bool redirect(T &cli, const Request &req, Response &res, new_req.path = path; new_req.redirect_count -= 1; + if (res.status == 303 && (req.method != "GET" && req.method != "HEAD")) { + new_req.method = "GET"; + new_req.body.clear(); + new_req.headers.clear(); + } + Response new_res; auto ret = cli.send(new_req, new_res); @@ -2790,10 +2796,14 @@ inline void Response::set_header(const char *key, const std::string &val) { } } -inline void Response::set_redirect(const char *url) { +inline void Response::set_redirect(const char *url, int status) { if (!detail::has_crlf(url)) { set_header("Location", url); - status = 302; + if (300 <= status && status < 400) { + this->status = status; + } else { + this->status = 302; + } } } diff --git a/test/test.cc b/test/test.cc index 83cfe51..81178c4 100644 --- a/test/test.cc +++ b/test/test.cc @@ -749,6 +749,13 @@ protected: }) .Get("/", [&](const Request & /*req*/, Response &res) { res.set_redirect("/hi"); }) + .Post("/1", [](const Request & /*req*/, + Response &res) { res.set_redirect("/2", 303); }) + .Get("/2", + [](const Request & /*req*/, Response &res) { + res.set_content("redirected.", "text/plain"); + res.status = 200; + }) .Post("/person", [&](const Request &req, Response &res) { if (req.has_param("name") && req.has_param("note")) { @@ -913,10 +920,10 @@ protected: res.set_content("DELETE", "text/plain"); }) .Delete("/delete-body", - [&](const Request &req, Response &res) { - EXPECT_EQ(req.body, "content"); - res.set_content(req.body, "text/plain"); - }) + [&](const Request &req, Response &res) { + EXPECT_EQ(req.body, "content"); + res.set_content(req.body, "text/plain"); + }) .Options(R"(\*)", [&](const Request & /*req*/, Response &res) { res.set_header("Allow", "GET, POST, HEAD, OPTIONS"); @@ -1116,6 +1123,14 @@ TEST_F(ServerTest, GetMethod302) { EXPECT_EQ("/hi", res->get_header_value("Location")); } +TEST_F(ServerTest, GetMethod302Redirect) { + cli_.set_follow_location(true); + auto res = cli_.Get("/"); + ASSERT_TRUE(res != nullptr); + EXPECT_EQ(200, res->status); + EXPECT_EQ("Hello World!", res->body); +} + TEST_F(ServerTest, GetMethod404) { auto res = cli_.Get("/invalid"); ASSERT_TRUE(res != nullptr); @@ -1315,6 +1330,21 @@ TEST_F(ServerTest, GetMethodOutOfBaseDirMount2) { EXPECT_EQ(404, res->status); } +TEST_F(ServerTest, PostMethod303) { + auto res = cli_.Post("/1", "body", "text/plain"); + ASSERT_TRUE(res != nullptr); + EXPECT_EQ(303, res->status); + EXPECT_EQ("/2", res->get_header_value("Location")); +} + +TEST_F(ServerTest, PostMethod303Redirect) { + cli_.set_follow_location(true); + auto res = cli_.Post("/1", "body", "text/plain"); + ASSERT_TRUE(res != nullptr); + EXPECT_EQ(200, res->status); + EXPECT_EQ("redirected.", res->body); +} + TEST_F(ServerTest, UserDefinedMIMETypeMapping) { auto res = cli_.Get("/dir/test.abcde"); ASSERT_TRUE(res != nullptr); @@ -2142,8 +2172,8 @@ TEST(ServerRequestParsingTest, ReadHeadersRegexComplexity) { test_raw_request( "GET /hi HTTP/1.1\r\n" " : " - " " - ); + " " + " "); } TEST(ServerRequestParsingTest, ReadHeadersRegexComplexity2) {