UNPKG

@roots/bud-server

Version:

Development server for @roots/bud

84 lines (68 loc) 2.3 kB
import type {Bud} from '@roots/bud-framework' import type {Buffer} from 'node:buffer' import type {IncomingMessage, ServerResponse} from 'node:http' import {responseInterceptor} from '@roots/bud-support/http-proxy-middleware' declare module 'node:http' { interface IncomingMessage { cookies?: Record<string, any> } interface ServerResponse { cookie: CallableFunction } } const factory = (bud: Bud, url: Record<string, URL>) => { return responseInterceptor(async (buffer, proxy, request, response) => { response.setHeader(`x-proxy-by`, `@roots/bud`) response.removeHeader(`content-security-policy`) response.removeHeader(`x-http-method-override`) setResponseCookies(request, response) return transformResponseBuffer(bud, url, proxy, buffer) }) } const setResponseCookies = ( request: IncomingMessage, response: ServerResponse, ) => { if (request.cookies) { Object.entries(request.cookies).map(([k, v]) => { response.cookie(k, v, {domain: undefined}) }) } const headers = response.getHeaders() if (!headers[`set-cookie`]) return const cookies = Array.isArray(headers[`set-cookie`]) ? headers[`set-cookie`] : [headers[`set-cookie`]] response.setHeader( `set-cookie`, cookies.map(String).map(value => value.replace(`; secure`, ``).trim()), ) } const transformResponseBuffer = ( bud: Bud, url: Record<string, URL>, proxy: IncomingMessage, // eslint-disable-next-line @typescript-eslint/ban-types buffer: Buffer, ) => { if (!isTransformable(proxy)) return buffer if (!url.dev?.origin || !url.publicProxy.origin) return buffer return bud.hooks .filter(`dev.middleware.proxy.replacements`, [ [url.publicProxy.origin, url.dev.origin], ]) .reduce(transformBody, buffer.toString()) } const isTransformable = (message?: IncomingMessage) => { if (typeof message?.headers?.[`content-type`] !== `string`) return false const type = message.headers[`content-type`] return ( type.startsWith(`text/css`) || type.startsWith(`text/html`) || type.startsWith(`application/javascript`) || type.startsWith(`application/json`) ) } const transformBody = (value: string, [search, replace]) => value.replaceAll(new RegExp(search, `g`), replace) export {factory}