Redirecting /nonendpoint URLs to /content/nonendpoint

This commit is contained in:
Veloman Yunkan 2022-08-05 16:39:24 +04:00
parent 3b98987cb3
commit e323dcf6c9
2 changed files with 65 additions and 100 deletions

View File

@ -577,7 +577,11 @@ std::unique_ptr<Response> InternalServer::handle_request(const RequestContext& r
if (isEndpointUrl(url, "catch"))
return handle_catch(request);
return handle_content(request);
std::string contentUrl = m_root + "/content" + url;
const std::string query = request.get_query();
if ( ! query.empty() )
contentUrl += "?" + query;
return Response::build_redirect(*this, contentUrl);
} catch (std::exception& e) {
fprintf(stderr, "===== Unhandled error : %s\n", e.what());
return HTTP500Response(*this, request)

View File

@ -55,9 +55,6 @@ const ResourceCollection resources200Compressible{
{ NO_ETAG, "/ROOT/catch/external?source=www.example.com" },
{ WITH_ETAG, "/ROOT/zimfile/A/index" },
{ WITH_ETAG, "/ROOT/zimfile/A/Ray_Charles" },
{ WITH_ETAG, "/ROOT/content/zimfile/A/index" },
{ WITH_ETAG, "/ROOT/content/zimfile/A/Ray_Charles" },
@ -79,13 +76,8 @@ const ResourceCollection resources200Uncompressible{
{ NO_ETAG, "/ROOT/catalog/v2/illustration/6f1d19d0-633f-087b-fb55-7ac324ff9baf?size=48" },
{ WITH_ETAG, "/ROOT/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg" },
{ WITH_ETAG, "/ROOT/content/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg" },
{ WITH_ETAG, "/ROOT/corner_cases/A/empty.html" },
{ WITH_ETAG, "/ROOT/corner_cases/-/empty.css" },
{ WITH_ETAG, "/ROOT/corner_cases/-/empty.js" },
{ WITH_ETAG, "/ROOT/content/corner_cases/A/empty.html" },
{ WITH_ETAG, "/ROOT/content/corner_cases/-/empty.css" },
{ WITH_ETAG, "/ROOT/content/corner_cases/-/empty.js" },
@ -201,15 +193,6 @@ R"EXPECTEDRESULT( <img src="../skin/download.png?
<img src="../skin/hash.png?cacheid=f836e872" alt="download hash" />
<img src="../skin/magnet.png?cacheid=73b6bddf" alt="download magnet" />
<img src="../skin/bittorrent.png?cacheid=4f5c6882" alt="download torrent" />
)EXPECTEDRESULT"
},
{
/* url */ "/ROOT/zimfile/A/index",
R"EXPECTEDRESULT(<link type="root" href="/ROOT"><link type="text/css" href="/ROOT/skin/taskbar.css?cacheid=26082885" rel="Stylesheet" />
<link type="text/css" href="/ROOT/skin/css/autoComplete.css?cacheid=08951e06" rel="Stylesheet" />
<script type="text/javascript" src="/ROOT/skin/taskbar.js?cacheid=1aec4a68" defer></script>
<script type="text/javascript" src="/ROOT/skin/autoComplete.min.js?cacheid=1191aaaf"></script>
<label for="kiwix_button_show_toggle"><img src="/ROOT/skin/caret.png?cacheid=22b942b4" alt=""></label>
)EXPECTEDRESULT"
},
{
@ -268,18 +251,12 @@ TEST_F(ServerTest, 400)
const char* urls404[] = {
"/",
"/zimfile",
"/ROOT/non-existent-item",
"/ROOT/skin/non-existent-skin-resource",
"/ROOT/catalog",
"/ROOT/catalog/",
"/ROOT/catalog/non-existent-item",
"/ROOT/catalogBLABLABLA/root.xml",
"/ROOT/catalog/v2/illustration/zimfile?size=48",
"/ROOT/catalog/v2/illustration/6f1d19d0-633f-087b-fb55-7ac324ff9baf?size=96",
"/ROOT/meta",
"/ROOT/meta?content=zimfile",
"/ROOT/meta?content=zimfile&name=non-existent-item",
"/ROOT/meta?content=non-existent-book&name=title",
"/ROOT/random",
"/ROOT/random?content=non-existent-book",
"/ROOT/random/",
@ -294,7 +271,6 @@ const char* urls404[] = {
"/ROOT/catch/external", // missing ?source=URL
"/ROOT/catch/external?source=",
"/ROOT/catch/anythingotherthanexternal",
"/ROOT/zimfile/A/non-existent-article",
"/ROOT/content/zimfile/A/non-existent-article",
"/ROOT/raw/non-existent-book/meta/Title",
@ -699,30 +675,17 @@ TEST_F(ServerTest, Http404HtmlError)
</p>
)" },
{ /* url */ "/ROOT/invalid-book/whatever",
{ /* url */ "/ROOT/content/invalid-book/whatever",
expected_body==R"(
<h1>Not Found</h1>
<p>
The requested URL "/ROOT/invalid-book/whatever" was not found on this server.
The requested URL "/ROOT/content/invalid-book/whatever" was not found on this server.
</p>
<p>
Make a full text search for <a href="/ROOT/search?pattern=whatever">whatever</a>
</p>
)" },
{ /* url */ "/ROOT/zimfile/invalid-article",
book_name=="zimfile" &&
book_title=="Ray Charles" &&
expected_body==R"(
<h1>Not Found</h1>
<p>
The requested URL "/ROOT/zimfile/invalid-article" was not found on this server.
</p>
<p>
Make a full text search for <a href="/ROOT/search?content=zimfile&pattern=invalid-article">invalid-article</a>
</p>
)" },
{ /* url */ "/ROOT/content/zimfile/invalid-article",
book_name=="zimfile" &&
book_title=="Ray Charles" &&
@ -736,30 +699,17 @@ TEST_F(ServerTest, Http404HtmlError)
</p>
)" },
{ /* url */ R"(/ROOT/"><svg onload=alert(1)>)",
{ /* url */ R"(/ROOT/content/"><svg onload=alert(1)>)",
expected_body==R"(
<h1>Not Found</h1>
<p>
The requested URL "/ROOT/&quot;&gt;&lt;svg onload=alert(1)&gt;" was not found on this server.
The requested URL "/ROOT/content/&quot;&gt;&lt;svg onload=alert(1)&gt;" was not found on this server.
</p>
<p>
Make a full text search for <a href="/ROOT/search?pattern=%22%3E%3Csvg%20onload%3Dalert(1)%3E">&quot;&gt;&lt;svg onload=alert(1)&gt;</a>
</p>
)" },
{ /* url */ R"(/ROOT/zimfile/"><svg onload=alert(1)>)",
book_name=="zimfile" &&
book_title=="Ray Charles" &&
expected_body==R"(
<h1>Not Found</h1>
<p>
The requested URL "/ROOT/zimfile/&quot;&gt;&lt;svg onload=alert(1)&gt;" was not found on this server.
</p>
<p>
Make a full text search for <a href="/ROOT/search?content=zimfile&pattern=%22%3E%3Csvg%20onload%3Dalert(1)%3E">&quot;&gt;&lt;svg onload=alert(1)&gt;</a>
</p>
)" },
{ /* url */ R"(/ROOT/content/zimfile/"><svg onload=alert(1)>)",
book_name=="zimfile" &&
book_title=="Ray Charles" &&
@ -773,20 +723,6 @@ TEST_F(ServerTest, Http404HtmlError)
</p>
)" },
{ /* url */ "/ROOT/zimfile/invalid-article?userlang=hy",
expected_page_title=="Սխալ հասցե" &&
book_name=="zimfile" &&
book_title=="Ray Charles" &&
expected_body==R"(
<h1>Սխալ հասցե</h1>
<p>
Սխալ հասցե՝ /ROOT/zimfile/invalid-article
</p>
<p>
Որոնել <a href="/ROOT/search?content=zimfile&pattern=invalid-article">invalid-article</a>
</p>
)" },
{ /* url */ "/ROOT/content/zimfile/invalid-article?userlang=hy",
expected_page_title=="Սխալ հասցե" &&
book_name=="zimfile" &&
@ -1042,12 +978,6 @@ TEST_F(ServerTest, 500)
</html>
)";
{
const auto r = zfs1_->GET("/ROOT/poor/A/redirect_loop.html");
EXPECT_EQ(r->status, 500);
EXPECT_EQ(r->body, expectedBody);
}
{
const auto r = zfs1_->GET("/ROOT/content/poor/A/redirect_loop.html");
EXPECT_EQ(r->status, 500);
@ -1074,33 +1004,33 @@ TEST_F(ServerTest, UserLanguageControl)
const TestData testData[] = {
{
/*url*/ "/ROOT/zimfile/invalid-article",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "",
/* expected <h1> */ "Not Found"
},
{
/*url*/ "/ROOT/zimfile/invalid-article?userlang=en",
/*url*/ "/ROOT/content/zimfile/invalid-article?userlang=en",
/*Accept-Language:*/ "",
/* expected <h1> */ "Not Found"
},
{
/*url*/ "/ROOT/zimfile/invalid-article?userlang=hy",
/*url*/ "/ROOT/content/zimfile/invalid-article?userlang=hy",
/*Accept-Language:*/ "",
/* expected <h1> */ "Սխալ հասցե"
},
{
/*url*/ "/ROOT/zimfile/invalid-article",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "*",
/* expected <h1> */ "Not Found"
},
{
/*url*/ "/ROOT/zimfile/invalid-article",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "hy",
/* expected <h1> */ "Սխալ հասցե"
},
{
// userlang query parameter takes precedence over Accept-Language
/*url*/ "/ROOT/zimfile/invalid-article?userlang=en",
/*url*/ "/ROOT/content/zimfile/invalid-article?userlang=en",
/*Accept-Language:*/ "hy",
/* expected <h1> */ "Not Found"
},
@ -1108,7 +1038,7 @@ TEST_F(ServerTest, UserLanguageControl)
// The value of the Accept-Language header is not currently parsed.
// In case of a comma separated list of languages (optionally weighted
// with quality values) the default (en) language is used instead.
/*url*/ "/ROOT/zimfile/invalid-article",
/*url*/ "/ROOT/content/zimfile/invalid-article",
/*Accept-Language:*/ "hy;q=0.9, en;q=0.2",
/* expected <h1> */ "Not Found"
},
@ -1136,15 +1066,52 @@ TEST_F(ServerTest, RandomPageRedirectsToAnExistingArticle)
ASSERT_TRUE(kiwix::startsWith(g->get_header_value("Location"), "/ROOT/content/zimfile/A/"));
}
TEST_F(ServerTest, NonEndpointUrlsAreRedirectedToContentUrls)
{
const std::string paths[] = {
"/zimfile",
"/zimfile/A/index",
"/some/path",
"/non-existent-item",
// Validate that paths starting with a string matching an endpoint name
// are not misinterpreted as endpoint URLs
"/catalogarithm",
"/catalogistics/root.xml",
"/catch22",
"/catchy/song",
"/contention",
"/contents/is/not/the/same/as/content",
"/randomize",
"/randomestic/animals",
"/rawman",
"/rawkward/url",
"/searcheology",
"/searchitecture/history",
"/skinhead",
"/skineffect/formula",
"/suggesture",
"/suggestonia/tallinn",
// The /meta endpoint has been replaced with /raw/<book>/meta
"/meta",
// Make sure that the query is preserved in the redirect URL
"/does?P=NP"
};
for ( const std::string& p : paths )
{
auto g = zfs1_->GET(("/ROOT" + p).c_str());
const TestContext ctx{ { "path", p } };
ASSERT_EQ(302, g->status) << ctx;
ASSERT_TRUE(g->has_header("Location")) << ctx;
ASSERT_EQ("/ROOT/content" + p, g->get_header_value("Location")) << ctx;
}
}
TEST_F(ServerTest, BookMainPageIsRedirectedToArticleIndex)
{
{
auto g = zfs1_->GET("/ROOT/zimfile");
ASSERT_EQ(302, g->status);
ASSERT_TRUE(g->has_header("Location"));
ASSERT_EQ("/ROOT/content/zimfile/A/index", g->get_header_value("Location"));
}
{
auto g = zfs1_->GET("/ROOT/content/zimfile");
ASSERT_EQ(302, g->status);
@ -1172,12 +1139,6 @@ TEST_F(ServerTest, RawEntry)
EXPECT_EQ(200, p->status);
EXPECT_EQ(std::string(p->body), std::string(entry.getItem(true).getData()));
// ... but the "normal" content is not
p = zfs1_->GET("/ROOT/zimfile/A/Ray_Charles");
EXPECT_EQ(200, p->status);
EXPECT_NE(std::string(p->body), std::string(entry.getItem(true).getData()));
EXPECT_TRUE(p->body.find("taskbar") != std::string::npos);
// ... but the "normal" content is not
p = zfs1_->GET("/ROOT/content/zimfile/A/Ray_Charles");
EXPECT_EQ(200, p->status);
@ -1343,7 +1304,7 @@ TEST_F(ServerTest, IfNoneMatchRequestsWithMismatchingETagResultIn200Responses)
TEST_F(ServerTest, ValidSingleRangeByteRangeRequestsAreHandledProperly)
{
const char url[] = "/ROOT/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg";
const char url[] = "/ROOT/content/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg";
const auto full = zfs1_->GET(url);
EXPECT_FALSE(full->has_header("Content-Range"));
EXPECT_EQ("bytes", full->get_header_value("Accept-Ranges"));
@ -1393,7 +1354,7 @@ TEST_F(ServerTest, ValidSingleRangeByteRangeRequestsAreHandledProperly)
TEST_F(ServerTest, InvalidAndMultiRangeByteRangeRequestsResultIn416Responses)
{
const char url[] = "/ROOT/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg";
const char url[] = "/ROOT/content/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg";
const char* invalidRanges[] = {
"0-10", "bytes=", "bytes=123", "bytes=-10-20", "bytes=10-20xxx",
@ -1414,7 +1375,7 @@ TEST_F(ServerTest, InvalidAndMultiRangeByteRangeRequestsResultIn416Responses)
TEST_F(ServerTest, ValidByteRangeRequestsOfZeroSizedEntriesResultIn416Responses)
{
const char url[] = "/ROOT/corner_cases/-/empty.js";
const char url[] = "/ROOT/content/corner_cases/-/empty.js";
const char* ranges[] = {
"bytes=0-",
@ -1433,7 +1394,7 @@ TEST_F(ServerTest, ValidByteRangeRequestsOfZeroSizedEntriesResultIn416Responses)
TEST_F(ServerTest, RangeHasPrecedenceOverCompression)
{
const char url[] = "/ROOT/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg";
const char url[] = "/ROOT/content/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg";
const Headers onlyRange{ {"Range", "bytes=123-456"} };
Headers rangeAndCompression(onlyRange);
@ -1448,7 +1409,7 @@ TEST_F(ServerTest, RangeHasPrecedenceOverCompression)
TEST_F(ServerTest, RangeHeaderIsCaseInsensitive)
{
const char url[] = "/ROOT/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg";
const char url[] = "/ROOT/content/zimfile/I/m/Ray_Charles_classic_piano_pose.jpg";
const auto r0 = zfs1_->GET(url, { {"Range", "bytes=100-200"} } );
const char* header_variations[] = { "RANGE", "range", "rAnGe", "RaNgE" };