From d13bd1ff5759f1cd874fff5220df6ed75743b6eb Mon Sep 17 00:00:00 2001 From: rohow Date: Mon, 14 Oct 2024 11:17:23 +0800 Subject: [PATCH] first commit --- .gitignore | 27 ++++ Dockerfile | 11 ++ README.md | 0 deno.json | 12 ++ deno.lock | 348 ++++++++++++++++++++++++++++++++++++++++++++++++ main.ts | 92 +++++++++++++ views/error.hbs | 246 ++++++++++++++++++++++++++++++++++ 7 files changed, 736 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 deno.json create mode 100644 deno.lock create mode 100644 main.ts create mode 100644 views/error.hbs diff --git a/ .gitignore b/ .gitignore new file mode 100644 index 0000000..0068d12 --- /dev/null +++ b/ .gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +.gradle +build diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9650d90 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM denoland/deno:latest + +WORKDIR /app + +COPY . . + +RUN deno install + +CMD ["deno", "run", "start"] + +EXPOSE 8080 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..2d9f4c6 --- /dev/null +++ b/deno.json @@ -0,0 +1,12 @@ +{ + "imports": { + "@fastify/view": "npm:@fastify/view@^10.0.1", + "@std/path": "jsr:@std/path@^1.0.6", + "fastify": "npm:fastify@^5.0.0", + "handlebars": "npm:handlebars@^4.7.8", + "mime": "npm:mime@^4.0.4" + }, + "tasks": { + "start": "deno run --allow-net --allow-read --allow-sys --allow-env main.ts" + } +} diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..737305a --- /dev/null +++ b/deno.lock @@ -0,0 +1,348 @@ +{ + "version": "4", + "specifiers": { + "jsr:@std/path@^1.0.6": "1.0.6", + "npm:@fastify/view@^10.0.1": "10.0.1", + "npm:fastify@5": "5.0.0", + "npm:handlebars@^4.7.8": "4.7.8", + "npm:mime@^4.0.4": "4.0.4" + }, + "jsr": { + "@std/path@1.0.6": { + "integrity": "ab2c55f902b380cf28e0eec501b4906e4c1960d13f00e11cfbcd21de15f18fed" + } + }, + "npm": { + "@fastify/ajv-compiler@4.0.1_ajv@8.17.1": { + "integrity": "sha512-DxrBdgsjNLP0YM6W5Hd6/Fmj43S8zMKiFJYgi+Ri3htTGAowPVG/tG1wpnWLMjufEnehRivUCKZ1pLDIoZdTuw==", + "dependencies": [ + "ajv", + "ajv-formats", + "fast-uri@3.0.2" + ] + }, + "@fastify/error@4.0.0": { + "integrity": "sha512-OO/SA8As24JtT1usTUTKgGH7uLvhfwZPwlptRi2Dp5P4KKmJI3gvsZ8MIHnNwDs4sLf/aai5LzTyl66xr7qMxA==" + }, + "@fastify/fast-json-stringify-compiler@5.0.1": { + "integrity": "sha512-f2d3JExJgFE3UbdFcpPwqNUEoHWmt8pAKf8f+9YuLESdefA0WgqxeT6DrGL4Yrf/9ihXNSKOqpjEmurV405meA==", + "dependencies": [ + "fast-json-stringify" + ] + }, + "@fastify/merge-json-schemas@0.1.1": { + "integrity": "sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==", + "dependencies": [ + "fast-deep-equal" + ] + }, + "@fastify/view@10.0.1": { + "integrity": "sha512-rXtBN0oVDmoRZAS7lelrCIahf+qFtlMOOas8VPdA7JvrJ9ChcF7e36pIUPU0Vbs3KmHxESUb7XatavUZEe/k5Q==", + "dependencies": [ + "fastify-plugin", + "toad-cache" + ] + }, + "abort-controller@3.0.0": { + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": [ + "event-target-shim" + ] + }, + "abstract-logging@2.0.1": { + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==" + }, + "ajv-formats@3.0.1_ajv@8.17.1": { + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": [ + "ajv" + ] + }, + "ajv@8.17.1": { + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": [ + "fast-deep-equal", + "fast-uri@3.0.2", + "json-schema-traverse", + "require-from-string" + ] + }, + "atomic-sleep@1.0.0": { + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" + }, + "avvio@9.0.0": { + "integrity": "sha512-UbYrOXgE/I+knFG+3kJr9AgC7uNo8DG+FGGODpH9Bj1O1kL/QDjBXnTem9leD3VdQKtaHjV3O85DQ7hHh4IIHw==", + "dependencies": [ + "@fastify/error", + "fastq" + ] + }, + "base64-js@1.5.1": { + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "buffer@6.0.3": { + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dependencies": [ + "base64-js", + "ieee754" + ] + }, + "cookie@0.7.2": { + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" + }, + "event-target-shim@5.0.1": { + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "events@3.3.0": { + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "fast-decode-uri-component@1.0.1": { + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" + }, + "fast-deep-equal@3.1.3": { + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stringify@6.0.0_ajv@8.17.1": { + "integrity": "sha512-FGMKZwniMTgZh7zQp9b6XnBVxUmKVahQLQeRQHqwYmPDqDhcEKZ3BaQsxelFFI5PY7nN71OEeiL47/zUWcYe1A==", + "dependencies": [ + "@fastify/merge-json-schemas", + "ajv", + "ajv-formats", + "fast-deep-equal", + "fast-uri@2.4.0", + "json-schema-ref-resolver", + "rfdc" + ] + }, + "fast-querystring@1.1.2": { + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "dependencies": [ + "fast-decode-uri-component" + ] + }, + "fast-redact@3.5.0": { + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==" + }, + "fast-uri@2.4.0": { + "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==" + }, + "fast-uri@3.0.2": { + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==" + }, + "fastify-plugin@5.0.1": { + "integrity": "sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==" + }, + "fastify@5.0.0": { + "integrity": "sha512-Qe4dU+zGOzg7vXjw4EvcuyIbNnMwTmcuOhlOrOJsgwzvjEZmsM/IeHulgJk+r46STjdJS/ZJbxO8N70ODXDMEQ==", + "dependencies": [ + "@fastify/ajv-compiler", + "@fastify/error", + "@fastify/fast-json-stringify-compiler", + "abstract-logging", + "avvio", + "fast-json-stringify", + "find-my-way", + "light-my-request", + "pino", + "process-warning", + "proxy-addr", + "rfdc", + "secure-json-parse", + "semver", + "toad-cache" + ] + }, + "fastq@1.17.1": { + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": [ + "reusify" + ] + }, + "find-my-way@9.1.0": { + "integrity": "sha512-Y5jIsuYR4BwWDYYQ2A/RWWE6gD8a0FMgtU+HOq1WKku+Cwdz8M1v8wcAmRXXM1/iqtoqg06v+LjAxMYbCjViMw==", + "dependencies": [ + "fast-deep-equal", + "fast-querystring", + "safe-regex2" + ] + }, + "forwarded@0.2.0": { + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "handlebars@4.7.8": { + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": [ + "minimist", + "neo-async", + "source-map", + "uglify-js", + "wordwrap" + ] + }, + "ieee754@1.2.1": { + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ipaddr.js@1.9.1": { + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "json-schema-ref-resolver@1.0.1": { + "integrity": "sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==", + "dependencies": [ + "fast-deep-equal" + ] + }, + "json-schema-traverse@1.0.0": { + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "light-my-request@6.1.0": { + "integrity": "sha512-+NFuhlOGoEwxeQfJ/pobkVFxcnKyDtiX847hLjuB/IzBxIl3q4VJeFI8uRCgb3AlTWL1lgOr+u5+8QdUcr33ng==", + "dependencies": [ + "cookie", + "process-warning", + "set-cookie-parser" + ] + }, + "mime@4.0.4": { + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==" + }, + "minimist@1.2.8": { + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "neo-async@2.6.2": { + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "on-exit-leak-free@2.1.2": { + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==" + }, + "pino-abstract-transport@1.2.0": { + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dependencies": [ + "readable-stream", + "split2" + ] + }, + "pino-std-serializers@7.0.0": { + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, + "pino@9.4.0": { + "integrity": "sha512-nbkQb5+9YPhQRz/BeQmrWpEknAaqjpAqRK8NwJpmrX/JHu7JuZC5G1CeAwJDJfGes4h+YihC6in3Q2nGb+Y09w==", + "dependencies": [ + "atomic-sleep", + "fast-redact", + "on-exit-leak-free", + "pino-abstract-transport", + "pino-std-serializers", + "process-warning", + "quick-format-unescaped", + "real-require", + "safe-stable-stringify", + "sonic-boom", + "thread-stream" + ] + }, + "process-warning@4.0.0": { + "integrity": "sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==" + }, + "process@0.11.10": { + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, + "proxy-addr@2.0.7": { + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": [ + "forwarded", + "ipaddr.js" + ] + }, + "quick-format-unescaped@4.0.4": { + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "readable-stream@4.5.2": { + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": [ + "abort-controller", + "buffer", + "events", + "process", + "string_decoder" + ] + }, + "real-require@0.2.0": { + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==" + }, + "require-from-string@2.0.2": { + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "ret@0.5.0": { + "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==" + }, + "reusify@1.0.4": { + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rfdc@1.4.1": { + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "safe-buffer@5.2.1": { + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-regex2@4.0.0": { + "integrity": "sha512-Hvjfv25jPDVr3U+4LDzBuZPPOymELG3PYcSk5hcevooo1yxxamQL/bHs/GrEPGmMoMEwRrHVGiCA1pXi97B8Ew==", + "dependencies": [ + "ret" + ] + }, + "safe-stable-stringify@2.5.0": { + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==" + }, + "secure-json-parse@2.7.0": { + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" + }, + "semver@7.6.3": { + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" + }, + "set-cookie-parser@2.7.0": { + "integrity": "sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==" + }, + "sonic-boom@4.1.0": { + "integrity": "sha512-NGipjjRicyJJ03rPiZCJYjwlsuP2d1/5QUviozRXC7S3WdVWNK5e3Ojieb9CCyfhq2UC+3+SRd9nG3I2lPRvUw==", + "dependencies": [ + "atomic-sleep" + ] + }, + "source-map@0.6.1": { + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "split2@4.2.0": { + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, + "string_decoder@1.3.0": { + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": [ + "safe-buffer" + ] + }, + "thread-stream@3.1.0": { + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "dependencies": [ + "real-require" + ] + }, + "toad-cache@3.7.0": { + "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==" + }, + "uglify-js@3.19.3": { + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==" + }, + "wordwrap@1.0.0": { + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + } + }, + "workspace": { + "dependencies": [ + "jsr:@std/path@^1.0.6", + "npm:@fastify/view@^10.0.1", + "npm:fastify@5", + "npm:handlebars@^4.7.8", + "npm:mime@^4.0.4" + ] + } +} diff --git a/main.ts b/main.ts new file mode 100644 index 0000000..0889d12 --- /dev/null +++ b/main.ts @@ -0,0 +1,92 @@ +import * as path from "@std/path"; + +import fastify from 'fastify'; +import fastifyView from "@fastify/view" +import handlebars from "handlebars"; +import mime from 'mime/lite'; + +const server = fastify(); + +const __dirname = new URL('.', import.meta.url).pathname; + +server.register(fastifyView, { engine: { handlebars }, root: path.resolve(__dirname, 'views') }); + +enum Headers { + FormatHeader = 'x-format', + CodeHeader = 'x-code', + OriginalURI = 'x-original-uri', + ContentType = 'content-type', + Namespace = "x-namespace", + IngressName = "x-ingress-name", + ServiceName = "x-service-name", + ServicePort = "x-service-port", + RequestId = "x-request-id", +} + +const CodeMessageMap: Record = { + 403: '禁止访问此内容: 抱歉,由于安全问题您被禁止访问此内容。如果您认为这是个错误,请联系我们获取帮助。', + 404: '内容未找到: 您正在寻找的内容可能已被删除、名称已更改或暂时不可用。', + 500: '服务器错误: 请稍后再试,或者返回主页。如果问题持续存在,请联系我们,我们会尽快修复。' +}; + +// 默认处理函数 +server.all('/', (request, reply) => { + const headers = request.headers; + + // 获取OriginalURI的文件后缀 + const originalURI: string = headers[Headers.OriginalURI] || ''; + const urlExtWithDot = path.extname(originalURI); + + // 获取FormatHeader对应的文件后缀 + const format: string = headers[Headers.FormatHeader] || ''; + // 排除format存在多个的情况 目前只支持一个 + const firstFormat = format.split(',')[0]; + const formatExt = mime.getExtension(firstFormat); + const formatExtWithDot = formatExt ? `.${formatExt}` : ''; + + const ext = formatExtWithDot || urlExtWithDot || '.html'; + + // 获取header中的其他内容 + const requestId: string = headers[Headers.RequestId] || ''; + + // 获取CodeHeader对应的状态码 + const code: number = Number(headers[Headers.CodeHeader] || 404); + + // 获取兼容code 比如没有403的code,就使用404 没有502的code,就使用500 取第一位相同的但是最小的code + let compatibleCode = code; + + const isCodeExist = Reflect.has(CodeMessageMap, code); + + if (!isCodeExist) { + const codeList = Object.keys(CodeMessageMap).map(Number).sort((a, b) => a - b); + compatibleCode = Number(codeList.find((c) => String(c).startsWith(String(code).charAt(0))) || 404) + } + + const message = CodeMessageMap[compatibleCode]; + + const data = { code, requestId, message }; + + console.log(`[${new Date().toISOString()}] code:${code} url:'${originalURI}' ext:'${ext}' requestId:'${requestId}'`); + + // 根据后缀渲染不同的内容 + if (ext === '.html' || ext === '.htm') { + const [title, content] = message.split(':'); + + const htmlContent = content.trim().replace(/。(?=.+)/, '。
'); + + reply.code(code).view('error.hbs', { ...data, title, content: htmlContent }); + } else if (ext === '.json') { + reply.code(code).send(data); + } else { + reply.code(code).send(message); + } +}); + +// 提供健康检查接口 +server.get('/healthz', (_request, reply) => reply.send('OK')); + +server.listen({ port: 8080, host: '0.0.0.0'}, (_err, address) => { + if (_err) throw _err + + console.log(`Server listening at ${address}`); +}); diff --git a/views/error.hbs b/views/error.hbs new file mode 100644 index 0000000..7da5d73 --- /dev/null +++ b/views/error.hbs @@ -0,0 +1,246 @@ + + + + + + {{ code }} {{ title }} + + + +
+
+
+
+
+
+
+
+
+

{{ code }}

+
+

{{ title }}

+

{{{ content }}}

+

{{ requestId }}

+ 回到首页 + 联系我们 +
+
+ +