Skip to content

Commit bc6ba6a

Browse files
committed
Redirect to path+/ if path doesn't end with /
If HTML document uses relative paths, it'll fail to load them otherwise. $ echo hello > index.html && mkdir test && echo world > test/index.html $ curl -I http://127.0.0.1:8848 HTTP/1.1 200 OK content-length: 13 content-type: text/html; charset=utf-8 server: drogon/1.9.11 date: Wed, 26 Nov 2025 13:09:28 GMT $ curl -I http://127.0.0.1:8848/test HTTP/1.1 301 Moved Permanently content-length: 0 content-type: text/html; charset=utf-8 server: drogon/1.9.11 location: /test/ date: Wed, 26 Nov 2025 13:09:33 GMT $ curl -I http://127.0.0.1:8848/test/ HTTP/1.1 200 OK content-length: 6 content-type: text/html; charset=utf-8 server: drogon/1.9.11 accept-range: bytes expires: Thu, 01 Jan 1970 00:00:00 GMT last-modified: Wed, 26 Nov 2025 13:08:38 GMT date: Wed, 26 Nov 2025 13:09:34 GMT
1 parent 1d9dcf3 commit bc6ba6a

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

lib/src/StaticFileRouter.cc

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,18 @@ void StaticFileRouter::route(
169169
if (std::filesystem::is_directory(fsFilePath, err))
170170
{
171171
// Check if path is eligible for an implicit index.html
172-
if (implicitPageEnable_)
172+
if (implicitPageEnable_ && req->path().back() != '/')
173+
{
174+
std::string newLocation = req->path() + "/";
175+
if (!req->query().empty())
176+
{
177+
newLocation += "?" + req->query();
178+
}
179+
callback(HttpResponse::newRedirectionResponse(
180+
newLocation, k301MovedPermanently));
181+
return;
182+
}
183+
else if (implicitPageEnable_)
173184
{
174185
filePath = filePath + "/" + implicitPage_;
175186
}
@@ -244,7 +255,19 @@ void StaticFileRouter::route(
244255
if (std::filesystem::is_directory(fsDirectoryPath, err))
245256
{
246257
// Check if path is eligible for an implicit index.html
247-
if (implicitPageEnable_)
258+
if (implicitPageEnable_ && req->path().back() != '/')
259+
{
260+
std::string newLocation = req->path() + "/";
261+
if (!req->query().empty())
262+
{
263+
newLocation += "?" + req->query();
264+
}
265+
callback(
266+
HttpResponse::newRedirectionResponse(newLocation,
267+
k301MovedPermanently));
268+
return;
269+
}
270+
else if (implicitPageEnable_)
248271
{
249272
std::string filePath = directoryPath + "/" + implicitPage_;
250273
sendStaticFileResponse(filePath, req, std::move(callback), "");

lib/tests/integration_test/client/main.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,15 @@ void doTest(const HttpClientPtr &client, std::shared_ptr<test::Case> TEST_CTX)
673673
req = HttpRequest::newHttpRequest();
674674
req->setMethod(drogon::Get);
675675
req->setPath("/a-directory");
676+
client->sendRequest(
677+
req, [req, TEST_CTX](ReqResult result, const HttpResponsePtr &resp) {
678+
REQUIRE(result == ReqResult::Ok);
679+
CHECK(resp->getStatusCode() == k301MovedPermanently);
680+
CHECK(resp->getHeader("Location") == "/a-directory/");
681+
});
682+
req = HttpRequest::newHttpRequest();
683+
req->setMethod(drogon::Get);
684+
req->setPath("/a-directory/");
676685
client->sendRequest(req,
677686
[req, TEST_CTX, body](ReqResult result,
678687
const HttpResponsePtr &resp) {

0 commit comments

Comments
 (0)