diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index d364e414..5806d7da 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -709,12 +709,10 @@ std::unique_ptr InternalServer::handle_request(const RequestContext& r return Response::build_redirect(contentUrl + query); } catch (std::exception& e) { fprintf(stderr, "===== Unhandled error : %s\n", e.what()); - return HTTP500Response(request) - + ParameterizedMessage("non-translated-text", {{"MSG", e.what()}}); + return HTTP500Response(request, m_root, request.get_full_url(), e.what()); } catch (...) { fprintf(stderr, "===== Unhandled unknown error\n"); - return HTTP500Response(request) - + nonParameterizedMessage("unknown-error"); + return HTTP500Response(request, m_root, request.get_full_url()); } } diff --git a/src/server/response.cpp b/src/server/response.cpp index aa3eadb1..d4caf8f3 100644 --- a/src/server/response.cpp +++ b/src/server/response.cpp @@ -491,15 +491,24 @@ HTTP400Response::HTTP400Response(const RequestContext& request) *this += ParameterizedMessage("invalid-request", {{"url", requestUrl}}); } -HTTP500Response::HTTP500Response(const RequestContext& request) - : HTTPErrorResponse(request, - MHD_HTTP_INTERNAL_SERVER_ERROR, - "500-page-title", - "500-page-heading", - std::string(), - /*includeKiwixResponseData=*/true) +HTTP500Response::HTTP500Response(const RequestContext& request, + const std::string& root, + const std::string& urlPath, + const std::string& /*errorText*/) + : ContentResponseBlueprint(&request, + MHD_HTTP_INTERNAL_SERVER_ERROR, + "text/html; charset=utf-8", + RESOURCE::templates::sexy500_html, + /*includeKiwixResponseData=*/true) { - *this += nonParameterizedMessage("500-page-text"); + *this->m_data = Data(Data::Object{ + {"root", root }, + {"url_path", urlPath}, + {"PAGE_TITLE", Data::fromMsgId("500-page-title")}, + {"PAGE_HEADING", Data::fromMsgId("500-page-heading")}, + {"PAGE_TEXT", Data::fromMsgId("500-page-text")}, + {"500_img_text", Data::fromMsgId("500-img-text")}, + }); } std::unique_ptr Response::build_416(size_t resourceLength) diff --git a/src/server/response.h b/src/server/response.h index 597caa9d..e57cab7f 100644 --- a/src/server/response.h +++ b/src/server/response.h @@ -180,9 +180,12 @@ struct HTTP400Response : HTTPErrorResponse explicit HTTP400Response(const RequestContext& request); }; -struct HTTP500Response : HTTPErrorResponse +struct HTTP500Response : ContentResponseBlueprint { - explicit HTTP500Response(const RequestContext& request); + HTTP500Response(const RequestContext& request, + const std::string& root, + const std::string& urlPath, + const std::string& error = ""); }; class ItemResponse : public Response { diff --git a/static/resources_list.txt b/static/resources_list.txt index 15d0624d..d0bff6af 100644 --- a/static/resources_list.txt +++ b/static/resources_list.txt @@ -2,6 +2,7 @@ skin/caret.png skin/bittorrent.png skin/magnet.png skin/404.svg +skin/500.svg skin/blocklink.svg skin/feed.svg skin/langSelector.svg @@ -47,6 +48,7 @@ templates/viewer_settings.js templates/no_js_library_page.html templates/no_js_download.html templates/sexy404.html +templates/sexy500.html opensearchdescription.xml ft_opensearchdescription.xml catalog_v2_searchdescription.xml diff --git a/static/skin/500.svg b/static/skin/500.svg new file mode 100644 index 00000000..3a295d10 --- /dev/null +++ b/static/skin/500.svg @@ -0,0 +1 @@ + diff --git a/static/skin/i18n/en.json b/static/skin/i18n/en.json index 0212e36c..03703786 100644 --- a/static/skin/i18n/en.json +++ b/static/skin/i18n/en.json @@ -30,8 +30,9 @@ , "404-advice.p4": "Look for keywords or titles related to the information you're seeking" , "404-advice.p5": "This approach should help you locate the desired content, even if the original link isn't working properly." , "500-page-title" : "Internal Server Error" - , "500-page-heading" : "Internal Server Error" - , "500-page-text": "An internal server error occured. We are sorry about that :/" + , "500-page-heading" : "Oops. Page isn't working." + , "500-page-text": "The requested path cannot be properly delivered:" + , "500-img-text": "Page isn't working" , "external-link-detected" : "External Link Detected" , "caution-warning" : "Caution!" , "external-link-intro" : "You are about to leave Kiwix's ZIM reader to go online to" diff --git a/static/skin/i18n/qqq.json b/static/skin/i18n/qqq.json index 0c7b591d..d17e5722 100644 --- a/static/skin/i18n/qqq.json +++ b/static/skin/i18n/qqq.json @@ -36,6 +36,7 @@ "500-page-title": "Title of the 500 error page", "500-page-heading": "Heading of the 500 error page", "500-page-text": "Text of the 500 error page", + "500-img-text": "Fallback text for the image on the 500 error page", "external-link-detected": "Title & heading of the external link blocker page", "caution-warning": "Warning of action that shouldn't be carried out carelessly", "external-link-intro": "Message introducing the external link (to be followed by the actual link)", diff --git a/static/skin/i18n/test.json b/static/skin/i18n/test.json index 98f5a9e8..daa2b653 100644 --- a/static/skin/i18n/test.json +++ b/static/skin/i18n/test.json @@ -22,6 +22,10 @@ , "404-advice.p3": "[I18N TESTING] Check the spelling of the URL path" , "404-advice.p4": "[I18N TESTING] Press the dice button" , "404-advice.p5": "Good luck! [I18N TESTING]" + , "500-page-title" : "[I18N] Internal Server Error [TESTING]" + , "500-page-heading" : "Oops. [I18N] Page isn't [TESTING] working." + , "500-page-text": "The requested path [I18N TESTING] cannot be properly delivered:" + , "500-img-text": "Page [I18N] isn't [TESTING] working" , "external-link-detected" : "External [I18] Link [TESTING] Detected" , "caution-warning" : "[I18N] C5n! [TESTING]" , "external-link-intro" : "[I18N TESTING] The following link may lead you to a place from which you won't ever be able to return" diff --git a/static/templates/sexy500.html b/static/templates/sexy500.html new file mode 100644 index 00000000..2ea67c28 --- /dev/null +++ b/static/templates/sexy500.html @@ -0,0 +1,26 @@ + + + + + + {{PAGE_TITLE}} + + + + +
+ {{500_img_text}} +
+
+

{{PAGE_HEADING}}

+

{{PAGE_TEXT}}

+

{{url_path}}

+
+ + diff --git a/test/server.cpp b/test/server.cpp index d9a14481..a7c63ca4 100644 --- a/test/server.cpp +++ b/test/server.cpp @@ -112,6 +112,8 @@ const ResourceCollection resources200Compressible{ const ResourceCollection resources200Uncompressible{ { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/404.svg" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/404.svg?cacheid=b6d648af" }, + { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/500.svg" }, + { STATIC_CONTENT, "/ROOT%23%3F/skin/500.svg?cacheid=32eb0f20" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/bittorrent.png" }, { STATIC_CONTENT, "/ROOT%23%3F/skin/bittorrent.png?cacheid=4f5c6882" }, { DYNAMIC_CONTENT, "/ROOT%23%3F/skin/blank.html" }, @@ -1006,7 +1008,6 @@ std::string expectedSexy404ErrorHtml(const std::string& url) TEST_F(ServerTest, HttpSexy404HtmlError) { - using namespace TestingOfHtmlResponses; const std::vector testUrls { // XXX: Nicer 404 error page no longer hints whether the error // XXX: is because of the missing book/ZIM-file or a missing article @@ -1209,35 +1210,79 @@ TEST_F(ServerTest, HttpXmlError) } } -TEST_F(ServerTest, 500) +std::string expectedSexy500ErrorHtml(const std::string& url) { - const std::string expectedBody = R"( - + const auto urlWithoutQuery = replace(url, "\\?.*$", ""); + const auto htmlSafeUrl = htmlEscape(urlWithoutQuery); + const auto jsSafeUrl = escapeJsString(urlWithoutQuery); + + const std::string englishText[] = { + "Internal Server Error", + "Page isn't working", + "Oops. Page isn't working.", + "The requested path cannot be properly delivered:", + }; + + const std::string translatedText[] = { + "[I18N] Internal Server Error [TESTING]", + "Page [I18N] isn't [TESTING] working", + "Oops. [I18N] Page isn't [TESTING] working.", + "The requested path [I18N TESTING] cannot be properly delivered:", + }; + + const bool shouldTranslate = url.find("userlang=test") != std::string::npos; + const std::string* const t = shouldTranslate ? translatedText : englishText; + + return R"RAWSTRINGLITERAL( + - - Internal Server Error + + + )RAWSTRINGLITERAL" + t[0] + R"RAWSTRINGLITERAL( + -

Internal Server Error

-

- An internal server error occured. We are sorry about that :/ -

-

- Entry redirect_loop.html is a redirect entry. -

+
+ )RAWSTRINGLITERAL +
+
+

)RAWSTRINGLITERAL" + t[2] + R"RAWSTRINGLITERAL(

+

)RAWSTRINGLITERAL" + t[3] + R"RAWSTRINGLITERAL(

+

)RAWSTRINGLITERAL" + + // inject the URL + htmlSafeUrl // inject the URL + + // inject the URL + R"RAWSTRINGLITERAL(

+
-)"; +)RAWSTRINGLITERAL"; +} - { - const auto r = zfs1_->GET("/ROOT%23%3F/content/poor/A/redirect_loop.html"); - EXPECT_EQ(r->status, 500); - EXPECT_EQ(r->body, expectedBody); - EXPECT_EQ(r->get_header_value("Content-Type"), "text/html; charset=utf-8"); +TEST_F(ServerTest, 500) +{ + const std::vector testUrls { + "/ROOT%23%3F/content/poor/A/redirect_loop.html", + "/ROOT%23%3F/content/poor/A/redirect_loop.html?userlang=test", + }; + + for ( const auto& url : testUrls ) { + const TestContext ctx{ {"url", url} }; + const auto r = zfs1_->GET(url.c_str()); + EXPECT_EQ(r->status, 500) << ctx; + EXPECT_EQ(r->get_header_value("Content-Type"), "text/html; charset=utf-8") << ctx; + EXPECT_EQ(r->body, expectedSexy500ErrorHtml(url)) << ctx; } }