diff options
author | EuAndreh <eu@euandre.org> | 2024-03-08 07:47:47 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2024-03-08 07:47:47 -0300 |
commit | 1ad0f47d584f6783539217d8ca689de1a6b0f4da (patch) | |
tree | e703cda662aceed0800f904ef6c029ac17b9b6ba /src | |
parent | src/hero.mjs: Make sure globalInceptors are used even when we get a 404 (diff) | |
download | papod-1ad0f47d584f6783539217d8ca689de1a6b0f4da.tar.gz papod-1ad0f47d584f6783539217d8ca689de1a6b0f4da.tar.xz |
src/web.mjs: Move logging and interceptors to the beginning of the file
Diffstat (limited to 'src')
-rw-r--r-- | src/hero.mjs | 208 |
1 files changed, 104 insertions, 104 deletions
diff --git a/src/hero.mjs b/src/hero.mjs index 2355bbf..9c6df64 100644 --- a/src/hero.mjs +++ b/src/hero.mjs @@ -9,6 +9,110 @@ import util from "node:util"; import * as u from "./utils.mjs"; +export const loggerDefaults = { + pid: process.pid, + ppid: process.ppid, + tool: "hero", +}; + +export let loggerGlobals = {}; + +export const configLogger = o => loggerGlobals = o; + +export const logit = (writerFn, level, o) => + writerFn(JSON.stringify({ + ...loggerDefaults, + ...loggerGlobals, + level, + ...o, + })); + +export const makeLogger = (writerFn = console.error) => ({ + debug: (...args) => process.env.DEBUG ? + logit(writerFn, "DEBUG", ...args) : + null, + info: u.partial(logit, writerFn, "INFO"), + warn: u.partial(logit, writerFn, "WARN"), + error: u.partial(logit, writerFn, "ERROR"), +}); + +export const log = makeLogger(); + +export const interceptorsFn = ({ + uuidFn = crypto.randomUUID, + logger = log, +} = {}) => ({ + requestId: (req, next) => next({ ...req, id: uuidFn() }), + logged: async (req, next) => { + const { id, url, method } = req; + logger.info({ + id, + url, + method, + type: "in-request", + }); + const response = await next(req); + const { status } = response; + logger.info({ + id, + status, + type: "in-response", + }); + return response; + }, + contentType: async (req, next) => { + const response = await next(req); + const [mimeType, body] = typeof response.body === "string" ? + ["text/html", response.body] : + ["application/json", JSON.stringify(response.body) || ""]; + return { + ...response, + body, + headers: { + "Content-Type": mimeType, + "Content-Length": Buffer.byteLength(body), + ...(response.headers || {}) + }, + }; + }, + serverError: async (req, next) => { + try { + const response = await next(req); + assert.ok("status" in response, `Missing "status"`); + return response; + } catch (error) { + logger.error({ + id: req.id, + type: "server-error-interceptor", + message: error.message, + }); + return { + status: 500, + body: "Internal Server Error\n", + }; + } + }, +}); + +export const interceptors = interceptorsFn(); + +export const defaultInterceptors = [ + interceptors.serverError, + interceptors.contentType, + interceptors.requestId, + interceptors.logged, +]; + +export const chainInterceptors = arr => + req => arr.length === 0 ? + req : + arr[0](req, chainInterceptors(arr.slice(1))); + +export const wrapHandler = (fn, arr) => + arr.length === 0 ? + fn : + chainInterceptors(arr.concat([ (req, _next) => fn(req) ])); + export const normalizeSegments = segments => segments.length === 1 && segments[0] === "" ? segments : @@ -155,110 +259,6 @@ export const makeRequestListener = table => async (req, res) => { res.end(response.body); }; -export const loggerDefaults = { - pid: process.pid, - ppid: process.ppid, - tool: "hero", -}; - -export let loggerGlobals = {}; - -export const configLogger = o => loggerGlobals = o; - -export const logit = (writerFn, level, o) => - writerFn(JSON.stringify({ - ...loggerDefaults, - ...loggerGlobals, - level, - ...o, - })); - -export const makeLogger = (writerFn = console.error) => ({ - debug: (...args) => process.env.DEBUG ? - logit(writerFn, "DEBUG", ...args) : - null, - info: u.partial(logit, writerFn, "INFO"), - warn: u.partial(logit, writerFn, "WARN"), - error: u.partial(logit, writerFn, "ERROR"), -}); - -export const log = makeLogger(); - -export const interceptorsFn = ({ - uuidFn = crypto.randomUUID, - logger = log, -} = {}) => ({ - requestId: (req, next) => next({ ...req, id: uuidFn() }), - logged: async (req, next) => { - const { id, url, method } = req; - logger.info({ - id, - url, - method, - type: "in-request", - }); - const response = await next(req); - const { status } = response; - logger.info({ - id, - status, - type: "in-response", - }); - return response; - }, - contentType: async (req, next) => { - const response = await next(req); - const [mimeType, body] = typeof response.body === "string" ? - ["text/html", response.body] : - ["application/json", JSON.stringify(response.body) || ""]; - return { - ...response, - body, - headers: { - "Content-Type": mimeType, - "Content-Length": Buffer.byteLength(body), - ...(response.headers || {}) - }, - }; - }, - serverError: async (req, next) => { - try { - const response = await next(req); - assert.ok("status" in response, `Missing "status"`); - return response; - } catch (error) { - logger.error({ - id: req.id, - type: "server-error-interceptor", - message: error.message, - }); - return { - status: 500, - body: "Internal Server Error\n", - }; - } - }, -}); - -export const interceptors = interceptorsFn(); - -export const defaultInterceptors = [ - interceptors.serverError, - interceptors.contentType, - interceptors.requestId, - interceptors.logged, -]; - -export const chainInterceptors = arr => - req => arr.length === 0 ? - req : - arr[0](req, chainInterceptors(arr.slice(1))); - -export const wrapHandler = (fn, arr) => - arr.length === 0 ? - fn : - chainInterceptors(arr.concat([ (req, _next) => fn(req) ])); - export const actionsFn = ({ logger = log, } = {}) => ({ |