mirror of
https://github.com/kiwix/libkiwix.git
synced 2025-08-03 02:06:05 -04:00
New 404 error page
The page doesn't support translation, yet. The new 404 error page is used only when accessing ZIM file content (i.e. as a response from the `/content` API endpoint). One notable difference from the previous error page is that now no hint is provided about whether the error is due to trying to access a non-existent book/ZIM-file or non-existent resource inside a valid book/ZIM-file (previously such a hint was present in the suggested search URL). However, when displayed in the viewer this difference can be seen in the viewer toolbar - book related buttons are hidden if the URL points to a non-existent book. This change breaks some unit tests. They will be fixed in a separate commit.
This commit is contained in:
parent
107421cdab
commit
5eb31d7286
@ -1121,15 +1121,6 @@ InternalServer::search_catalog(const RequestContext& request,
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
ParameterizedMessage suggestSearchMsg(const std::string& searchURL, const std::string& pattern)
|
|
||||||
{
|
|
||||||
return ParameterizedMessage("suggest-search",
|
|
||||||
{
|
|
||||||
{ "PATTERN", pattern },
|
|
||||||
{ "SEARCH_URL", searchURL }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// The content security policy below is set on responses to the /content
|
// The content security policy below is set on responses to the /content
|
||||||
// endpoint in order to prevent the ZIM content from interfering with the
|
// endpoint in order to prevent the ZIM content from interfering with the
|
||||||
@ -1183,9 +1174,7 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
|
|||||||
} catch (const std::out_of_range& e) {}
|
} catch (const std::out_of_range& e) {}
|
||||||
|
|
||||||
if (archive == nullptr) {
|
if (archive == nullptr) {
|
||||||
const std::string searchURL = m_root + "/search?pattern=" + kiwix::urlEncode(pattern);
|
return NewHTTP404Response(request, m_root, m_root + url);
|
||||||
return UrlNotFoundResponse(request)
|
|
||||||
+ suggestSearchMsg(searchURL, kiwix::urlDecode(pattern));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string archiveUuid(archive->getUuid());
|
const std::string archiveUuid(archive->getUuid());
|
||||||
@ -1230,9 +1219,7 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
|
|||||||
if (m_verbose.load())
|
if (m_verbose.load())
|
||||||
printf("Failed to find %s\n", urlStr.c_str());
|
printf("Failed to find %s\n", urlStr.c_str());
|
||||||
|
|
||||||
std::string searchURL = m_root + "/search?content=" + bookName + "&pattern=" + kiwix::urlEncode(pattern);
|
return NewHTTP404Response(request, m_root, m_root + url);
|
||||||
return UrlNotFoundResponse(request)
|
|
||||||
+ suggestSearchMsg(searchURL, kiwix::urlDecode(pattern));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,6 +368,21 @@ std::unique_ptr<ContentResponse> ContentResponseBlueprint::generateResponseObjec
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewHTTP404Response::NewHTTP404Response(const RequestContext& request,
|
||||||
|
const std::string& root,
|
||||||
|
const std::string& urlPath)
|
||||||
|
: ContentResponseBlueprint(&request,
|
||||||
|
MHD_HTTP_NOT_FOUND,
|
||||||
|
"text/html; charset=utf-8",
|
||||||
|
RESOURCE::templates::sexy404_html,
|
||||||
|
/*includeKiwixResponseData=*/false)
|
||||||
|
{
|
||||||
|
*this->m_data = Data(Data::Object{
|
||||||
|
{"root", root },
|
||||||
|
{"url_path", urlPath}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
HTTPErrorResponse::HTTPErrorResponse(const RequestContext& request,
|
HTTPErrorResponse::HTTPErrorResponse(const RequestContext& request,
|
||||||
int httpStatusCode,
|
int httpStatusCode,
|
||||||
const std::string& pageTitleMsgId,
|
const std::string& pageTitleMsgId,
|
||||||
|
@ -145,6 +145,13 @@ protected: //data
|
|||||||
std::unique_ptr<Data> m_data;
|
std::unique_ptr<Data> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NewHTTP404Response : ContentResponseBlueprint
|
||||||
|
{
|
||||||
|
NewHTTP404Response(const RequestContext& request,
|
||||||
|
const std::string& root,
|
||||||
|
const std::string& urlPath);
|
||||||
|
};
|
||||||
|
|
||||||
struct HTTPErrorResponse : ContentResponseBlueprint
|
struct HTTPErrorResponse : ContentResponseBlueprint
|
||||||
{
|
{
|
||||||
HTTPErrorResponse(const RequestContext& request,
|
HTTPErrorResponse(const RequestContext& request,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
skin/caret.png
|
skin/caret.png
|
||||||
skin/bittorrent.png
|
skin/bittorrent.png
|
||||||
skin/magnet.png
|
skin/magnet.png
|
||||||
|
skin/404.svg
|
||||||
skin/feed.svg
|
skin/feed.svg
|
||||||
skin/langSelector.svg
|
skin/langSelector.svg
|
||||||
skin/download.png
|
skin/download.png
|
||||||
@ -11,9 +12,11 @@ skin/iso6391To3.js
|
|||||||
skin/isotope.pkgd.min.js
|
skin/isotope.pkgd.min.js
|
||||||
skin/index.js
|
skin/index.js
|
||||||
skin/autoComplete/autoComplete.min.js
|
skin/autoComplete/autoComplete.min.js
|
||||||
|
skin/error.css
|
||||||
skin/kiwix.css
|
skin/kiwix.css
|
||||||
skin/taskbar.css
|
skin/taskbar.css
|
||||||
skin/index.css
|
skin/index.css
|
||||||
|
skin/fonts/DMSans-Regular.ttf
|
||||||
skin/fonts/Poppins.ttf
|
skin/fonts/Poppins.ttf
|
||||||
skin/fonts/Roboto.ttf
|
skin/fonts/Roboto.ttf
|
||||||
skin/search_results.css
|
skin/search_results.css
|
||||||
@ -42,6 +45,7 @@ templates/url_of_search_results_css.tmpl
|
|||||||
templates/viewer_settings.js
|
templates/viewer_settings.js
|
||||||
templates/no_js_library_page.html
|
templates/no_js_library_page.html
|
||||||
templates/no_js_download.html
|
templates/no_js_download.html
|
||||||
|
templates/sexy404.html
|
||||||
opensearchdescription.xml
|
opensearchdescription.xml
|
||||||
ft_opensearchdescription.xml
|
ft_opensearchdescription.xml
|
||||||
catalog_v2_searchdescription.xml
|
catalog_v2_searchdescription.xml
|
||||||
|
1
static/skin/404.svg
Normal file
1
static/skin/404.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.4 KiB |
153
static/skin/error.css
Normal file
153
static/skin/error.css
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family:"DM Sans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src : url('../skin/fonts/DMSans-Regular.ttf?KIWIXCACHEID');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family:"DM Sans Bold";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src : url('../skin/fonts/DMSans-Regular.ttf?KIWIXCACHEID');
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: linear-gradient(to bottom right, #ffffff, #e6e6e6);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-attachment: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
width: 100%;
|
||||||
|
margin: auto;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
margin-top: 15%;
|
||||||
|
margin-bottom: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
header img {
|
||||||
|
width: 60%;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 500px;
|
||||||
|
max-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header, .intro {
|
||||||
|
font-family: "DM Sans";
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
font-size: 1em;
|
||||||
|
padding: 0 10%;
|
||||||
|
line-height: 1.2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro h1 {
|
||||||
|
line-height: 1.1em;
|
||||||
|
font-family: "DM Sans Bold";
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro code {
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 1.1em;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice {
|
||||||
|
width: 80%;
|
||||||
|
margin: auto;
|
||||||
|
margin-bottom: 15%;
|
||||||
|
margin-top: 5em;
|
||||||
|
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 1rem;
|
||||||
|
border: 1px solid #b7b7b7;
|
||||||
|
|
||||||
|
padding: 2em;
|
||||||
|
|
||||||
|
font-family: "DM Sans";
|
||||||
|
font-size: .9em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
align-items: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice p {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice p:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice p.list-intro {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice ul {
|
||||||
|
list-style-type: square;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice ul li {
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* sm: 640px+ */
|
||||||
|
@media (width >= 40rem) {
|
||||||
|
header {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
margin-top: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
header img {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* xl: 1280px+ */
|
||||||
|
@media (width >= 80rem) {
|
||||||
|
.intro h1 {
|
||||||
|
font-size: 3.4em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2xl: 1536px+ */
|
||||||
|
@media (width >= 96rem) {
|
||||||
|
header img {
|
||||||
|
width: 25%;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 500px;
|
||||||
|
max-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advice {
|
||||||
|
width: 25%;
|
||||||
|
min-width: 200px;
|
||||||
|
min-width: 300px;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
}
|
BIN
static/skin/fonts/DMSans-Regular.ttf
Normal file
BIN
static/skin/fonts/DMSans-Regular.ttf
Normal file
Binary file not shown.
31
static/templates/sexy404.html
Normal file
31
static/templates/sexy404.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
|
<title>Page not found</title>
|
||||||
|
<link type="text/css" href="{{root}}/skin/error.css?KIWIXCACHEID" rel="Stylesheet" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<img src="{{root}}/skin/404.svg?KIWIXCACHEID"
|
||||||
|
alt="Not found!"
|
||||||
|
aria-label="Not found!"
|
||||||
|
title="Not found!">
|
||||||
|
</header>
|
||||||
|
<section class="intro">
|
||||||
|
<h1>Oops. Page not found.</h1>
|
||||||
|
<p>The requested path was not found:</p>
|
||||||
|
<p><code>{{url_path}}</code></p>
|
||||||
|
</section>
|
||||||
|
<section class="advice">
|
||||||
|
<p>The content you're looking for may still be available, but it might be located at a different place within the ZIM file.</p>
|
||||||
|
<p class="list-intro">Please:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Try using the search function to find the content you want</li>
|
||||||
|
<li>Look for keywords or titles related to the information you're seeking</li>
|
||||||
|
</ul>
|
||||||
|
<p>This approach should help you locate the desired content, even if the original link isn't working properly.</p>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -58,6 +58,8 @@ const ResourceCollection resources200Compressible{
|
|||||||
{ STATIC_CONTENT, "/ROOT%23%3F/skin/autoComplete/autoComplete.min.js?cacheid=1191aaaf" },
|
{ STATIC_CONTENT, "/ROOT%23%3F/skin/autoComplete/autoComplete.min.js?cacheid=1191aaaf" },
|
||||||
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/autoComplete/css/autoComplete.css" },
|
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/autoComplete/css/autoComplete.css" },
|
||||||
{ STATIC_CONTENT, "/ROOT%23%3F/skin/autoComplete/css/autoComplete.css?cacheid=f2d376c4" },
|
{ STATIC_CONTENT, "/ROOT%23%3F/skin/autoComplete/css/autoComplete.css?cacheid=f2d376c4" },
|
||||||
|
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/error.css" },
|
||||||
|
{ STATIC_CONTENT, "/ROOT%23%3F/skin/error.css?cacheid=c49d1586" },
|
||||||
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/i18n.js" },
|
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/i18n.js" },
|
||||||
{ STATIC_CONTENT, "/ROOT%23%3F/skin/i18n.js?cacheid=071abc9a" },
|
{ STATIC_CONTENT, "/ROOT%23%3F/skin/i18n.js?cacheid=071abc9a" },
|
||||||
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.css" },
|
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.css" },
|
||||||
@ -106,6 +108,8 @@ const ResourceCollection resources200Compressible{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ResourceCollection resources200Uncompressible{
|
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/bittorrent.png" },
|
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/bittorrent.png" },
|
||||||
{ STATIC_CONTENT, "/ROOT%23%3F/skin/bittorrent.png?cacheid=4f5c6882" },
|
{ STATIC_CONTENT, "/ROOT%23%3F/skin/bittorrent.png?cacheid=4f5c6882" },
|
||||||
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/blank.html" },
|
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/blank.html" },
|
||||||
@ -339,6 +343,12 @@ R"EXPECTEDRESULT( <link type="text/css" href="./skin/kiwix.css?cacheid=3948b8
|
|||||||
/* url */ "/ROOT%23%3F/content/zimfile/A/index",
|
/* url */ "/ROOT%23%3F/content/zimfile/A/index",
|
||||||
""
|
""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/* url */ "/ROOT%23%3F/content/invalid-book/whatever",
|
||||||
|
R"EXPECTEDRESULT( <link type="text/css" href="/ROOT%23%3F/skin/error.css?cacheid=c49d1586" rel="Stylesheet" />
|
||||||
|
<img src="/ROOT%23%3F/skin/404.svg?cacheid=b6d648af"
|
||||||
|
)EXPECTEDRESULT"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// Searching in a ZIM file without a full-text index returns
|
// Searching in a ZIM file without a full-text index returns
|
||||||
// a page rendered from static/templates/no_search_result_html
|
// a page rendered from static/templates/no_search_result_html
|
||||||
|
Loading…
x
Reference in New Issue
Block a user