diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp
index baffc6738..6d2ac4a39 100644
--- a/src/server/internalServer.cpp
+++ b/src/server/internalServer.cpp
@@ -526,8 +526,13 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re
} catch (const std::out_of_range&) {}
/* Make the search */
- if ( (!archive && !bookName.empty())
- || (patternString.empty() && ! has_geo_query) ) {
+ if (patternString.empty() && ! has_geo_query) {
+ return HTTP400HtmlResponse(*this, request)
+ + invalidUrlMsg
+ + std::string("No query provided.");
+ }
+
+ if (!archive && !bookName.empty()) {
auto data = get_default_data();
data.set("pattern", encodeDiples(patternString));
data.set("root", m_root);
diff --git a/test/server.cpp b/test/server.cpp
index cf57826e6..73ad0f83d 100644
--- a/test/server.cpp
+++ b/test/server.cpp
@@ -287,6 +287,19 @@ TEST_F(ServerTest, UncompressibleContentIsNotCompressed)
}
}
+const char* urls400[] = {
+ "/ROOT/search",
+ "/ROOT/search?content=zimfile",
+ "/ROOT/search?pattern"
+};
+
+
+TEST_F(ServerTest, 400)
+{
+ for (const char* url: urls400 )
+ EXPECT_EQ(400, zfs1_->GET(url)->status) << "url: " << url;
+}
+
const char* urls404[] = {
"/",
"/zimfile",
@@ -302,7 +315,6 @@ const char* urls404[] = {
"/ROOT/meta?content=non-existent-book&name=title",
"/ROOT/random",
"/ROOT/random?content=non-existent-book",
- "/ROOT/search",
"/ROOT/search?content=non-existing-book&pattern=asdfqwerty",
"/ROOT/suggest",
"/ROOT/suggest?content=non-existent-book&term=abcd",
@@ -388,13 +400,14 @@ public:
: ExpectedResponseData(erd)
, url(url)
{}
+ virtual ~TestContentIn404HtmlResponse() = default;
const std::string url;
std::string expectedResponse() const;
private:
- std::string pageTitle() const;
+ virtual std::string pageTitle() const;
std::string pageCssLink() const;
std::string hiddenBookNameInput() const;
std::string searchPatternInput() const;
@@ -521,6 +534,25 @@ std::string TestContentIn404HtmlResponse::taskbarLinks() const
+ R"(">🎲 )";
}
+class TestContentIn400HtmlResponse : public TestContentIn404HtmlResponse
+{
+public:
+ TestContentIn400HtmlResponse(const std::string& url,
+ const ExpectedResponseData& erd)
+ : TestContentIn404HtmlResponse(url, erd)
+ {}
+
+private:
+ std::string pageTitle() const;
+};
+
+std::string TestContentIn400HtmlResponse::pageTitle() const {
+ return expectedPageTitle.empty()
+ ? "Invalid request"
+ : expectedPageTitle;
+}
+
+
} // namespace TestingOfHtmlResponses
TEST_F(ServerTest, 404WithBodyTesting)
@@ -651,19 +683,6 @@ TEST_F(ServerTest, 404WithBodyTesting)
)" },
- { /* url */ "/ROOT/search?content=zimfile",
- expected_page_title=="Fulltext search unavailable" &&
- expected_css_url=="/ROOT/skin/search_results.css" &&
- book_name=="zimfile" &&
- book_title=="Ray Charles" &&
- expected_body==R"(
-
-
- There is no article with the title ""
- and the fulltext search engine is not available for this content.
-
-)" },
-
{ /* url */ "/ROOT/search?content=non-existent-book&pattern=asdfqwerty",
expected_page_title=="Fulltext search unavailable" &&
expected_css_url=="/ROOT/skin/search_results.css" &&
@@ -684,6 +703,52 @@ TEST_F(ServerTest, 404WithBodyTesting)
}
}
+TEST_F(ServerTest, 400WithBodyTesting)
+{
+ using namespace TestingOfHtmlResponses;
+ const std::vector testData{
+ { /* url */ "/ROOT/search",
+ expected_body== R"(
+ Invalid request
+
+ The requested URL "/ROOT/search" is not a valid request.
+
+
+ No query provided.
+
+)" },
+ { /* url */ "/ROOT/search?content=zimfile",
+ expected_body==R"(
+ Invalid request
+
+ The requested URL "/ROOT/search?content=zimfile" is not a valid request.
+
+
+ No query provided.
+
+)" },
+ // There is a flaw in our way to handle query string, we cannot differenciate
+ // between `pattern` and `pattern=`
+ { /* url */ "/ROOT/search?pattern",
+ expected_body==R"(
+ Invalid request
+
+ The requested URL "/ROOT/search?pattern=" is not a valid request.
+
+
+ No query provided.
+
+)" },
+ };
+
+ for ( const auto& t : testData ) {
+ const TestContext ctx{ {"url", t.url} };
+ const auto r = zfs1_->GET(t.url.c_str());
+ EXPECT_EQ(r->status, 400) << ctx;
+ EXPECT_EQ(r->body, t.expectedResponse()) << ctx;
+ }
+}
+
TEST_F(ServerTest, RandomPageRedirectsToAnExistingArticle)
{
auto g = zfs1_->GET("/ROOT/random?content=zimfile");