| 1 | import Koa from 'koa' |
| 2 | import { getLangData } from './lang' |
| 3 | import { getSection } from './customHtml' |
| 4 | import { |
| 5 | HTTP_FORBIDDEN, HTTP_MESSAGES, HTTP_NOT_FOUND, HTTP_TOO_MANY_REQUESTS, HTTP_UNAUTHORIZED, replace |
| 6 | } from './cross' |
| 7 | |
| 8 | const declaredErrorPages = [HTTP_NOT_FOUND, HTTP_FORBIDDEN, HTTP_TOO_MANY_REQUESTS].map(String) |
| 9 | |
| 10 | export function getErrorSections() { |
| 11 | return declaredErrorPages |
| 12 | } |
| 13 | |
| 14 | // to be used with errors whose recipient is possibly human |
| 15 | export async function sendErrorPage(ctx: Koa.Context, code=ctx.status) { |
| 16 | ctx.type = 'text' |
| 17 | ctx.set('content-disposition', '') // reset ctx.attachment (or forceDownload) |
| 18 | ctx.status = code |
| 19 | let msg = HTTP_MESSAGES[ctx.status] || '' |
| 20 | if (!msg) return |
| 21 | const lang = await getLangData(ctx) |
| 22 | const trans = lang ? (Object.values(lang)[0] as any)?.translate : undefined |
| 23 | msg = trans?.[msg] ?? msg |
| 24 | const page = getSection(ctx.status === HTTP_UNAUTHORIZED ? 'unauthorized' : String(ctx.status)) |
| 25 | || SIMPLE_PAGE || '' |
| 26 | if (page.includes('<')) |
| 27 | ctx.type = 'html' |
| 28 | ctx.body = replace(page, { MESSAGE: msg, HOME: trans?.home ?? 'home', URL: ctx.state.revProxyPath || '/' }, '$') |
| 29 | } |
| 30 | |
| 31 | const SIMPLE_PAGE = `<!DOCTYPE html> |
| 32 | <html><head> |
| 33 | <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"> |
| 34 | <title>$MESSAGE</title> |
| 35 | <style> |
| 36 | body{margin-top:30vh; text-align:center; font-family:sans-serif;} |
| 37 | a{color:#68a} |
| 38 | @media (prefers-color-scheme:dark){body{background:#111; color:#999;}} |
| 39 | </style> |
| 40 | </head><body> |
| 41 | <h1>$MESSAGE</h1> |
| 42 | <h2><a href="$URL">$HOME</a></h2> |
| 43 | </body></html>` |