diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index c749ebd9f..0566bec28 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -742,6 +742,15 @@ std::string get_book_name(const RequestContext& request) } } +std::string searchSuggestionHTML(const std::string& searchURL, const std::string& pattern) +{ + kainjow::mustache::mustache tmpl("Make a full text search for {{pattern}}"); + MustacheData data; + data.set("pattern", pattern); + data.set("searchURL", searchURL); + return (tmpl.render(data)); +} + } // unnamed namespace std::shared_ptr @@ -765,6 +774,8 @@ InternalServer::build_redirect(const std::string& bookName, const kiwix::Entry& std::unique_ptr InternalServer::handle_content(const RequestContext& request) { + const std::string url = request.get_url(); + const std::string pattern = url.substr((url.find_last_of('/'))+1); if (m_verbose.load()) { printf("** running handle_content\n"); } @@ -775,7 +786,10 @@ std::unique_ptr InternalServer::handle_content(const RequestContext& r const std::shared_ptr reader = get_reader(bookName); if (reader == nullptr) { - return Response::build_404(*this, request, bookName); + std::string searchURL = m_root+"/search?pattern="+pattern; // Make a full search on the entire library. + const std::string details = searchSuggestionHTML(searchURL, kiwix::urlDecode(pattern)); + + return Response::build_404(*this, request, bookName, details); } auto urlStr = request.get_url().substr(bookName.size()+1); @@ -805,7 +819,10 @@ std::unique_ptr InternalServer::handle_content(const RequestContext& r if (m_verbose.load()) printf("Failed to find %s\n", urlStr.c_str()); - return Response::build_404(*this, request, bookName); + std::string searchURL = m_root+"/search?content="+bookName+"&pattern="+pattern; // Make a search on this specific book only. + const std::string details = searchSuggestionHTML(searchURL, kiwix::urlDecode(pattern)); + + return Response::build_404(*this, request, bookName, details); } } diff --git a/src/server/response.cpp b/src/server/response.cpp index 5b7eba04b..292b55e5a 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -93,10 +93,11 @@ std::unique_ptr Response::build_304(const InternalServer& server, cons return response; } -std::unique_ptr Response::build_404(const InternalServer& server, const RequestContext& request, const std::string& bookName) +std::unique_ptr Response::build_404(const InternalServer& server, const RequestContext& request, const std::string& bookName, const std::string& details) { MustacheData results; results.set("url", request.get_full_url()); + results.set("details", details); auto response = ContentResponse::build(server, RESOURCE::templates::_404_html, results, "text/html"); response->set_code(MHD_HTTP_NOT_FOUND); diff --git a/src/server/response.h b/src/server/response.h index f493bb00d..76bb82f7a 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -47,7 +47,7 @@ class Response { static std::unique_ptr build(const InternalServer& server); static std::unique_ptr build_304(const InternalServer& server, const ETag& etag); - static std::unique_ptr build_404(const InternalServer& server, const RequestContext& request, const std::string& bookName); + static std::unique_ptr build_404(const InternalServer& server, const RequestContext& request, const std::string& bookName, const std::string& details=""); static std::unique_ptr build_416(const InternalServer& server, size_t resourceLength); static std::unique_ptr build_500(const InternalServer& server, const std::string& msg); static std::unique_ptr build_redirect(const InternalServer& server, const std::string& redirectUrl); diff --git a/static/templates/404.html b/static/templates/404.html index e127f793c..501c6ebb3 100644 --- a/static/templates/404.html +++ b/static/templates/404.html @@ -9,5 +9,10 @@

The requested URL "{{url}}" was not found on this server.

+ {{#details}} +

+ {{{details}}} +

+ {{/details}}