From eee621d15ba3f41fc57bf5a804ee2f5d321bedb5 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Wed, 29 Jul 2020 15:38:19 +0200 Subject: [PATCH] Move small utilities method to create response in Response class. --- src/server/internalServer.cpp | 93 +++++++++-------------------------- src/server/internalServer.h | 4 +- src/server/response.cpp | 66 +++++++++++++++++++------ src/server/response.h | 11 ++--- 4 files changed, 79 insertions(+), 95 deletions(-) diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 4f11b3d77..140dc1e94 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -230,24 +230,15 @@ MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection, return ret; } -std::unique_ptr InternalServer::build_304(const RequestContext& request, const ETag& etag) const -{ - // This is just to set the m_mode. - auto response = ContentResponse::build(*this, "", ""); - response->set_code(MHD_HTTP_NOT_MODIFIED); - response->set_etag(etag); - return response; -} - std::unique_ptr InternalServer::handle_request(const RequestContext& request) { try { if (! request.is_valid_url()) - return build_404(request, ""); + return Response::build_404(*this, request, ""); const ETag etag = get_matching_if_none_match_etag(request); if ( etag ) - return build_304(request, etag); + return Response::build_304(*this, etag); if (kiwix::startsWith(request.get_url(), "/skin/")) return handle_skin(request); @@ -273,10 +264,10 @@ std::unique_ptr InternalServer::handle_request(const RequestContext& r return handle_content(request); } catch (std::exception& e) { fprintf(stderr, "===== Unhandled error : %s\n", e.what()); - return build_500(e.what()); + return Response::build_500(*this, e.what()); } catch (...) { fprintf(stderr, "===== Unhandled unknown error\n"); - return build_500("Unknown error"); + return Response::build_500(*this, "Unknown error"); } } @@ -287,34 +278,6 @@ MustacheData InternalServer::get_default_data() const return data; } -std::unique_ptr InternalServer::build_404(const RequestContext& request, - const std::string& bookName) -{ - MustacheData results; - results.set("url", request.get_full_url()); - - auto response = Response::build(*this); - response->set_template(RESOURCE::templates::_404_html, results); - response->set_mimeType("text/html"); - response->set_code(MHD_HTTP_NOT_FOUND); - response->set_compress(true); - response->set_taskbar(bookName, ""); - - return response; -} - -std::unique_ptr InternalServer::build_500(const std::string& msg) -{ - MustacheData data; - data.set("error", msg); - std::unique_ptr response( - new Response(m_root, true, false, false, false)); - response->set_template(RESOURCE::templates::_500_html, data); - response->set_mimeType("text/html"); - response->set_code(MHD_HTTP_INTERNAL_SERVER_ERROR); - return response; -} - MustacheData InternalServer::homepage_data() const { auto data = get_default_data(); @@ -359,9 +322,7 @@ InternalServer::get_matching_if_none_match_etag(const RequestContext& r) const std::unique_ptr InternalServer::build_homepage(const RequestContext& request) { - auto response = Response::build(*this); - response->set_template(RESOURCE::templates::index_html, homepage_data()); - response->set_mimeType("text/html; charset=utf-8"); + auto response = ContentResponse::build(*this, RESOURCE::templates::index_html, homepage_data(), "text/html; charset=utf-8"); response->set_compress(true); return response; } @@ -378,11 +339,11 @@ std::unique_ptr InternalServer::handle_meta(const RequestContext& requ meta_name = request.get_argument("name"); reader = mp_library->getReaderById(bookId); } catch (const std::out_of_range& e) { - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } if (reader == nullptr) { - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } std::string content; @@ -407,7 +368,7 @@ std::unique_ptr InternalServer::handle_meta(const RequestContext& requ } else if (meta_name == "favicon") { reader->getFavicon(content, mimeType); } else { - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } auto response = ContentResponse::build(*this, content, mimeType); @@ -437,7 +398,7 @@ std::unique_ptr InternalServer::handle_suggest(const RequestContext& r term = request.get_argument("term"); reader = mp_library->getReaderById(bookId); } catch (const std::out_of_range&) { - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } if (m_verbose.load()) { @@ -474,9 +435,7 @@ std::unique_ptr InternalServer::handle_suggest(const RequestContext& r auto data = get_default_data(); data.set("suggestions", results); - auto response = Response::build(*this); - response->set_template(RESOURCE::templates::suggestion_json, data); - response->set_mimeType("application/json; charset=utf-8"); + auto response = ContentResponse::build(*this, RESOURCE::templates::suggestion_json, data, "application/json; charset=utf-8"); response->set_compress(true); return response; } @@ -497,7 +456,7 @@ std::unique_ptr InternalServer::handle_skin(const RequestContext& requ response->set_cacheable(); return response; } catch (const ResourceNotFound& e) { - return build_404(request, ""); + return Response::build_404(*this, request, ""); } } @@ -566,11 +525,9 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re || (patternString.empty() && ! has_geo_query) ) { auto data = get_default_data(); data.set("pattern", encodeDiples(patternString)); - auto response = Response::build(*this); - response->set_mimeType("text/html; charset=utf-8"); + auto response = ContentResponse::build(*this, RESOURCE::templates::no_search_result_html, data, "text/html; charset=utf-8"); response->set_taskbar(bookName, reader ? reader->getTitle() : ""); response->set_compress(true); - response->set_template(RESOURCE::templates::no_search_result_html, data); response->set_code(MHD_HTTP_NOT_FOUND); return response; } @@ -632,7 +589,7 @@ std::unique_ptr InternalServer::handle_search(const RequestContext& re return response; } catch (const std::exception& e) { std::cerr << e.what() << std::endl; - return build_500(e.what()); + return Response::build_500(*this, e.what()); } } @@ -650,18 +607,18 @@ std::unique_ptr InternalServer::handle_random(const RequestContext& re bookId = mp_nameMapper->getIdForName(bookName); reader = mp_library->getReaderById(bookId); } catch (const std::out_of_range&) { - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } if (reader == nullptr) { - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } try { auto entry = reader->getRandomPage(); return build_redirect(bookName, entry.getFinalEntry()); } catch(kiwix::NoEntry& e) { - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } } @@ -673,13 +630,11 @@ std::unique_ptr InternalServer::handle_captured_external(const Request } catch (const std::out_of_range& e) {} if (source.empty()) - return build_404(request, ""); + return Response::build_404(*this, request, ""); auto data = get_default_data(); data.set("source", source); - auto response = Response::build(*this); - response->set_template(RESOURCE::templates::captured_external_html, data); - response->set_mimeType("text/html; charset=utf-8"); + auto response = ContentResponse::build(*this, RESOURCE::templates::captured_external_html, data, "text/html; charset=utf-8"); response->set_compress(true); return response; } @@ -696,18 +651,16 @@ 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 build_404(request, ""); + return Response::build_404(*this, request, ""); } if (url != "searchdescription.xml" && url != "root.xml" && url != "search") { - return build_404(request, ""); + return Response::build_404(*this, request, ""); } if (url == "searchdescription.xml") { - auto response = Response::build(*this); + auto response = ContentResponse::build(*this, RESOURCE::opensearchdescription_xml, get_default_data(), "application/opensearchdescription+xml"); response->set_compress(true); - response->set_template(RESOURCE::opensearchdescription_xml, get_default_data()); - response->set_mimeType("application/opensearchdescription+xml"); return response; } @@ -816,7 +769,7 @@ std::unique_ptr InternalServer::handle_content(const RequestContext& r const std::shared_ptr reader = get_reader(bookName); if (reader == nullptr) { - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } auto urlStr = request.get_url().substr(bookName.size()+1); @@ -837,7 +790,7 @@ std::unique_ptr InternalServer::handle_content(const RequestContext& r if (m_verbose.load()) printf("Failed to find %s\n", urlStr.c_str()); - return build_404(request, bookName); + return Response::build_404(*this, request, bookName); } auto response = EntryResponse::build(*this, request, entry); diff --git a/src/server/internalServer.h b/src/server/internalServer.h index 7e27962fe..21d773548 100644 --- a/src/server/internalServer.h +++ b/src/server/internalServer.h @@ -68,9 +68,6 @@ class InternalServer { private: // functions std::unique_ptr handle_request(const RequestContext& request); - std::unique_ptr build_500(const std::string& msg); - std::unique_ptr build_404(const RequestContext& request, const std::string& zimName); - std::unique_ptr build_304(const RequestContext& request, const ETag& etag) const; std::unique_ptr build_redirect(const std::string& bookName, const kiwix::Entry& entry) const; std::unique_ptr build_homepage(const RequestContext& request); std::unique_ptr handle_skin(const RequestContext& request); @@ -109,6 +106,7 @@ class InternalServer { friend std::unique_ptr RedirectionResponse::build(const InternalServer& server, const std::string& redirectionUrl); friend std::unique_ptr ContentResponse::build(const InternalServer& server, const std::string& content, const std::string& mimetype); friend std::unique_ptr EntryResponse::build(const InternalServer& server, const RequestContext& request, const Entry& entry); + friend std::unique_ptr Response::build_500(const InternalServer& server, const std::string& msg); }; diff --git a/src/server/response.cpp b/src/server/response.cpp index f1293f059..7c23d192b 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -22,6 +22,17 @@ namespace { // some utilities +std::string render_template(const std::string& template_str, kainjow::mustache::data data) +{ + kainjow::mustache::mustache tmpl(template_str); + kainjow::mustache::data urlencode{kainjow::mustache::lambda2{ + [](const std::string& str,const kainjow::mustache::renderer& r) { return urlEncode(r(str), true); }}}; + data.set("urlencoded", urlencode); + std::stringstream ss; + tmpl.render(data, [&ss](const std::string& str) { ss << str; }); + return ss.str(); +} + std::string get_mime_type(const kiwix::Entry& entry) { try { @@ -45,6 +56,7 @@ bool is_compressible_mime_type(const std::string& mimeType) Response::Response(const std::string& root, bool verbose, bool withTaskbar, bool withLibraryButton, bool blockExternalLinks) : m_verbose(verbose), + m_mode(ResponseMode::RAW_CONTENT), m_root(root), m_content(""), m_mimeType(""), @@ -67,6 +79,39 @@ std::unique_ptr Response::build(const InternalServer& server) server.m_blockExternalLinks)); } +std::unique_ptr Response::build_304(const InternalServer& server, const ETag& etag) +{ + auto response = Response::build(server); + response->set_code(MHD_HTTP_NOT_MODIFIED); + response->m_etag = etag; + return response; +} + +std::unique_ptr Response::build_404(const InternalServer& server, const RequestContext& request, const std::string& bookName) +{ + MustacheData results; + results.set("url", request.get_full_url()); + + auto response = ContentResponse::build(server, RESOURCE::templates::_404_html, results, "text/html"); + response->set_code(MHD_HTTP_NOT_FOUND); + response->set_compress(true); + response->set_taskbar(bookName, ""); + + return response; +} + +std::unique_ptr Response::build_500(const InternalServer& server, const std::string& msg) +{ + MustacheData data; + data.set("error", msg); + auto content = render_template(RESOURCE::templates::_500_html, data); + std::unique_ptr response ( + new ContentResponse(server.m_root, true, false, false, false, content, "text/html")); + response->set_code(MHD_HTTP_INTERNAL_SERVER_ERROR); + return response; +} + + static MHD_Result print_key_value (void *cls, enum MHD_ValueKind kind, const char *key, const char *value) @@ -124,16 +169,6 @@ void print_response_info(int retCode, MHD_Response* response) } -std::string render_template(const std::string& template_str, kainjow::mustache::data data) -{ - kainjow::mustache::mustache tmpl(template_str); - kainjow::mustache::data urlencode{kainjow::mustache::lambda2{ - [](const std::string& str,const kainjow::mustache::renderer& r) { return urlEncode(r(str), true); }}}; - data.set("urlencoded", urlencode); - std::stringstream ss; - tmpl.render(data, [&ss](const std::string& str) { ss << str; }); - return ss.str(); -} void Response::introduce_taskbar() @@ -291,11 +326,6 @@ MHD_Result Response::send(const RequestContext& request, MHD_Connection* connect return ret; } -void Response::set_template(const std::string& template_str, kainjow::mustache::data data) { - m_content = render_template(template_str, data); - m_mode = ResponseMode::RAW_CONTENT; -} - void Response::set_taskbar(const std::string& bookName, const std::string& bookTitle) { m_bookName = bookName; @@ -348,6 +378,12 @@ std::unique_ptr ContentResponse::build(const InternalServer& server, c mimetype)); } +std::unique_ptr ContentResponse::build(const InternalServer& server, const std::string& template_str, kainjow::mustache::data data, const std::string& mimetype) { + auto content = render_template(template_str, data); + return ContentResponse::build(server, content, mimetype); +} + + EntryResponse::EntryResponse(const std::string& root, bool verbose, bool withTaskbar, bool withLibraryButton, bool blockExternalLinks, const Entry& entry, const std::string& mimetype, const ByteRange& byterange) : Response(root, verbose, withTaskbar, withLibraryButton, blockExternalLinks), m_entry(entry) diff --git a/src/server/response.h b/src/server/response.h index 9134e85ba..dd9d82ebc 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -50,16 +50,15 @@ class Response { virtual ~Response() = default; 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_500(const InternalServer& server, const std::string& msg); MHD_Result send(const RequestContext& request, MHD_Connection* connection); - void set_template(const std::string& template_str, kainjow::mustache::data data); - - void set_mimeType(const std::string& mimeType) { m_mimeType = mimeType; } void set_code(int code) { m_returnCode = code; } void set_cacheable() { m_etag.set_option(ETag::CACHEABLE_ENTITY); } void set_server_id(const std::string& id) { m_etag.set_server_id(id); } - void set_etag(const ETag& etag) { m_etag = etag; } void set_compress(bool compress) { m_compress = compress; } void set_taskbar(const std::string& bookName, const std::string& bookTitle); @@ -100,7 +99,6 @@ class Response { class RedirectionResponse : public Response { public: RedirectionResponse(const std::string& root, bool verbose, bool withTaskbar, bool withLibraryButton, bool blockExternalLinks, const std::string& redirectionUrl); - static std::unique_ptr build(const InternalServer& server, const std::string& redirectionUrl); @@ -113,14 +111,13 @@ class RedirectionResponse : public Response { class ContentResponse : public Response { public: ContentResponse(const std::string& root, bool verbose, bool withTaskbar, bool withLibraryButton, bool blockExternalLinks, const std::string& content, const std::string& mimetype); - static std::unique_ptr build(const InternalServer& server, const std::string& content, const std::string& mimetype); + static std::unique_ptr build(const InternalServer& server, const std::string& template_str, kainjow::mustache::data data, const std::string& mimetype); }; class EntryResponse : public Response { public: EntryResponse(const std::string& root, bool verbose, bool withTaskbar, bool withLibraryButton, bool blockExternalLinks, const Entry& entry, const std::string& mimetype, const ByteRange& byterange); - static std::unique_ptr build(const InternalServer& server, const RequestContext& request, const Entry& entry); private: