UNPKG

@whatwg-node/server

Version:

Fetch API compliant HTTP Server adapter

112 lines (111 loc) 3.38 kB
import { completeAssign } from '../utils.js'; export function useUWSAdapter() { const uwsResponseMap = new WeakMap(); return { onRequestAdapt({ args: [res, req, ...restOfCtx], setRequest, setServerContext, fetchAPI }) { if (isUWSResponse(res)) { const request = getRequestFromUWSRequest({ req: req, res, fetchAPI, }); uwsResponseMap.set(request, res); setRequest(request); const defaultServerContext = { req, res, }; const serverContext = restOfCtx.length > 0 ? completeAssign(...restOfCtx) : defaultServerContext; setServerContext(serverContext); } }, onResponse({ request, response }) { const res = uwsResponseMap.get(request); if (res) { return sendResponseToUwsOpts({ res, response, }); } }, }; } export function isUWSResponse(res) { return !!res.onData; } export function getRequestFromUWSRequest({ req, res, fetchAPI }) { let body; const method = req.getMethod(); if (method !== 'get' && method !== 'head') { body = new fetchAPI.ReadableStream({}); const readable = body.readable; res.onAborted(() => { readable.push(null); }); res.onData(function (chunk, isLast) { readable.push(Buffer.from(chunk, 0, chunk.byteLength)); if (isLast) { readable.push(null); } }); } const headers = new fetchAPI.Headers(); req.forEach((key, value) => { headers.set(key, value); }); const url = `http://localhost${req.getUrl()}`; return new fetchAPI.Request(url, { method, headers, body: body, }); } export async function sendResponseToUwsOpts({ res, response }) { let resAborted = false; res.onAborted(function () { resAborted = true; }); res.cork(() => { res.writeStatus(`${response.status} ${response.statusText}`); }); response.headers.forEach((value, key) => { // content-length causes an error with Node.js's fetch if (key !== 'content-length') { if (key === 'set-cookie') { const setCookies = response.headers.getSetCookie?.(); if (setCookies) { setCookies.forEach(setCookie => { res.cork(() => { res.writeHeader(key, setCookie); }); }); return; } } res.cork(() => { res.writeHeader(key, value); }); } }); if (response.bodyType === 'String' || response.bodyType === 'Uint8Array') { res.cork(() => { res.end(response.bodyInit); }); return; } if (!response.body) { res.end(); return; } for await (const chunk of response.body) { if (resAborted) { return; } res.cork(() => { res.write(chunk); }); } res.cork(() => { res.end(); }); }