From 96cbd2bf26fa79310282f84dc19b1727098f81a0 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Fri, 11 Mar 2022 21:57:50 +0400 Subject: [PATCH 01/20] kiwix::onlyAsNonEmptyMustacheValue() --- src/opds_dumper.cpp | 9 +++------ src/tools/otherTools.cpp | 7 +++++++ src/tools/otherTools.h | 4 ++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/opds_dumper.cpp b/src/opds_dumper.cpp index af642246c..91bfb7f44 100644 --- a/src/opds_dumper.cpp +++ b/src/opds_dumper.cpp @@ -73,9 +73,6 @@ IllustrationInfo getBookIllustrationInfo(const Book& book) kainjow::mustache::object getSingleBookData(const Book& book) { const auto bookDate = book.getDate() + "T00:00:00Z"; - const MustacheData bookUrl = book.getUrl().empty() - ? MustacheData(false) - : MustacheData(book.getUrl()); return kainjow::mustache::object{ {"id", book.getId()}, {"name", book.getName()}, @@ -92,7 +89,7 @@ kainjow::mustache::object getSingleBookData(const Book& book) {"media_count", to_string(book.getMediaCount())}, {"author_name", book.getCreator()}, {"publisher_name", book.getPublisher()}, - {"url", bookUrl}, + {"url", onlyAsNonEmptyMustacheValue(book.getUrl())}, {"size", to_string(book.getSize())}, {"icons", getBookIllustrationInfo(book)}, }; @@ -194,7 +191,7 @@ string OPDSDumper::dumpOPDSFeed(const std::vector& bookIds, const s {"date", gen_date_str()}, {"root", rootLocation}, {"feed_id", gen_uuid(libraryId + "/catalog/search?"+query)}, - {"filter", query.empty() ? MustacheData(false) : MustacheData(query)}, + {"filter", onlyAsNonEmptyMustacheValue(query)}, {"totalResults", to_string(m_totalResults)}, {"startIndex", to_string(m_startIndex)}, {"itemsPerPage", to_string(m_count)}, @@ -214,7 +211,7 @@ string OPDSDumper::dumpOPDSFeedV2(const std::vector& bookIds, const {"date", gen_date_str()}, {"endpoint_root", endpointRoot}, {"feed_id", gen_uuid(libraryId + endpoint + "?" + query)}, - {"filter", query.empty() ? MustacheData(false) : MustacheData(query)}, + {"filter", onlyAsNonEmptyMustacheValue(query)}, {"query", query.empty() ? "" : "?" + urlEncode(query)}, {"totalResults", to_string(m_totalResults)}, {"startIndex", to_string(m_startIndex)}, diff --git a/src/tools/otherTools.cpp b/src/tools/otherTools.cpp index 1afcc7d7b..ab5bf5874 100644 --- a/src/tools/otherTools.cpp +++ b/src/tools/otherTools.cpp @@ -370,6 +370,13 @@ std::string kiwix::gen_uuid(const std::string& s) return kiwix::to_string(zim::Uuid::generate(s)); } +kainjow::mustache::data kiwix::onlyAsNonEmptyMustacheValue(const std::string& s) +{ + return s.empty() + ? kainjow::mustache::data(false) + : kainjow::mustache::data(s); +} + std::string kiwix::render_template(const std::string& template_str, kainjow::mustache::data data) { kainjow::mustache::mustache tmpl(template_str); diff --git a/src/tools/otherTools.h b/src/tools/otherTools.h index 219332cdb..b1297798e 100644 --- a/src/tools/otherTools.h +++ b/src/tools/otherTools.h @@ -48,6 +48,10 @@ namespace kiwix std::string gen_date_str(); std::string gen_uuid(const std::string& s); + // if s is empty then returns kainjow::mustache::data(false) + // otherwise kainjow::mustache::data(value) + kainjow::mustache::data onlyAsNonEmptyMustacheValue(const std::string& s); + std::string render_template(const std::string& template_str, kainjow::mustache::data data); } From d487c78ea48587808f520e3625986cf83bb843fc Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Fri, 21 Jan 2022 22:15:06 +0400 Subject: [PATCH 02/20] Changed the return type of Response::build_404() --- src/server/response.cpp | 4 ++-- src/server/response.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/response.cpp b/src/server/response.cpp index 398c5ee88..c1a7d20a3 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -83,7 +83,7 @@ std::unique_ptr Response::build_304(const InternalServer& server, cons return response; } -std::unique_ptr Response::build_404(const InternalServer& server, const std::string& url, const std::string& bookName, const std::string& bookTitle, const std::string& details) +std::unique_ptr Response::build_404(const InternalServer& server, const std::string& url, const std::string& bookName, const std::string& bookTitle, const std::string& details) { MustacheData results; if ( !url.empty() ) { @@ -95,7 +95,7 @@ std::unique_ptr Response::build_404(const InternalServer& server, cons response->set_code(MHD_HTTP_NOT_FOUND); response->set_taskbar(bookName, bookTitle); - return std::move(response); + return response; } std::unique_ptr Response::build_416(const InternalServer& server, size_t resourceLength) diff --git a/src/server/response.h b/src/server/response.h index 1a74aaf00..a36c9538c 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -38,7 +38,7 @@ namespace kiwix { class InternalServer; class RequestContext; -class EntryResponse; +class ContentResponse; class Response { public: @@ -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 std::string& url, const std::string& bookName, const std::string& bookTitle, const std::string& details=""); + static std::unique_ptr build_404(const InternalServer& server, const std::string& url, const std::string& bookName, const std::string& bookTitle, 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); From 40e9a19c48949e7cef218d731b9d817de8832db6 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Fri, 21 Jan 2022 22:31:01 +0400 Subject: [PATCH 03/20] Introduced withTaskbarInfo() helper function This was done in preparation for removing the `bookName` and `bookTitle` parameters from `Response::build_404()`, but since the new function could already be put to some use in this commit that was done too. --- src/server/internalServer.cpp | 7 ++----- src/server/response.cpp | 10 ++++++++++ src/server/response.h | 8 ++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index eb43286bd..d11f86482 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -519,9 +519,8 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re data.set("pattern", encodeDiples(patternString)); data.set("root", m_root); auto response = ContentResponse::build(*this, RESOURCE::templates::no_search_result_html, data, "text/html; charset=utf-8"); - response->set_taskbar(bookName, archive ? getArchiveTitle(*archive) : ""); response->set_code(MHD_HTTP_NOT_FOUND); - return std::move(response); + return withTaskbarInfo(bookName, archive.get(), std::move(response)); } std::shared_ptr searcher; @@ -591,9 +590,7 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re renderer.setSearchProtocolPrefix(m_root + "/search?"); renderer.setPageLength(pageLength); auto response = ContentResponse::build(*this, renderer.getHtml(), "text/html; charset=utf-8"); - response->set_taskbar(bookName, archive ? getArchiveTitle(*archive) : ""); - - return std::move(response); + return withTaskbarInfo(bookName, archive.get(), std::move(response)); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return Response::build_500(*this, e.what()); diff --git a/src/server/response.cpp b/src/server/response.cpp index c1a7d20a3..0310c8870 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -25,6 +25,7 @@ #include "tools/regexTools.h" #include "tools/stringTools.h" #include "tools/otherTools.h" +#include "tools/archiveTools.h" #include "string.h" #include @@ -383,6 +384,15 @@ std::unique_ptr ContentResponse::build( return ContentResponse::build(server, content, mimetype, isHomePage); } +std::unique_ptr withTaskbarInfo( + const std::string& bookName, + const zim::Archive* archive, + std::unique_ptr r) +{ + r->set_taskbar(bookName, archive ? getArchiveTitle(*archive) : ""); + return r; +} + ItemResponse::ItemResponse(bool verbose, const zim::Item& item, const std::string& mimetype, const ByteRange& byterange) : Response(verbose), m_item(item), diff --git a/src/server/response.h b/src/server/response.h index a36c9538c..744afd25a 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -33,6 +33,10 @@ extern "C" { #include "microhttpd_wrapper.h" } +namespace zim { +class Archive; +} // namespace zim + namespace kiwix { class InternalServer; @@ -124,6 +128,10 @@ class ContentResponse : public Response { std::string m_bookTitle; }; +std::unique_ptr withTaskbarInfo(const std::string& bookName, + const zim::Archive* archive, + std::unique_ptr r); + class ItemResponse : public Response { public: ItemResponse(bool verbose, const zim::Item& item, const std::string& mimetype, const ByteRange& byterange); From 6d16d7386d438aaee0a8e75bdf7c8c2ed14b6b15 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sun, 30 Jan 2022 19:32:04 +0400 Subject: [PATCH 04/20] Changed the signature of ContentResponse::set_taskbar() --- src/server/internalServer.cpp | 2 +- src/server/response.cpp | 6 +++--- src/server/response.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index d11f86482..569fe2c13 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -816,7 +816,7 @@ std::unique_ptr InternalServer::handle_content(const RequestContext& r } auto response = ItemResponse::build(*this, request, entry.getItem()); try { - dynamic_cast(*response).set_taskbar(bookName, getArchiveTitle(*archive)); + dynamic_cast(*response).set_taskbar(bookName, archive.get()); } catch (std::bad_cast& e) {} if (m_verbose.load()) { diff --git a/src/server/response.cpp b/src/server/response.cpp index 0310c8870..94f5df0b5 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -333,10 +333,10 @@ MHD_Result Response::send(const RequestContext& request, MHD_Connection* connect return ret; } -void ContentResponse::set_taskbar(const std::string& bookName, const std::string& bookTitle) +void ContentResponse::set_taskbar(const std::string& bookName, const zim::Archive* archive) { m_bookName = bookName; - m_bookTitle = bookTitle; + m_bookTitle = archive ? getArchiveTitle(*archive) : ""; } @@ -389,7 +389,7 @@ std::unique_ptr withTaskbarInfo( const zim::Archive* archive, std::unique_ptr r) { - r->set_taskbar(bookName, archive ? getArchiveTitle(*archive) : ""); + r->set_taskbar(bookName, archive); return r; } diff --git a/src/server/response.h b/src/server/response.h index 744afd25a..e464ca54c 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -104,7 +104,7 @@ class ContentResponse : public Response { const std::string& mimetype, bool isHomePage = false); - void set_taskbar(const std::string& bookName, const std::string& bookTitle); + void set_taskbar(const std::string& bookName, const zim::Archive* archive); private: MHD_Response* create_mhd_response(const RequestContext& request); From ca965d448f6e0272fd64be792f9e3f9152cfb26f Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Fri, 11 Mar 2022 22:31:33 +0400 Subject: [PATCH 05/20] Got rid of 2 parameters in Response::build_404() Instead of passing the `bookName` and `bookTitle` parameters to `Response::build_404()`, `withTaskbarInfo()` is applied to its result when needed. Note, that in `InternalServer::handle_raw()` `withTaskbarInfo()` was not utilized since the results of the `/raw` endpoint are not supposed to be decorated with a taskbar. --- src/server/internalServer.cpp | 33 ++++++++++++++---------- src/server/internalServer_catalog_v2.cpp | 8 +++--- src/server/response.cpp | 3 +-- src/server/response.h | 2 +- test/server.cpp | 4 --- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 569fe2c13..d89d77213 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -279,7 +279,7 @@ std::unique_ptr InternalServer::handle_request(const RequestContext& r { try { if (! request.is_valid_url()) - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); const ETag etag = get_matching_if_none_match_etag(request); if ( etag ) @@ -406,7 +406,8 @@ std::unique_ptr InternalServer::handle_suggest(const RequestContext& r if (archive == nullptr) { const std::string error_details = "No such book: " + bookName; - return Response::build_404(*this, "", bookName, "", error_details); + auto response = Response::build_404(*this, "", error_details); + return withTaskbarInfo(bookName, nullptr, std::move(response)); } const auto queryString = request.get_optional_param("term", std::string()); @@ -476,7 +477,7 @@ std::unique_ptr InternalServer::handle_skin(const RequestContext& requ response->set_cacheable(); return std::move(response); } catch (const ResourceNotFound& e) { - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); } } @@ -615,7 +616,8 @@ std::unique_ptr InternalServer::handle_random(const RequestContext& re if (archive == nullptr) { const std::string error_details = "No such book: " + bookName; - return Response::build_404(*this, "", bookName, "", error_details); + auto response = Response::build_404(*this, "", error_details); + return withTaskbarInfo(bookName, nullptr, std::move(response)); } try { @@ -623,7 +625,8 @@ std::unique_ptr InternalServer::handle_random(const RequestContext& re return build_redirect(bookName, getFinalItem(*archive, entry)); } catch(zim::EntryNotFound& e) { const std::string error_details = "Oops! Failed to pick a random article :("; - return Response::build_404(*this, "", bookName, getArchiveTitle(*archive), error_details); + auto response = Response::build_404(*this, "", error_details); + return withTaskbarInfo(bookName, archive.get(), std::move(response)); } } @@ -635,7 +638,7 @@ std::unique_ptr InternalServer::handle_captured_external(const Request } catch (const std::out_of_range& e) {} if (source.empty()) - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); auto data = get_default_data(); data.set("source", source); @@ -654,7 +657,7 @@ std::unique_ptr InternalServer::handle_catalog(const RequestContext& r host = request.get_header("Host"); url = request.get_url_part(1); } catch (const std::out_of_range&) { - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); } if (url == "v2") { @@ -662,7 +665,7 @@ std::unique_ptr InternalServer::handle_catalog(const RequestContext& r } if (url != "searchdescription.xml" && url != "root.xml" && url != "search") { - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); } if (url == "searchdescription.xml") { @@ -799,7 +802,8 @@ std::unique_ptr InternalServer::handle_content(const RequestContext& r std::string searchURL = m_root + "/search?pattern=" + kiwix::urlEncode(pattern, true); // Make a full search on the entire library. const std::string details = searchSuggestionHTML(searchURL, kiwix::urlDecode(pattern)); - return Response::build_404(*this, request.get_full_url(), bookName, "", details); + auto response = Response::build_404(*this, request.get_full_url(), details); + return withTaskbarInfo(bookName, nullptr, std::move(response)); } auto urlStr = request.get_url().substr(bookName.size()+1); @@ -832,7 +836,8 @@ std::unique_ptr InternalServer::handle_content(const RequestContext& r std::string searchURL = m_root + "/search?content=" + bookName + "&pattern=" + kiwix::urlEncode(pattern, true); // Make a search on this specific book only. const std::string details = searchSuggestionHTML(searchURL, kiwix::urlDecode(pattern)); - return Response::build_404(*this, request.get_full_url(), bookName, getArchiveTitle(*archive), details); + auto response = Response::build_404(*this, request.get_full_url(), details); + return withTaskbarInfo(bookName, archive.get(), std::move(response)); } } @@ -849,12 +854,12 @@ std::unique_ptr InternalServer::handle_raw(const RequestContext& reque bookName = request.get_url_part(1); kind = request.get_url_part(2); } catch (const std::out_of_range& e) { - return Response::build_404(*this, request.get_full_url(), bookName, "", ""); + return Response::build_404(*this, request.get_full_url()); } if (kind != "meta" && kind!= "content") { const std::string error_details = kind + " is not a valid request for raw content."; - return Response::build_404(*this, request.get_full_url(), bookName, "", error_details); + return Response::build_404(*this, request.get_full_url(), error_details); } std::shared_ptr archive; @@ -865,7 +870,7 @@ std::unique_ptr InternalServer::handle_raw(const RequestContext& reque if (archive == nullptr) { const std::string error_details = "No such book: " + bookName; - return Response::build_404(*this, request.get_full_url(), bookName, "", error_details); + return Response::build_404(*this, request.get_full_url(), error_details); } // Remove the beggining of the path: @@ -890,7 +895,7 @@ std::unique_ptr InternalServer::handle_raw(const RequestContext& reque printf("Failed to find %s\n", itemPath.c_str()); } const std::string error_details = "Cannot find " + kind + " entry " + itemPath; - return Response::build_404(*this, request.get_full_url(), bookName, getArchiveTitle(*archive), error_details); + return Response::build_404(*this, request.get_full_url(), error_details); } } diff --git a/src/server/internalServer_catalog_v2.cpp b/src/server/internalServer_catalog_v2.cpp index 3a578cb02..cd678ba55 100644 --- a/src/server/internalServer_catalog_v2.cpp +++ b/src/server/internalServer_catalog_v2.cpp @@ -43,7 +43,7 @@ std::unique_ptr InternalServer::handle_catalog_v2(const RequestContext try { url = request.get_url_part(2); } catch (const std::out_of_range&) { - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); } if (url == "root.xml") { @@ -69,7 +69,7 @@ std::unique_ptr InternalServer::handle_catalog_v2(const RequestContext } else if (url == "illustration") { return handle_catalog_v2_illustration(request); } else { - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); } } @@ -110,7 +110,7 @@ std::unique_ptr InternalServer::handle_catalog_v2_complete_entry(const try { mp_library->getBookById(entryId); } catch (const std::out_of_range&) { - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); } OPDSDumper opdsDumper(mp_library); @@ -158,7 +158,7 @@ std::unique_ptr InternalServer::handle_catalog_v2_illustration(const R auto illustration = book.getIllustration(size); return ContentResponse::build(*this, illustration->getData(), illustration->mimeType); } catch(...) { - return Response::build_404(*this, request.get_full_url(), "", ""); + return Response::build_404(*this, request.get_full_url()); } } diff --git a/src/server/response.cpp b/src/server/response.cpp index 94f5df0b5..16c614b58 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -84,7 +84,7 @@ std::unique_ptr Response::build_304(const InternalServer& server, cons return response; } -std::unique_ptr Response::build_404(const InternalServer& server, const std::string& url, const std::string& bookName, const std::string& bookTitle, const std::string& details) +std::unique_ptr Response::build_404(const InternalServer& server, const std::string& url, const std::string& details) { MustacheData results; if ( !url.empty() ) { @@ -94,7 +94,6 @@ std::unique_ptr Response::build_404(const InternalServer& serve auto response = ContentResponse::build(server, RESOURCE::templates::_404_html, results, "text/html"); response->set_code(MHD_HTTP_NOT_FOUND); - response->set_taskbar(bookName, bookTitle); return response; } diff --git a/src/server/response.h b/src/server/response.h index e464ca54c..37bfc6929 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -51,7 +51,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 std::string& url, const std::string& bookName, const std::string& bookTitle, const std::string& details=""); + static std::unique_ptr build_404(const InternalServer& server, const std::string& url, 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/test/server.cpp b/test/server.cpp index 4eb22e063..658211216 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -638,8 +638,6 @@ TEST_F(ServerTest, 404WithBodyTesting) )" }, { /* url */ "/ROOT/raw/zimfile/meta/invalid-metadata", - book_name=="zimfile" && - book_title=="Ray Charles" && expected_body==R"(

Not Found

@@ -651,8 +649,6 @@ TEST_F(ServerTest, 404WithBodyTesting) )" }, { /* url */ "/ROOT/raw/zimfile/content/invalid-article", - book_name=="zimfile" && - book_title=="Ray Charles" && expected_body==R"(

Not Found

From 26c16bb1b247b173454ef5e44db22f603900d081 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sat, 22 Jan 2022 18:13:34 +0400 Subject: [PATCH 06/20] Renamed a variable --- src/server/response.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/response.cpp b/src/server/response.cpp index 16c614b58..587136882 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -86,13 +86,13 @@ std::unique_ptr Response::build_304(const InternalServer& server, cons std::unique_ptr Response::build_404(const InternalServer& server, const std::string& url, const std::string& details) { - MustacheData results; + MustacheData data; if ( !url.empty() ) { - results.set("url", url); + data.set("url", url); } - results.set("details", details); + data.set("details", details); - auto response = ContentResponse::build(server, RESOURCE::templates::_404_html, results, "text/html"); + auto response = ContentResponse::build(server, RESOURCE::templates::_404_html, data, "text/html"); response->set_code(MHD_HTTP_NOT_FOUND); return response; From 8cfcf2ea86e5251d78b36a727ebf820c7292d27c Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sat, 22 Jan 2022 18:15:19 +0400 Subject: [PATCH 07/20] A new overload of Response::build_404() --- src/server/response.cpp | 6 ++++++ src/server/response.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/server/response.cpp b/src/server/response.cpp index 587136882..f4e6f424b 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -92,12 +92,18 @@ std::unique_ptr Response::build_404(const InternalServer& serve } data.set("details", details); + return build_404(server, data); +} + +std::unique_ptr Response::build_404(const InternalServer& server, const kainjow::mustache::data& data) +{ auto response = ContentResponse::build(server, RESOURCE::templates::_404_html, data, "text/html"); response->set_code(MHD_HTTP_NOT_FOUND); return response; } + std::unique_ptr Response::build_416(const InternalServer& server, size_t resourceLength) { auto response = Response::build(server); diff --git a/src/server/response.h b/src/server/response.h index 37bfc6929..ccafa02e9 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -51,6 +51,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 kainjow::mustache::data& data); static std::unique_ptr build_404(const InternalServer& server, const std::string& url, 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); From ae60ba806bfbb7c71840c30b9f1702e316633574 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Thu, 24 Mar 2022 17:22:41 +0400 Subject: [PATCH 08/20] Made 404.html error template a little more generic The fact that an info message was moved into C++ code is temporary since it will be moved to a message resource file soon. --- src/server/response.cpp | 10 ++++++---- static/templates/404.html | 11 +++-------- test/server.cpp | 2 -- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/server/response.cpp b/src/server/response.cpp index f4e6f424b..65be83eb4 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -86,13 +86,15 @@ std::unique_ptr Response::build_304(const InternalServer& server, cons std::unique_ptr Response::build_404(const InternalServer& server, const std::string& url, const std::string& details) { - MustacheData data; + kainjow::mustache::list pList; if ( !url.empty() ) { - data.set("url", url); + kainjow::mustache::mustache msgTmpl(R"(The requested URL "{{url}}" was not found on this server.)"); + const auto urlNotFoundMsg = msgTmpl.render({"url", url}); + pList.push_back({"p", urlNotFoundMsg}); } - data.set("details", details); + pList.push_back({"p", details}); - return build_404(server, data); + return build_404(server, {"details", pList}); } std::unique_ptr Response::build_404(const InternalServer& server, const kainjow::mustache::data& data) diff --git a/static/templates/404.html b/static/templates/404.html index 2f6cf2acf..795e8c9ef 100644 --- a/static/templates/404.html +++ b/static/templates/404.html @@ -6,15 +6,10 @@

Not Found

- {{#url}} +{{#details}}

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

- {{/url}} - {{#details}} -

- {{{details}}} -

- {{/details}} +{{/details}} diff --git a/test/server.cpp b/test/server.cpp index 658211216..81af4c864 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -530,7 +530,6 @@ TEST_F(ServerTest, 404WithBodyTesting) { /* url */ "/ROOT/random?content=non-existent-book", expected_body==R"(

Not Found

- //EOLWHITESPACEMARKER

No such book: non-existent-book

@@ -539,7 +538,6 @@ TEST_F(ServerTest, 404WithBodyTesting) { /* url */ "/ROOT/suggest?content=no-such-book&term=whatever", expected_body==R"(

Not Found

- //EOLWHITESPACEMARKER

No such book: no-such-book

From ff8da65c6810bf03b1dc850a06bce7271da036b2 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sat, 22 Jan 2022 22:13:40 +0400 Subject: [PATCH 09/20] Separated make404ResponseData() --- src/server/response.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/server/response.cpp b/src/server/response.cpp index 65be83eb4..822f3d341 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -84,7 +84,7 @@ std::unique_ptr Response::build_304(const InternalServer& server, cons return response; } -std::unique_ptr Response::build_404(const InternalServer& server, const std::string& url, const std::string& details) +kainjow::mustache::data make404ResponseData(const std::string& url, const std::string& details) { kainjow::mustache::list pList; if ( !url.empty() ) { @@ -93,8 +93,12 @@ std::unique_ptr Response::build_404(const InternalServer& serve pList.push_back({"p", urlNotFoundMsg}); } pList.push_back({"p", details}); + return {"details", pList}; +} - return build_404(server, {"details", pList}); +std::unique_ptr Response::build_404(const InternalServer& server, const std::string& url, const std::string& details) +{ + return build_404(server, make404ResponseData(url, details)); } std::unique_ptr Response::build_404(const InternalServer& server, const kainjow::mustache::data& data) From df98c58d0773d1b6f471d52c4abb9c3662eafb32 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sat, 22 Jan 2022 23:02:06 +0400 Subject: [PATCH 10/20] Enter ContentResponseBlueprint --- src/server/internalServer.cpp | 3 ++- src/server/response.cpp | 9 +++++++ src/server/response.h | 49 +++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index d89d77213..17e4111be 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -657,7 +657,8 @@ std::unique_ptr InternalServer::handle_catalog(const RequestContext& r host = request.get_header("Host"); url = request.get_url_part(1); } catch (const std::out_of_range&) { - return Response::build_404(*this, request.get_full_url()); + return make404Response(*this, request) + + make404ResponseData(request.get_full_url()); } if (url == "v2") { diff --git a/src/server/response.cpp b/src/server/response.cpp index 822f3d341..8bcd2bb3a 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -109,6 +109,15 @@ std::unique_ptr Response::build_404(const InternalServer& serve return response; } +ContentResponseBlueprint make404Response(const InternalServer& server, + const RequestContext& request) +{ + return ContentResponseBlueprint(&server, + &request, + MHD_HTTP_NOT_FOUND, + "text/html", + RESOURCE::templates::_404_html); +} std::unique_ptr Response::build_416(const InternalServer& server, size_t resourceLength) { diff --git a/src/server/response.h b/src/server/response.h index ccafa02e9..fa0d9e42d 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -133,6 +133,55 @@ std::unique_ptr withTaskbarInfo(const std::string& bookName, const zim::Archive* archive, std::unique_ptr r); +class ContentResponseBlueprint +{ +public: // functions + ContentResponseBlueprint(const InternalServer* server, + const RequestContext* request, + int httpStatusCode, + const std::string& mimeType, + const std::string& templateStr) + : m_server(*server) + , m_request(*request) + , m_httpStatusCode(httpStatusCode) + , m_mimeType(mimeType) + , m_template(templateStr) + {} + + ContentResponseBlueprint& operator+(kainjow::mustache::data&& data) + { + this->m_data = std::move(data); + return *this; + } + + operator std::unique_ptr() const + { + auto r = ContentResponse::build(m_server, m_template, m_data, m_mimeType); + r->set_code(m_httpStatusCode); + return r; + } + + operator std::unique_ptr() const + { + return operator std::unique_ptr(); + } + +private: // data + const InternalServer& m_server; + const RequestContext& m_request; + const int m_httpStatusCode; + const std::string m_mimeType; + const std::string m_template; + kainjow::mustache::data m_data; +}; + +ContentResponseBlueprint make404Response(const InternalServer& server, + const RequestContext& request); + +kainjow::mustache::data make404ResponseData(const std::string& url, + const std::string& details = ""); + + class ItemResponse : public Response { public: ItemResponse(bool verbose, const zim::Item& item, const std::string& mimetype, const ByteRange& byterange); From 668063205c27b6b2343f958e94e2b1894d515e02 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sat, 22 Jan 2022 23:48:01 +0400 Subject: [PATCH 11/20] Enter UrlNotFoundMsg iomanipulator-like class --- src/server/internalServer.cpp | 24 ++++++++++++++++++++++-- src/server/response.cpp | 13 ++++++++----- src/server/response.h | 2 +- test/server.cpp | 6 ------ 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 17e4111be..61b7409e4 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -387,6 +387,25 @@ SuggestionsList_t getSuggestions(SuggestionSearcherCache& cache, const zim::Arch return suggestions; } +namespace +{ + +class UrlNotFoundMsg {}; + +const UrlNotFoundMsg urlNotFoundMsg; + +ContentResponseBlueprint&& operator+(ContentResponseBlueprint&& crb, + UrlNotFoundMsg /*unused*/) +{ + const std::string requestUrl = crb.m_request.get_full_url(); + kainjow::mustache::mustache msgTmpl(R"(The requested URL "{{url}}" was not found on this server.)"); + const auto urlNotFoundMsgText = msgTmpl.render({"url", requestUrl}); + crb.m_data["details"].push_back({"p", urlNotFoundMsgText}); + return std::move(crb); +} + + +} // unnamed namespace std::unique_ptr InternalServer::handle_suggest(const RequestContext& request) { @@ -658,7 +677,7 @@ std::unique_ptr InternalServer::handle_catalog(const RequestContext& r url = request.get_url_part(1); } catch (const std::out_of_range&) { return make404Response(*this, request) - + make404ResponseData(request.get_full_url()); + + urlNotFoundMsg; } if (url == "v2") { @@ -666,7 +685,8 @@ std::unique_ptr InternalServer::handle_catalog(const RequestContext& r } if (url != "searchdescription.xml" && url != "root.xml" && url != "search") { - return Response::build_404(*this, request.get_full_url()); + return make404Response(*this, request) + + urlNotFoundMsg; } if (url == "searchdescription.xml") { diff --git a/src/server/response.cpp b/src/server/response.cpp index 8bcd2bb3a..5a403bf9f 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -112,11 +112,14 @@ std::unique_ptr Response::build_404(const InternalServer& serve ContentResponseBlueprint make404Response(const InternalServer& server, const RequestContext& request) { - return ContentResponseBlueprint(&server, - &request, - MHD_HTTP_NOT_FOUND, - "text/html", - RESOURCE::templates::_404_html); + auto crb = ContentResponseBlueprint(&server, + &request, + MHD_HTTP_NOT_FOUND, + "text/html", + RESOURCE::templates::_404_html); + + kainjow::mustache::list emptyList; + return crb + kainjow::mustache::object{{"details", emptyList}}; } std::unique_ptr Response::build_416(const InternalServer& server, size_t resourceLength) diff --git a/src/server/response.h b/src/server/response.h index fa0d9e42d..f77517581 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -166,7 +166,7 @@ public: // functions return operator std::unique_ptr(); } -private: // data +public: //data const InternalServer& m_server; const RequestContext& m_request; const int m_httpStatusCode; diff --git a/test/server.cpp b/test/server.cpp index 81af4c864..cf57826e6 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -549,9 +549,6 @@ TEST_F(ServerTest, 404WithBodyTesting)

The requested URL "/ROOT/catalog/" was not found on this server.

-

- //EOLWHITESPACEMARKER -

)" }, { /* url */ "/ROOT/catalog/invalid_endpoint", @@ -560,9 +557,6 @@ TEST_F(ServerTest, 404WithBodyTesting)

The requested URL "/ROOT/catalog/invalid_endpoint" was not found on this server.

-

- //EOLWHITESPACEMARKER -

)" }, { /* url */ "/ROOT/invalid-book/whatever", From 89785a259ad52f784c23cf643b4eeb878cd75c15 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sun, 23 Jan 2022 16:04:29 +0400 Subject: [PATCH 12/20] Enter HTTP404HtmlResponse --- src/server/internalServer.cpp | 4 ++-- src/server/response.cpp | 15 +++++++-------- src/server/response.h | 11 +++++------ 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 61b7409e4..597f52dbb 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -676,7 +676,7 @@ std::unique_ptr InternalServer::handle_catalog(const RequestContext& r host = request.get_header("Host"); url = request.get_url_part(1); } catch (const std::out_of_range&) { - return make404Response(*this, request) + return HTTP404HtmlResponse(*this, request) + urlNotFoundMsg; } @@ -685,7 +685,7 @@ std::unique_ptr InternalServer::handle_catalog(const RequestContext& r } if (url != "searchdescription.xml" && url != "root.xml" && url != "search") { - return make404Response(*this, request) + return HTTP404HtmlResponse(*this, request) + urlNotFoundMsg; } diff --git a/src/server/response.cpp b/src/server/response.cpp index 5a403bf9f..42175637c 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -109,17 +109,16 @@ std::unique_ptr Response::build_404(const InternalServer& serve return response; } -ContentResponseBlueprint make404Response(const InternalServer& server, +HTTP404HtmlResponse::HTTP404HtmlResponse(const InternalServer& server, const RequestContext& request) + : ContentResponseBlueprint(&server, + &request, + MHD_HTTP_NOT_FOUND, + "text/html", + RESOURCE::templates::_404_html) { - auto crb = ContentResponseBlueprint(&server, - &request, - MHD_HTTP_NOT_FOUND, - "text/html", - RESOURCE::templates::_404_html); - kainjow::mustache::list emptyList; - return crb + kainjow::mustache::object{{"details", emptyList}}; + this->m_data = kainjow::mustache::object{{"details", emptyList}}; } std::unique_ptr Response::build_416(const InternalServer& server, size_t resourceLength) diff --git a/src/server/response.h b/src/server/response.h index f77517581..fb7cf84b5 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -175,12 +175,11 @@ public: //data kainjow::mustache::data m_data; }; -ContentResponseBlueprint make404Response(const InternalServer& server, - const RequestContext& request); - -kainjow::mustache::data make404ResponseData(const std::string& url, - const std::string& details = ""); - +struct HTTP404HtmlResponse : ContentResponseBlueprint +{ + HTTP404HtmlResponse(const InternalServer& server, + const RequestContext& request); +}; class ItemResponse : public Response { public: From 1a5e2eda0f40ff60a57cc96506df71299f9dd1b1 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sun, 23 Jan 2022 16:09:51 +0400 Subject: [PATCH 13/20] HTTP404HtmlResponse::operator+(UrlNotFoundMsg) --- src/server/internalServer.cpp | 20 -------------------- src/server/response.cpp | 11 +++++++++++ src/server/response.h | 6 ++++++ 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 597f52dbb..5f53b5d54 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -387,26 +387,6 @@ SuggestionsList_t getSuggestions(SuggestionSearcherCache& cache, const zim::Arch return suggestions; } -namespace -{ - -class UrlNotFoundMsg {}; - -const UrlNotFoundMsg urlNotFoundMsg; - -ContentResponseBlueprint&& operator+(ContentResponseBlueprint&& crb, - UrlNotFoundMsg /*unused*/) -{ - const std::string requestUrl = crb.m_request.get_full_url(); - kainjow::mustache::mustache msgTmpl(R"(The requested URL "{{url}}" was not found on this server.)"); - const auto urlNotFoundMsgText = msgTmpl.render({"url", requestUrl}); - crb.m_data["details"].push_back({"p", urlNotFoundMsgText}); - return std::move(crb); -} - - -} // unnamed namespace - std::unique_ptr InternalServer::handle_suggest(const RequestContext& request) { if (m_verbose.load()) { diff --git a/src/server/response.cpp b/src/server/response.cpp index 42175637c..f07a1e6d2 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -109,6 +109,8 @@ std::unique_ptr Response::build_404(const InternalServer& serve return response; } +extern const UrlNotFoundMsg urlNotFoundMsg; + HTTP404HtmlResponse::HTTP404HtmlResponse(const InternalServer& server, const RequestContext& request) : ContentResponseBlueprint(&server, @@ -121,6 +123,15 @@ HTTP404HtmlResponse::HTTP404HtmlResponse(const InternalServer& server, this->m_data = kainjow::mustache::object{{"details", emptyList}}; } +HTTP404HtmlResponse& HTTP404HtmlResponse::operator+(UrlNotFoundMsg /*unused*/) +{ + const std::string requestUrl = m_request.get_full_url(); + kainjow::mustache::mustache msgTmpl(R"(The requested URL "{{url}}" was not found on this server.)"); + const auto urlNotFoundMsgText = msgTmpl.render({"url", requestUrl}); + m_data["details"].push_back({"p", urlNotFoundMsgText}); + return *this; +} + std::unique_ptr Response::build_416(const InternalServer& server, size_t resourceLength) { auto response = Response::build(server); diff --git a/src/server/response.h b/src/server/response.h index fb7cf84b5..7826d3e72 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -175,10 +175,16 @@ public: //data kainjow::mustache::data m_data; }; +class UrlNotFoundMsg {}; + +extern const UrlNotFoundMsg urlNotFoundMsg; + struct HTTP404HtmlResponse : ContentResponseBlueprint { HTTP404HtmlResponse(const InternalServer& server, const RequestContext& request); + + HTTP404HtmlResponse& operator+(UrlNotFoundMsg /*unused*/); }; class ItemResponse : public Response { From d5ae92e4e239e3780b29510354ba2a19d3a1c9c6 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sun, 23 Jan 2022 21:57:10 +0400 Subject: [PATCH 14/20] More uses of HTTP404HtmlResponse --- src/server/internalServer.cpp | 18 ++++++++++++------ src/server/internalServer_catalog_v2.cpp | 12 ++++++++---- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 5f53b5d54..bc14851f9 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -278,8 +278,10 @@ MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection, std::unique_ptr InternalServer::handle_request(const RequestContext& request) { try { - if (! request.is_valid_url()) - return Response::build_404(*this, request.get_full_url()); + if (! request.is_valid_url()) { + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg; + } const ETag etag = get_matching_if_none_match_etag(request); if ( etag ) @@ -476,7 +478,8 @@ std::unique_ptr InternalServer::handle_skin(const RequestContext& requ response->set_cacheable(); return std::move(response); } catch (const ResourceNotFound& e) { - return Response::build_404(*this, request.get_full_url()); + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg; } } @@ -636,8 +639,10 @@ std::unique_ptr InternalServer::handle_captured_external(const Request source = kiwix::urlDecode(request.get_argument("source")); } catch (const std::out_of_range& e) {} - if (source.empty()) - return Response::build_404(*this, request.get_full_url()); + if (source.empty()) { + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg; + } auto data = get_default_data(); data.set("source", source); @@ -855,7 +860,8 @@ std::unique_ptr InternalServer::handle_raw(const RequestContext& reque bookName = request.get_url_part(1); kind = request.get_url_part(2); } catch (const std::out_of_range& e) { - return Response::build_404(*this, request.get_full_url()); + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg; } if (kind != "meta" && kind!= "content") { diff --git a/src/server/internalServer_catalog_v2.cpp b/src/server/internalServer_catalog_v2.cpp index cd678ba55..a5c9f49c8 100644 --- a/src/server/internalServer_catalog_v2.cpp +++ b/src/server/internalServer_catalog_v2.cpp @@ -43,7 +43,8 @@ std::unique_ptr InternalServer::handle_catalog_v2(const RequestContext try { url = request.get_url_part(2); } catch (const std::out_of_range&) { - return Response::build_404(*this, request.get_full_url()); + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg; } if (url == "root.xml") { @@ -69,7 +70,8 @@ std::unique_ptr InternalServer::handle_catalog_v2(const RequestContext } else if (url == "illustration") { return handle_catalog_v2_illustration(request); } else { - return Response::build_404(*this, request.get_full_url()); + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg; } } @@ -110,7 +112,8 @@ std::unique_ptr InternalServer::handle_catalog_v2_complete_entry(const try { mp_library->getBookById(entryId); } catch (const std::out_of_range&) { - return Response::build_404(*this, request.get_full_url()); + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg; } OPDSDumper opdsDumper(mp_library); @@ -158,7 +161,8 @@ std::unique_ptr InternalServer::handle_catalog_v2_illustration(const R auto illustration = book.getIllustration(size); return ContentResponse::build(*this, illustration->getData(), illustration->mimeType); } catch(...) { - return Response::build_404(*this, request.get_full_url()); + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg; } } From 48d377ca4401cd19871d6982d65a340a8bc0c7d9 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Thu, 24 Mar 2022 18:57:26 +0400 Subject: [PATCH 15/20] HTTP404HtmlResponse::operator+(const std::string&) --- src/server/internalServer.cpp | 4 +++- src/server/response.cpp | 8 ++++++-- src/server/response.h | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index bc14851f9..f94a82990 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -877,7 +877,9 @@ std::unique_ptr InternalServer::handle_raw(const RequestContext& reque if (archive == nullptr) { const std::string error_details = "No such book: " + bookName; - return Response::build_404(*this, request.get_full_url(), error_details); + return HTTP404HtmlResponse(*this, request) + + urlNotFoundMsg + + error_details; } // Remove the beggining of the path: diff --git a/src/server/response.cpp b/src/server/response.cpp index f07a1e6d2..da6fe00b7 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -127,8 +127,12 @@ HTTP404HtmlResponse& HTTP404HtmlResponse::operator+(UrlNotFoundMsg /*unused*/) { const std::string requestUrl = m_request.get_full_url(); kainjow::mustache::mustache msgTmpl(R"(The requested URL "{{url}}" was not found on this server.)"); - const auto urlNotFoundMsgText = msgTmpl.render({"url", requestUrl}); - m_data["details"].push_back({"p", urlNotFoundMsgText}); + return *this + msgTmpl.render({"url", requestUrl}); +} + +HTTP404HtmlResponse& HTTP404HtmlResponse::operator+(const std::string& msg) +{ + m_data["details"].push_back({"p", msg}); return *this; } diff --git a/src/server/response.h b/src/server/response.h index 7826d3e72..ee45e1d3f 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -185,6 +185,7 @@ struct HTTP404HtmlResponse : ContentResponseBlueprint const RequestContext& request); HTTP404HtmlResponse& operator+(UrlNotFoundMsg /*unused*/); + HTTP404HtmlResponse& operator+(const std::string& errorDetails); }; class ItemResponse : public Response { From 9bc09a815c54f3e124f306a9e40e2b62cc3e0c0d Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Thu, 24 Mar 2022 19:10:07 +0400 Subject: [PATCH 16/20] noSuchBookErrorMsg() --- src/server/internalServer.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index f94a82990..1fdb47be5 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -389,6 +389,16 @@ SuggestionsList_t getSuggestions(SuggestionSearcherCache& cache, const zim::Arch return suggestions; } +namespace +{ + +std::string noSuchBookErrorMsg(const std::string& bookName) +{ + return "No such book: " + bookName; +} + +} // unnamed namespace + std::unique_ptr InternalServer::handle_suggest(const RequestContext& request) { if (m_verbose.load()) { @@ -406,7 +416,7 @@ std::unique_ptr InternalServer::handle_suggest(const RequestContext& r } if (archive == nullptr) { - const std::string error_details = "No such book: " + bookName; + const std::string error_details = noSuchBookErrorMsg(bookName); auto response = Response::build_404(*this, "", error_details); return withTaskbarInfo(bookName, nullptr, std::move(response)); } @@ -617,7 +627,7 @@ std::unique_ptr InternalServer::handle_random(const RequestContext& re } if (archive == nullptr) { - const std::string error_details = "No such book: " + bookName; + const std::string error_details = noSuchBookErrorMsg(bookName); auto response = Response::build_404(*this, "", error_details); return withTaskbarInfo(bookName, nullptr, std::move(response)); } @@ -876,10 +886,9 @@ std::unique_ptr InternalServer::handle_raw(const RequestContext& reque } catch (const std::out_of_range& e) {} if (archive == nullptr) { - const std::string error_details = "No such book: " + bookName; return HTTP404HtmlResponse(*this, request) + urlNotFoundMsg - + error_details; + + noSuchBookErrorMsg(bookName); } // Remove the beggining of the path: From 0ecbdbcf636110933d90c5680117fe3ade86f53f Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Thu, 24 Mar 2022 19:26:25 +0400 Subject: [PATCH 17/20] Enter TaskbarInfo After this change it's time to say thank you and good-bye to `withTaskbarInfo()`. But it will take a while. --- src/server/internalServer.cpp | 6 +++--- src/server/response.cpp | 14 ++++++++++++++ src/server/response.h | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 1fdb47be5..536695416 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -627,9 +627,9 @@ std::unique_ptr InternalServer::handle_random(const RequestContext& re } if (archive == nullptr) { - const std::string error_details = noSuchBookErrorMsg(bookName); - auto response = Response::build_404(*this, "", error_details); - return withTaskbarInfo(bookName, nullptr, std::move(response)); + return HTTP404HtmlResponse(*this, request) + + noSuchBookErrorMsg(bookName) + + TaskbarInfo(bookName); } try { diff --git a/src/server/response.cpp b/src/server/response.cpp index da6fe00b7..e6df8db1b 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -136,6 +136,20 @@ HTTP404HtmlResponse& HTTP404HtmlResponse::operator+(const std::string& msg) return *this; } +HTTP404HtmlResponse& HTTP404HtmlResponse::operator+(const TaskbarInfo& taskbarInfo) +{ + this->taskbarInfo.reset(new TaskbarInfo(taskbarInfo)); + return *this; +} + +std::unique_ptr HTTP404HtmlResponse::generateResponseObject() const +{ + auto r = ContentResponseBlueprint::generateResponseObject(); + return taskbarInfo + ? withTaskbarInfo(taskbarInfo->bookName, taskbarInfo->archive, std::move(r)) + : std::move(r); +} + std::unique_ptr Response::build_416(const InternalServer& server, size_t resourceLength) { auto response = Response::build(server); diff --git a/src/server/response.h b/src/server/response.h index ee45e1d3f..e2161fb72 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -148,6 +148,8 @@ public: // functions , m_template(templateStr) {} + virtual ~ContentResponseBlueprint() = default; + ContentResponseBlueprint& operator+(kainjow::mustache::data&& data) { this->m_data = std::move(data); @@ -155,6 +157,11 @@ public: // functions } operator std::unique_ptr() const + { + return generateResponseObject(); + } + + virtual std::unique_ptr generateResponseObject() const { auto r = ContentResponse::build(m_server, m_template, m_data, m_mimeType); r->set_code(m_httpStatusCode); @@ -179,6 +186,17 @@ class UrlNotFoundMsg {}; extern const UrlNotFoundMsg urlNotFoundMsg; +struct TaskbarInfo +{ + const std::string bookName; + const zim::Archive* const archive; + + TaskbarInfo(const std::string& bookName, const zim::Archive* a = nullptr) + : bookName(bookName) + , archive(a) + {} +}; + struct HTTP404HtmlResponse : ContentResponseBlueprint { HTTP404HtmlResponse(const InternalServer& server, @@ -186,6 +204,11 @@ struct HTTP404HtmlResponse : ContentResponseBlueprint HTTP404HtmlResponse& operator+(UrlNotFoundMsg /*unused*/); HTTP404HtmlResponse& operator+(const std::string& errorDetails); + HTTP404HtmlResponse& operator+(const TaskbarInfo& taskbarInfo); + + std::unique_ptr generateResponseObject() const override; + + std::unique_ptr taskbarInfo; }; class ItemResponse : public Response { From 0eb8f09f79b2561ecc5b41670f2529294a7deb63 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Thu, 24 Mar 2022 19:27:40 +0400 Subject: [PATCH 18/20] One more victory of HTTP404HtmlResponse One more instance of `Response::build_404()` & `withTaskbarInfo()` was taken over by `HTTP404HtmlResponse`. --- src/server/internalServer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 536695416..baffc6738 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -416,9 +416,9 @@ std::unique_ptr InternalServer::handle_suggest(const RequestContext& r } if (archive == nullptr) { - const std::string error_details = noSuchBookErrorMsg(bookName); - auto response = Response::build_404(*this, "", error_details); - return withTaskbarInfo(bookName, nullptr, std::move(response)); + return HTTP404HtmlResponse(*this, request) + + noSuchBookErrorMsg(bookName) + + TaskbarInfo(bookName); } const auto queryString = request.get_optional_param("term", std::string()); From 2da8ea1650d27c03c1aa3bc49593e8843377336d Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Sun, 23 Jan 2022 22:50:59 +0400 Subject: [PATCH 19/20] Moved function definition to cpp --- src/server/response.cpp | 7 +++++++ src/server/response.h | 10 +++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/server/response.cpp b/src/server/response.cpp index e6df8db1b..9c049900c 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -111,6 +111,13 @@ std::unique_ptr Response::build_404(const InternalServer& serve extern const UrlNotFoundMsg urlNotFoundMsg; +std::unique_ptr ContentResponseBlueprint::generateResponseObject() const +{ + auto r = ContentResponse::build(m_server, m_template, m_data, m_mimeType); + r->set_code(m_httpStatusCode); + return r; +} + HTTP404HtmlResponse::HTTP404HtmlResponse(const InternalServer& server, const RequestContext& request) : ContentResponseBlueprint(&server, diff --git a/src/server/response.h b/src/server/response.h index e2161fb72..c0654da1a 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -161,18 +161,14 @@ public: // functions return generateResponseObject(); } - virtual std::unique_ptr generateResponseObject() const - { - auto r = ContentResponse::build(m_server, m_template, m_data, m_mimeType); - r->set_code(m_httpStatusCode); - return r; - } - operator std::unique_ptr() const { return operator std::unique_ptr(); } +protected: // functions + virtual std::unique_ptr generateResponseObject() const; + public: //data const InternalServer& m_server; const RequestContext& m_request; From ec2e10b40eac7815bb92c2a5611ad5a12f27d196 Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Thu, 24 Mar 2022 20:04:01 +0400 Subject: [PATCH 20/20] Moved taskbarInfo into ContentResponseBlueprint --- src/server/response.cpp | 16 +++++----------- src/server/response.h | 32 ++++++++++++++++---------------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/server/response.cpp b/src/server/response.cpp index 9c049900c..50a66c344 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -115,7 +115,9 @@ std::unique_ptr ContentResponseBlueprint::generateResponseObjec { auto r = ContentResponse::build(m_server, m_template, m_data, m_mimeType); r->set_code(m_httpStatusCode); - return r; + return m_taskbarInfo + ? withTaskbarInfo(m_taskbarInfo->bookName, m_taskbarInfo->archive, std::move(r)) + : std::move(r); } HTTP404HtmlResponse::HTTP404HtmlResponse(const InternalServer& server, @@ -143,20 +145,12 @@ HTTP404HtmlResponse& HTTP404HtmlResponse::operator+(const std::string& msg) return *this; } -HTTP404HtmlResponse& HTTP404HtmlResponse::operator+(const TaskbarInfo& taskbarInfo) +ContentResponseBlueprint& ContentResponseBlueprint::operator+(const TaskbarInfo& taskbarInfo) { - this->taskbarInfo.reset(new TaskbarInfo(taskbarInfo)); + this->m_taskbarInfo.reset(new TaskbarInfo(taskbarInfo)); return *this; } -std::unique_ptr HTTP404HtmlResponse::generateResponseObject() const -{ - auto r = ContentResponseBlueprint::generateResponseObject(); - return taskbarInfo - ? withTaskbarInfo(taskbarInfo->bookName, taskbarInfo->archive, std::move(r)) - : std::move(r); -} - std::unique_ptr Response::build_416(const InternalServer& server, size_t resourceLength) { auto response = Response::build(server); diff --git a/src/server/response.h b/src/server/response.h index c0654da1a..b10524bc8 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -129,6 +129,17 @@ class ContentResponse : public Response { std::string m_bookTitle; }; +struct TaskbarInfo +{ + const std::string bookName; + const zim::Archive* const archive; + + TaskbarInfo(const std::string& bookName, const zim::Archive* a = nullptr) + : bookName(bookName) + , archive(a) + {} +}; + std::unique_ptr withTaskbarInfo(const std::string& bookName, const zim::Archive* archive, std::unique_ptr r); @@ -166,6 +177,9 @@ public: // functions return operator std::unique_ptr(); } + + ContentResponseBlueprint& operator+(const TaskbarInfo& taskbarInfo); + protected: // functions virtual std::unique_ptr generateResponseObject() const; @@ -176,35 +190,21 @@ public: //data const std::string m_mimeType; const std::string m_template; kainjow::mustache::data m_data; + std::unique_ptr m_taskbarInfo; }; class UrlNotFoundMsg {}; extern const UrlNotFoundMsg urlNotFoundMsg; -struct TaskbarInfo -{ - const std::string bookName; - const zim::Archive* const archive; - - TaskbarInfo(const std::string& bookName, const zim::Archive* a = nullptr) - : bookName(bookName) - , archive(a) - {} -}; - struct HTTP404HtmlResponse : ContentResponseBlueprint { HTTP404HtmlResponse(const InternalServer& server, const RequestContext& request); + using ContentResponseBlueprint::operator+; HTTP404HtmlResponse& operator+(UrlNotFoundMsg /*unused*/); HTTP404HtmlResponse& operator+(const std::string& errorDetails); - HTTP404HtmlResponse& operator+(const TaskbarInfo& taskbarInfo); - - std::unique_ptr generateResponseObject() const override; - - std::unique_ptr taskbarInfo; }; class ItemResponse : public Response {