UNPKG

@interopio/gateway-server

Version:

## `@glue42/gateway-ent` compatibility

87 lines (81 loc) 3.6 kB
import {Metrics} from '@interopio/gateway-metrics-api'; import {Middleware, WebExchange} from '../server/types.js'; import getLogger from '../logger.js'; import {FilePublisherConfig} from '@interopio/gateway/metrics/publisher/file'; import {HttpServerRequest, HttpServerResponse} from '../server/exchange.ts'; const logger = getLogger('metrics'); const COOKIE_NAME = 'GW_LOGIN'; function loggedIn(auth, ctx: WebExchange) { if (auth) { const cookieHeaderValue = ctx.request.headers.list('cookie'); const cookie = cookieHeaderValue?.join('; ').split('; ').find(value => value.startsWith(`${COOKIE_NAME}=`)); return cookie && (parseInt(cookie?.substring(COOKIE_NAME.length + 1)) > Date.now()); } return true; } async function routes(config: {file?: FilePublisherConfig, auth?}): Promise<Middleware<HttpServerRequest, HttpServerResponse>> { const {jsonFileAppender} = await import('@interopio/gateway/metrics/publisher/file'); const appender = jsonFileAppender(logger); await appender.open(config.file?.location ?? 'metrics.ndjson', config.file?.append ?? true); return [ async (ctx, next: () => Promise<void>) => { if (ctx.method === 'GET' && ctx.path === '/api/metrics') { if (loggedIn(config.auth, ctx)) { ctx.response.statusCode = 200; } else { ctx.response.statusCode = 302; ctx.response.headers.set('location', '/api/login?redirectTo=/api/metrics'); } ctx.response._res.end(); } else { await next(); } }, async (ctx, next: () => Promise<void>) => { if (ctx.method === 'GET' && ctx.path === '/api/login') { const redirectTo = new URLSearchParams(ctx.request.query ?? undefined).get('redirectTo'); const expires = Date.now() + 180 * 1000; ctx.response.headers.add('set-cookie', `${COOKIE_NAME}=${expires}; Path=/api; SameSite=strict`) if (redirectTo) { ctx.response.statusCode = 302; ctx.response.headers.set('location', redirectTo); } else { ctx.response.statusCode = 200; } ctx.response._res.end(); } else { await next(); } }, async (ctx, next: () => Promise<void>) => { if (ctx.method === 'POST' && ctx.path === '/api/metrics') { if (loggedIn(config.auth, ctx)) { ctx.response.statusCode = 202; ctx.response._res.end(); try { const json = await ctx.request.json; const update = json as Metrics.Update; if (logger.enabledFor('debug')) { logger.debug(`${JSON.stringify(update)}`); } if ((config.file?.status ?? false) || (update.status === undefined)) { await appender.write(update); } } catch (e) { logger.error(`error processing metrics`, e); } } else { ctx.response.statusCode = 401; ctx.response._res.end(); } } else { await next(); } }, ]; } export default routes;