diff --git a/lib/errors/index.ts b/lib/errors/index.ts
index 99269ed5d2d1c4..60f6e8420df9af 100644
--- a/lib/errors/index.ts
+++ b/lib/errors/index.ts
@@ -5,7 +5,7 @@ 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 { gitHash } from '@/utils/git-hash';
import RequestInProgressError from './request-in-progress';
import RejectError from './reject';
@@ -22,8 +22,9 @@ export const errorHandler: ErrorHandler = (error, ctx) => {
const debug = getDebugInfo();
if (ctx.res.headers.get('RSSHub-Cache-Status')) {
debug.hitCache++;
- setDebugInfo(debug);
}
+ debug.error++;
+ setDebugInfo(debug);
if (config.sentry.dsn) {
Sentry.withScope((scope) => {
diff --git a/lib/routes/index.ts b/lib/routes/index.ts
deleted file mode 100644
index be7a6180ac38dc..00000000000000
--- a/lib/routes/index.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import type { Handler } from 'hono';
-import { config } from '@/config';
-import art from 'art-template';
-import * as path from 'node:path';
-import gitHash from '@/utils/git-hash';
-import { getDebugInfo } from '@/utils/debug-info';
-
-const startTime = Date.now();
-
-const handler: Handler = (ctx) => {
- ctx.header('Cache-Control', 'no-cache');
-
- const debug = getDebugInfo();
-
- const showDebug = !config.debugInfo || config.debugInfo === 'false' ? false : config.debugInfo === 'true' || config.debugInfo === ctx.req.query('debug');
- const { disallowRobot, nodeName } = config;
-
- const duration = Date.now() - startTime;
-
- return ctx.html(
- art(path.resolve(__dirname, '../views/welcome.art'), {
- showDebug,
- disallowRobot,
- debug: [
- nodeName
- ? {
- name: 'Node Name',
- value: nodeName,
- }
- : null,
- {
- name: 'Git Hash',
- value: gitHash,
- },
- {
- name: 'Request Amount',
- value: debug.request,
- },
- {
- name: 'Request Frequency',
- value: ((debug.request / (duration / 1000)) * 60).toFixed(3) + ' times/minute',
- },
- {
- name: 'Cache Hit Ratio',
- value: debug.request ? (debug.hitCache / debug.request).toFixed(3) : 0,
- },
- {
- name: 'ETag Matched',
- value: debug.etag,
- },
- {
- name: 'Run Time',
- value: (duration / 3_600_000).toFixed(2) + ' hour(s)',
- },
- ],
- })
- );
-};
-
-export default handler;
diff --git a/lib/routes/index.tsx b/lib/routes/index.tsx
new file mode 100644
index 00000000000000..240e1bbb14155b
--- /dev/null
+++ b/lib/routes/index.tsx
@@ -0,0 +1,10 @@
+import type { Handler } from 'hono';
+import Index from '@/views/index';
+
+const handler: Handler = (ctx) => {
+ ctx.header('Cache-Control', 'no-cache');
+
+ return ctx.html();
+};
+
+export default handler;
diff --git a/lib/utils/debug-info.ts b/lib/utils/debug-info.ts
index 0ec829490de692..e1382068a94514 100644
--- a/lib/utils/debug-info.ts
+++ b/lib/utils/debug-info.ts
@@ -2,6 +2,7 @@ const debug = {
hitCache: 0,
request: 0,
etag: 0,
+ error: 0,
};
export const getDebugInfo = () => debug;
diff --git a/lib/utils/git-hash.ts b/lib/utils/git-hash.ts
index 85e255faa6a259..60d2b4b3bf6a0b 100644
--- a/lib/utils/git-hash.ts
+++ b/lib/utils/git-hash.ts
@@ -1,12 +1,14 @@
import gitRevSync from 'git-rev-sync';
-let gitHash = process.env.HEROKU_SLUG_COMMIT?.slice(0, 7) || process.env.VERCEL_GIT_COMMIT_SHA?.slice(0, 7);
+let gitHash = process.env.HEROKU_SLUG_COMMIT?.slice(0, 8) || process.env.VERCEL_GIT_COMMIT_SHA?.slice(0, 8);
+let gitDate;
if (!gitHash) {
try {
- gitHash = gitRevSync.short();
+ gitHash = gitRevSync.short(undefined, 8);
+ gitDate = gitRevSync.date();
} catch {
gitHash = 'unknown';
}
}
-export default gitHash;
+export { gitHash, gitDate };
diff --git a/lib/views/index.tsx b/lib/views/index.tsx
new file mode 100644
index 00000000000000..bc0fc096aa2f0b
--- /dev/null
+++ b/lib/views/index.tsx
@@ -0,0 +1,163 @@
+import type { FC } from 'hono/jsx';
+
+import { config } from '@/config';
+import { gitHash, gitDate } from '@/utils/git-hash';
+import { getDebugInfo } from '@/utils/debug-info';
+
+const startTime = Date.now();
+
+const Layout: FC = (props) => (
+
+
+ Welcome to RSSHub!
+
+
+ {props.children}
+
+);
+
+const Index: FC<{ debugQuery: string | undefined }> = ({ debugQuery }) => {
+ const debug = getDebugInfo();
+
+ const showDebug = !config.debugInfo || config.debugInfo === 'false' ? false : config.debugInfo === 'true' || config.debugInfo === debugQuery;
+ const { disallowRobot, nodeName } = config;
+
+ const duration = Date.now() - startTime;
+
+ const info = {
+ showDebug,
+ disallowRobot,
+ debug: [
+ ...(nodeName
+ ? [
+ {
+ name: 'Node Name',
+ value: nodeName,
+ },
+ ]
+ : []),
+ ...(gitHash
+ ? [
+ {
+ name: 'Git Hash',
+ value: (
+
+ {gitHash}
+
+ ),
+ },
+ ]
+ : []),
+ ...(gitDate
+ ? [
+ {
+ name: 'Git Date',
+ value: gitDate.toUTCString(),
+ },
+ ]
+ : []),
+ {
+ name: 'Cache Length',
+ value: config.cache.routeExpire + 's',
+ },
+ {
+ name: 'Request Amount',
+ value: debug.request,
+ },
+ {
+ name: 'Request Frequency',
+ value: ((debug.request / (duration / 1000)) * 60).toFixed(3) + ' times/minute',
+ },
+ {
+ name: 'Cache Hit Ratio',
+ value: debug.request ? ((debug.hitCache / debug.request) * 100).toFixed(2) + '%' : 0,
+ },
+ {
+ name: 'ETag Matched Ratio',
+ value: debug.request ? ((debug.etag / debug.request) * 100).toFixed(2) + '%' : 0,
+ },
+ {
+ name: 'Health',
+ value: debug.request ? ((1 - debug.error / debug.request) * 100).toFixed(2) + '%' : 0,
+ },
+ {
+ name: 'Run Time',
+ value: (duration / 3_600_000).toFixed(2) + ' hour(s)',
+ },
+ ],
+ };
+
+ return (
+
+
+
+

+
+ Welcome to RSSHub!
+
+
If you see this page, the RSSHub is successfully installed and working.
+
Everything is RSSible
+
+ {info.showDebug ? (
+
+ Debug Info
+ {info.debug.map((item) => (
+
+ {item.name}:
+ {item.value}
+
+ ))}
+
+ ) : null}
+
+
+
+ );
+};
+
+export default Index;
diff --git a/lib/views/welcome.art b/lib/views/welcome.art
deleted file mode 100644
index 7d8c0b80214f67..00000000000000
--- a/lib/views/welcome.art
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
-
- Welcome to RSSHub!
- {{ if disallowRobot }}
-
- {{ /if }}
-
-
-
-
-
-
-
-
-
-
Welcome to
- RSSHub!
-
-
If you see this page, the RSSHub is successfully installed and working.
-
-
For online documentation and support please refer to
- docs.rsshub.app.
-
-
-- Made with
- ♥ by
- DIYgod
-
-
- {{ if showDebug }}
-
- debug
- {{ each debug }}
- {{ if $value && $value.value }}
-
- {{ $value.name }}:
- {{@ $value.value }}
-
- {{ /if }}
- {{ /each }}
-
- {{ /if }}
-
-
-
-
diff --git a/tailwind.config.js b/tailwind.config.js
new file mode 100644
index 00000000000000..e69de29bb2d1d6