@whatwg-node/server
Version:
Fetch API compliant HTTP Server adapter
119 lines (118 loc) • 3.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendResponseToUwsOpts = exports.getRequestFromUWSRequest = exports.isUWSResponse = exports.useUWSAdapter = void 0;
const utils_js_1 = require("../utils.js");
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 ? (0, utils_js_1.completeAssign)(...restOfCtx) : defaultServerContext;
setServerContext(serverContext);
}
},
onResponse({ request, response }) {
const res = uwsResponseMap.get(request);
if (res) {
return sendResponseToUwsOpts({
res,
response,
});
}
},
};
}
exports.useUWSAdapter = useUWSAdapter;
function isUWSResponse(res) {
return !!res.onData;
}
exports.isUWSResponse = isUWSResponse;
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,
});
}
exports.getRequestFromUWSRequest = getRequestFromUWSRequest;
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();
});
}
exports.sendResponseToUwsOpts = sendResponseToUwsOpts;