Skip to content

Commit

Permalink
feat: new error page
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Mar 5, 2024
1 parent 641a8e6 commit 94cf074
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 116 deletions.
8 changes: 3 additions & 5 deletions lib/errors/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,16 @@ afterAll(() => {
describe('error', () => {
it(`error`, async () => {
const response = await request.get('/test/error');
expect(response.status).toBe(404);
expect(response.status).toBe(503);
expect(response.text).toMatch(/Error: Error test/);
});
});

describe('httperror', () => {
it(`httperror`, async () => {
const response = await request.get('/test/httperror');
expect(response.status).toBe(404);
expect(response.text).toMatch(
/Response code 404 \(Not Found\): target website might be blocking our access, you can <a href="https:\/\/docs\.rsshub\.app\/install\/">host your own RSSHub instance<\/a> for a better usability\./
);
expect(response.status).toBe(503);
expect(response.text).toMatch('Response code 404 (Not Found): target website might be blocking our access, you can host your own RSSHub instance for a better usability.');
}, 20000);
});

Expand Down
81 changes: 35 additions & 46 deletions lib/errors/index.ts → lib/errors/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,16 @@ import { getDebugInfo, setDebugInfo } from '@/utils/debug-info';
import { config } from '@/config';
import Sentry from '@sentry/node';
import logger from '@/utils/logger';
import art from 'art-template';
import * as path from 'node:path';
import { gitHash } from '@/utils/git-hash';
import Error from '@/views/error';

import RequestInProgressError from './request-in-progress';
import RejectError from './reject';
import NotFoundError from './not-found';

import { getCurrentPath } from '@/utils/helpers';
const __dirname = getCurrentPath(import.meta.url);

export const errorHandler: ErrorHandler = (error, ctx) => {
const requestPath = ctx.req.path;
const matchedRoute = ctx.req.routePath;
const hasMatchedRoute = matchedRoute !== '/*';
let message = '';
if (error.name && (error.name === 'HTTPError' || error.name === 'RequestError')) {
message = `${error.message}: target website might be blocking our access, you can <a href="https://docs.rsshub.app/install/">host your own RSSHub instance</a> for a better usability.`;
} else if (error instanceof Error) {
message = process.env.NODE_ENV === 'production' ? error.message : error.stack || error.message;
}

const debug = getDebugInfo();
if (ctx.res.headers.get('RSSHub-Cache-Status')) {
Expand All @@ -49,42 +38,42 @@ export const errorHandler: ErrorHandler = (error, ctx) => {
});
}

logger.error(`Error in ${requestPath}: ${message}`);

if (config.isPackage) {
return ctx.json({
error: {
message: error.message ?? error,
},
});
} else {
if (error instanceof RequestInProgressError) {
ctx.header('Cache-Control', `public, max-age=${config.requestTimeout / 1000}`);
ctx.status(503);
message = error.message;
} else if (error instanceof RejectError) {
ctx.status(403);
message = error.message;
} else if (error instanceof NotFoundError) {
ctx.status(404);
message = 'wrong path';
if (ctx.req.path.endsWith('/')) {
message += ', you can try removing the trailing slash in the path';
}
} else {
ctx.status(404);
let message = '';
if (error.name && (error.name === 'HTTPError' || error.name === 'RequestError')) {
ctx.status(503);
message = `${error.message}: target website might be blocking our access, you can host your own RSSHub instance for a better usability.`;
} else if (error instanceof RequestInProgressError) {
ctx.header('Cache-Control', `public, max-age=${config.requestTimeout / 1000}`);
ctx.status(503);
message = error.message;
} else if (error instanceof RejectError) {
ctx.status(403);
message = error.message;
} else if (error instanceof NotFoundError) {
ctx.status(404);
message = 'wrong path';
if (ctx.req.path.endsWith('/')) {
message += ', you can try removing the trailing slash in the path';
}

return ctx.html(
art(path.resolve(__dirname, '../views/error.art'), {
requestPath,
message,
errorRoute: hasMatchedRoute ? matchedRoute : requestPath,
nodeVersion: process.version,
gitHash,
})
);
} else {
ctx.status(503);
message = process.env.NODE_ENV === 'production' ? error.message : error.stack || error.message;
}

logger.error(`Error in ${requestPath}: ${message}`);

return config.isPackage ? ctx.json({
error: {
message: error.message ?? error,
},
}) : ctx.html((
<Error
requestPath={requestPath}
message={message}
errorRoute={hasMatchedRoute ? matchedRoute : requestPath}
nodeVersion={process.version}
/>
));
};

export const notFoundHandler: NotFoundHandler = (ctx) => errorHandler(new NotFoundError(), ctx);
65 changes: 0 additions & 65 deletions lib/views/error.art

This file was deleted.

112 changes: 112 additions & 0 deletions lib/views/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import type { FC } from 'hono/jsx';

import { gitHash, gitDate } from '@/utils/git-hash';

const Layout: FC = (props) => (
<html>
<head>
<title>Welcome to RSSHub!</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
{`
details::-webkit-scrollbar {
width: 0.25rem;
}
details::-webkit-scrollbar-thumb {
border-radius: 0.125rem;
background-color: #e4e4e7;
}
details::-webkit-scrollbar-thumb:hover {
background-color: #a1a1aa;
}`}
</style>
</head>
<body className="antialiased text-zinc-700">{props.children}</body>
</html>
);

const Index: FC<{
requestPath: string;
message: string;
errorRoute: string;
nodeVersion: string;
}> = ({
requestPath,
message,
errorRoute,
nodeVersion,
}) => (
<Layout>
<div
className="pointer-events-none absolute w-full h-screen"
style={{
backgroundImage: `url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAzMiAzMicgd2lkdGg9JzMyJyBoZWlnaHQ9JzMyJyBmaWxsPSdub25lJyBzdHJva2U9J3JnYigxNSAyMyA0MiAvIDAuMDQpJz48cGF0aCBkPSdNMCAuNUgzMS41VjMyJy8+PC9zdmc+')`,
maskImage: 'linear-gradient(transparent, black, transparent)',
}}
></div>
<div className="w-full h-screen flex items-center justify-center flex-col space-y-4">
<img className="grayscale" src="/logo.png" alt="RSSHub" width="100" loading="lazy" />
<h1 className="text-4xl font-bold">
Looks like something went wrong
</h1>
<div className="text-left w-[800px] space-y-6 !mt-10">
<div className="space-y-2">
<p className="mb-2 font-bold">Helpful Information</p>
<p>Error Message:</p>
<code className="mt-2 block max-h-28 overflow-auto bg-zinc-100 align-bottom w-fit details">{message}</code>
<p>Route: <code className="ml-2 bg-zinc-100">{errorRoute}</code></p>
<p>Full Route: <code className="ml-2 bg-zinc-100">{requestPath}</code></p>
<p>Node Version: <code className="ml-2 bg-zinc-100">{nodeVersion}</code></p>
<p>Git Hash: <code className="ml-2 bg-zinc-100">{gitHash}</code></p>
<p>Git Date: <code className="ml-2 bg-zinc-100">{gitDate?.toUTCString()}</code></p>
</div>
<div>
<p className="mb-2 font-bold">Report</p>
<p>After carefully reading the <a className="text-[#F5712C]" href="https://docs.rsshub.app/" target="_blank">document</a>, if you think this is a bug of RSSHub, please <a className="text-[#F5712C]" href="https://github.com/DIYgod/RSSHub/issues/new?assignees=&labels=RSS+bug&template=bug_report_en.yml" target="_blank">submit an issue</a> on GitHub.</p>
<p>在仔细阅读<a className="text-[#F5712C]" href="https://docs.rsshub.app/zh/" target="_blank">文档</a>后,如果你认为这是 RSSHub 的 bug,请在 GitHub <a className="text-[#F5712C]" href="https://github.com/DIYgod/RSSHub/issues/new?assignees=&labels=RSS+bug&template=bug_report_zh.yml" target="_blank">提交 issue</a></p>
</div>
<div>
<p className="mb-2 font-bold">Community</p>
<p>You can also join our <a className="text-[#F5712C]" target="_blank" href="https://t.me/rsshub">Telegram group</a>, or follow our <a className="text-[#F5712C]" target="_blank" href="https://t.me/awesomeRSSHub">Telegram channel</a> and <a target="_blank" href="https://twitter.com/intent/follow?screen_name=_RSSHub" className="text-[#F5712C]">Twitter</a> to get community support and news.</p>
<p>你也可以加入我们的 <a className="text-[#F5712C]" target="_blank" href="https://t.me/rsshub">Telegram 群组</a>,或关注我们的 <a className="text-[#F5712C]" target="_blank" href="https://t.me/awesomeRSSHub">Telegram 频道</a><a target="_blank" href="https://twitter.com/intent/follow?screen_name=_RSSHub" className="text-[#F5712C]">Twitter</a> 获取社区支持和新闻。</p>
</div>
</div>
</div>
<div className="absolute bottom-10 text-center w-full text-sm font-medium space-y-2">
<p className="space-x-4">
<a target="_blank" href="https://github.com/DIYgod/RSSHub">
<img className="inline" src="https://icons.ly/github/_/fff" alt="github" width="20" height="20" />
</a>
<a target="_blank" href="https://t.me/rsshub">
<img className="inline" src="https://icons.ly/telegram" alt="telegram group" width="20" height="20" />
</a>
<a target="_blank" href="https://t.me/awesomeRSSHub">
<img className="inline" src="https://icons.ly/telegram" alt="telegram channel" width="20" height="20" />
</a>
<a target="_blank" href="https://twitter.com/intent/follow?screen_name=_RSSHub" className="text-[#F5712C]">
<img className="inline" src="https://icons.ly/twitter" alt="github" width="20" height="20" />
</a>
</p>
<p className="!mt-6">
Please consider{' '}
<a target="_blank" href="https://docs.rsshub.app/support" className="text-[#F5712C]">
sponsoring
</a>{' '}
to help keep this open source project alive.
</p>
<p>
Made with ❤️ by{' '}
<a target="_blank" href="https://diygod.cc" className="text-[#F5712C]">
DIYgod
</a>{' '}
and{' '}
<a target="_blank" href="https://github.com/DIYgod/RSSHub/graphs/contributors" className="text-[#F5712C]">
Contributors
</a>{' '}
under MIT License.
</p>
</div>
</Layout>
);

export default Index;

0 comments on commit 94cf074

Please sign in to comment.