Additional error info on the HTTP 500 error page

Additional error info (text of the exception thrown by low level C++
code) is shown inside a text box of the same style as used for the
advice on the 404 error page (we either need to change the name of the
CSS style, or introduce a separate style for this piece of information).
This commit is contained in:
Veloman Yunkan 2025-05-22 15:18:13 +04:00
parent 2ba29f76e1
commit be69584637
3 changed files with 49 additions and 19 deletions

View File

@ -494,21 +494,27 @@ HTTP400Response::HTTP400Response(const RequestContext& request)
HTTP500Response::HTTP500Response(const RequestContext& request, HTTP500Response::HTTP500Response(const RequestContext& request,
const std::string& root, const std::string& root,
const std::string& urlPath, const std::string& urlPath,
const std::string& /*errorText*/) const std::string& errorText)
: ContentResponseBlueprint(&request, : ContentResponseBlueprint(&request,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_INTERNAL_SERVER_ERROR,
"text/html; charset=utf-8", "text/html; charset=utf-8",
RESOURCE::templates::sexy500_html, RESOURCE::templates::sexy500_html,
/*includeKiwixResponseData=*/true) /*includeKiwixResponseData=*/true)
{ {
*this->m_data = Data(Data::Object{ auto pageParams = Data::Object{
{"root", root }, {"root", root },
{"url_path", urlPath}, {"url_path", urlPath},
{"PAGE_TITLE", Data::fromMsgId("500-page-title")}, {"PAGE_TITLE", Data::fromMsgId("500-page-title")},
{"PAGE_HEADING", Data::fromMsgId("500-page-heading")}, {"PAGE_HEADING", Data::fromMsgId("500-page-heading")},
{"PAGE_TEXT", Data::fromMsgId("500-page-text")}, {"PAGE_TEXT", Data::fromMsgId("500-page-text")},
{"500_img_text", Data::fromMsgId("500-img-text")}, {"500_img_text", Data::fromMsgId("500-img-text")},
}); };
if ( !errorText.empty() ) {
pageParams["error"] = errorText;
}
*this->m_data = Data(pageParams);
} }
std::unique_ptr<Response> Response::build_416(size_t resourceLength) std::unique_ptr<Response> Response::build_416(size_t resourceLength)

View File

@ -22,5 +22,10 @@
<p>{{PAGE_TEXT}}</p> <p>{{PAGE_TEXT}}</p>
<p><code>{{url_path}}</code></p> <p><code>{{url_path}}</code></p>
</section> </section>
{{#error}}
<section class="advice">
<p>{{error}}</p>
</section>
{{/error}}
</body> </body>
</html> </html>

View File

@ -1210,7 +1210,8 @@ TEST_F(ServerTest, HttpXmlError)
} }
} }
std::string expectedSexy500ErrorHtml(const std::string& url) std::string expectedSexy500ErrorHtml(const std::string& url,
const std::string& error)
{ {
const auto urlWithoutQuery = replace(url, "\\?.*$", ""); const auto urlWithoutQuery = replace(url, "\\?.*$", "");
const auto htmlSafeUrl = htmlEscape(urlWithoutQuery); const auto htmlSafeUrl = htmlEscape(urlWithoutQuery);
@ -1241,8 +1242,12 @@ std::string expectedSexy500ErrorHtml(const std::string& url)
<title>)RAWSTRINGLITERAL" + t[0] + R"RAWSTRINGLITERAL(</title> <title>)RAWSTRINGLITERAL" + t[0] + R"RAWSTRINGLITERAL(</title>
<link type="text/css" href="/ROOT%23%3F/skin/error.css?cacheid=b3fa90cf" rel="Stylesheet" /> <link type="text/css" href="/ROOT%23%3F/skin/error.css?cacheid=b3fa90cf" rel="Stylesheet" />
<script> <script>
window.KIWIX_RESPONSE_TEMPLATE = "&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n &lt;head&gt;\n &lt;meta charset=&quot;utf-8&quot;&gt;\n &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot; /&gt;\n &lt;title&gt;{{PAGE_TITLE}}&lt;/title&gt;\n &lt;link type=&quot;text/css&quot; href=&quot;{{root}}/skin/error.css?cacheid=b3fa90cf&quot; rel=&quot;Stylesheet&quot; /&gt;\n &lt;script&gt;\n window.KIWIX_RESPONSE_TEMPLATE = &quot;{{KIWIX_RESPONSE_TEMPLATE}}&quot;;\n window.KIWIX_RESPONSE_DATA = {{{KIWIX_RESPONSE_DATA}}};\n &lt;/script&gt;\n &lt;/head&gt;\n &lt;body&gt;\n &lt;header&gt;\n &lt;img src=&quot;{{root}}/skin/500.svg?cacheid=32eb0f20&quot;\n alt=&quot;{{500_img_text}}&quot;\n aria-label=&quot;{{500_img_text}}&quot;\n title=&quot;{{500_img_text}}&quot;&gt;\n &lt;/header&gt;\n &lt;section class=&quot;intro&quot;&gt;\n &lt;h1&gt;{{PAGE_HEADING}}&lt;/h1&gt;\n &lt;p&gt;{{PAGE_TEXT}}&lt;/p&gt;\n &lt;p&gt;&lt;code&gt;{{url_path}}&lt;/code&gt;&lt;/p&gt;\n &lt;/section&gt;\n &lt;/body&gt;\n&lt;/html&gt;\n"; window.KIWIX_RESPONSE_TEMPLATE = "&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n &lt;head&gt;\n &lt;meta charset=&quot;utf-8&quot;&gt;\n &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot; /&gt;\n &lt;title&gt;{{PAGE_TITLE}}&lt;/title&gt;\n &lt;link type=&quot;text/css&quot; href=&quot;{{root}}/skin/error.css?cacheid=b3fa90cf&quot; rel=&quot;Stylesheet&quot; /&gt;\n &lt;script&gt;\n window.KIWIX_RESPONSE_TEMPLATE = &quot;{{KIWIX_RESPONSE_TEMPLATE}}&quot;;\n window.KIWIX_RESPONSE_DATA = {{{KIWIX_RESPONSE_DATA}}};\n &lt;/script&gt;\n &lt;/head&gt;\n &lt;body&gt;\n &lt;header&gt;\n &lt;img src=&quot;{{root}}/skin/500.svg?cacheid=32eb0f20&quot;\n alt=&quot;{{500_img_text}}&quot;\n aria-label=&quot;{{500_img_text}}&quot;\n title=&quot;{{500_img_text}}&quot;&gt;\n &lt;/header&gt;\n &lt;section class=&quot;intro&quot;&gt;\n &lt;h1&gt;{{PAGE_HEADING}}&lt;/h1&gt;\n &lt;p&gt;{{PAGE_TEXT}}&lt;/p&gt;\n &lt;p&gt;&lt;code&gt;{{url_path}}&lt;/code&gt;&lt;/p&gt;\n &lt;/section&gt;\n{{#error}}\n &lt;section class=&quot;advice&quot;&gt;\n &lt;p&gt;{{error}}&lt;/p&gt;\n &lt;/section&gt;\n{{/error}}\n &lt;/body&gt;\n&lt;/html&gt;\n";
window.KIWIX_RESPONSE_DATA = { "500_img_text" : { "msgid" : "500-img-text", "params" : { } }, "PAGE_HEADING" : { "msgid" : "500-page-heading", "params" : { } }, "PAGE_TEXT" : { "msgid" : "500-page-text", "params" : { } }, "PAGE_TITLE" : { "msgid" : "500-page-title", "params" : { } }, "root" : "/ROOT%23%3F", "url_path" : ")RAWSTRINGLITERAL" window.KIWIX_RESPONSE_DATA = { "500_img_text" : { "msgid" : "500-img-text", "params" : { } }, "PAGE_HEADING" : { "msgid" : "500-page-heading", "params" : { } }, "PAGE_TEXT" : { "msgid" : "500-page-text", "params" : { } }, "PAGE_TITLE" : { "msgid" : "500-page-title", "params" : { } }, "error" : ")RAWSTRINGLITERAL"
+ // inject the error
escapeJsString(error) // inject the error
+ // inject the error
R"RAWSTRINGLITERAL(", "root" : "/ROOT%23%3F", "url_path" : ")RAWSTRINGLITERAL"
+ // inject the URL + // inject the URL
jsSafeUrl // inject the URL jsSafeUrl // inject the URL
+ // inject the URL + // inject the URL
@ -1265,6 +1270,9 @@ std::string expectedSexy500ErrorHtml(const std::string& url)
+ // inject the URL + // inject the URL
R"RAWSTRINGLITERAL(</code></p> R"RAWSTRINGLITERAL(</code></p>
</section> </section>
<section class="advice">
<p>)RAWSTRINGLITERAL" + error + R"RAWSTRINGLITERAL(</p>
</section>
</body> </body>
</html> </html>
)RAWSTRINGLITERAL"; )RAWSTRINGLITERAL";
@ -1272,17 +1280,28 @@ std::string expectedSexy500ErrorHtml(const std::string& url)
TEST_F(ServerTest, 500) TEST_F(ServerTest, 500)
{ {
const std::vector<std::string> testUrls { struct TestData {
"/ROOT%23%3F/content/poor/A/redirect_loop.html", const std::string url;
"/ROOT%23%3F/content/poor/A/redirect_loop.html?userlang=test", const std::string error;
};
const TestData testData[] = {
{
"/ROOT%23%3F/content/poor/A/redirect_loop.html",
"Entry redirect_loop.html is a redirect entry."
},
{
"/ROOT%23%3F/content/poor/A/redirect_loop.html?userlang=test",
"Entry redirect_loop.html is a redirect entry."
}
}; };
for ( const auto& url : testUrls ) { for ( const auto& td : testData ) {
const TestContext ctx{ {"url", url} }; const TestContext ctx{ {"url", td.url} };
const auto r = zfs1_->GET(url.c_str()); const auto r = zfs1_->GET(td.url.c_str());
EXPECT_EQ(r->status, 500) << ctx; EXPECT_EQ(r->status, 500) << ctx;
EXPECT_EQ(r->get_header_value("Content-Type"), "text/html; charset=utf-8") << ctx; EXPECT_EQ(r->get_header_value("Content-Type"), "text/html; charset=utf-8") << ctx;
EXPECT_EQ(r->body, expectedSexy500ErrorHtml(url)) << ctx; EXPECT_EQ(r->body, expectedSexy500ErrorHtml(td.url, td.error)) << ctx;
} }
} }