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"( -
Not found
-

- 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");