Selaa lähdekoodia

Redirect a directory request with a relative Location (#2630)

* Redirect a directory request with a relative Location

The trailing-slash redirect used the request path as-is, so a path
starting with "//" produced a Location that clients read as a
network-path reference to another host. Name only the last segment,
percent-encoded and prefixed with "./", so the target always resolves
against the request URL, whatever the mount point or any prefix a
proxy put in front of it.

* Shorten the relative redirect comment
yhirose 3 päivää sitten
vanhempi
commit
2c918f27ee
2 muutettua tiedostoa jossa 13 lisäystä ja 2 poistoa
  1. 5 1
      httplib.h
  2. 8 1
      test/test.cc

+ 5 - 1
httplib.h

@@ -13869,7 +13869,11 @@ inline bool Server::handle_file_request(Request &req, Response &res) {
         detail::FileStat stat(path);
 
         if (stat.is_dir()) {
-          res.set_redirect(req.path + "/", StatusCode::MovedPermanently_301);
+          // Relative, so "//dir" cannot name another host; "./" keeps a ':'
+          // in the name from reading as a scheme.
+          auto name = req.path.substr(req.path.rfind('/') + 1);
+          res.set_redirect("./" + encode_path_component(name) + "/",
+                           StatusCode::MovedPermanently_301);
           return true;
         }
 

+ 8 - 1
test/test.cc

@@ -6664,7 +6664,14 @@ TEST_F(ServerTest, GetMethodDirMountWithoutTrailingSlash) {
   auto res = cli_.Get("/mount/dir");
   ASSERT_TRUE(res) << "Error: " << to_string(res.error());
   EXPECT_EQ(StatusCode::MovedPermanently_301, res->status);
-  EXPECT_EQ("/mount/dir/", res->get_header_value("Location"));
+  EXPECT_EQ("./dir/", res->get_header_value("Location"));
+}
+
+TEST_F(ServerTest, GetMethodDirWithLeadingDoubleSlash) {
+  auto res = cli_.Get("//dir");
+  ASSERT_TRUE(res) << "Error: " << to_string(res.error());
+  EXPECT_EQ(StatusCode::MovedPermanently_301, res->status);
+  EXPECT_EQ("./dir/", res->get_header_value("Location"));
 }
 
 TEST_F(ServerTest, PostMethod303) {