@whatwg-node/server
Advanced tools
Comparing version 0.9.49 to 0.9.50-rc-20241021101256-81d8f1da00e4bf6af4554659e281a14cc06847a5
@@ -6,2 +6,4 @@ "use strict"; | ||
exports.sendResponseToUwsOpts = sendResponseToUwsOpts; | ||
exports.fakePromise = fakePromise; | ||
const utils_js_1 = require("./utils.js"); | ||
function isUWSResponse(res) { | ||
@@ -11,41 +13,63 @@ return !!res.onData; | ||
function getRequestFromUWSRequest({ req, res, fetchAPI, signal }) { | ||
let body; | ||
const method = req.getMethod(); | ||
let duplex; | ||
const chunks = []; | ||
const pushFns = [ | ||
(chunk) => { | ||
chunks.push(chunk); | ||
}, | ||
]; | ||
const push = (chunk) => { | ||
for (const pushFn of pushFns) { | ||
pushFn(chunk); | ||
} | ||
}; | ||
let stopped = false; | ||
const stopFns = [ | ||
() => { | ||
stopped = true; | ||
}, | ||
]; | ||
const stop = () => { | ||
for (const stopFn of stopFns) { | ||
stopFn(); | ||
} | ||
}; | ||
res.onData(function (ab, isLast) { | ||
push(Buffer.from(Buffer.from(ab, 0, ab.byteLength))); | ||
if (isLast) { | ||
stop(); | ||
} | ||
}); | ||
let getReadableStream; | ||
if (method !== 'get' && method !== 'head') { | ||
let controller; | ||
body = new fetchAPI.ReadableStream({ | ||
start(c) { | ||
controller = c; | ||
}, | ||
duplex = 'half'; | ||
signal.addEventListener('abort', () => { | ||
stop(); | ||
}); | ||
const readable = body.readable; | ||
if (readable) { | ||
signal.addEventListener('abort', () => { | ||
readable.push(null); | ||
}); | ||
res.onData(function (ab, isLast) { | ||
const chunk = Buffer.from(ab, 0, ab.byteLength); | ||
readable.push(Buffer.from(chunk)); | ||
if (isLast) { | ||
readable.push(null); | ||
} | ||
}); | ||
} | ||
else { | ||
let closed = false; | ||
signal.addEventListener('abort', () => { | ||
if (!closed) { | ||
closed = true; | ||
controller.close(); | ||
} | ||
}); | ||
res.onData(function (ab, isLast) { | ||
const chunk = Buffer.from(ab, 0, ab.byteLength); | ||
controller.enqueue(Buffer.from(chunk)); | ||
if (isLast) { | ||
closed = true; | ||
controller.close(); | ||
} | ||
}); | ||
} | ||
let readableStream; | ||
getReadableStream = () => { | ||
if (!readableStream) { | ||
readableStream = new fetchAPI.ReadableStream({ | ||
start(controller) { | ||
for (const chunk of chunks) { | ||
controller.enqueue(chunk); | ||
} | ||
if (stopped) { | ||
controller.close(); | ||
return; | ||
} | ||
pushFns.push((chunk) => { | ||
controller.enqueue(chunk); | ||
}); | ||
stopFns.push(() => { | ||
if (controller.desiredSize) { | ||
controller.close(); | ||
} | ||
}); | ||
}, | ||
}); | ||
} | ||
return readableStream; | ||
}; | ||
} | ||
@@ -61,11 +85,69 @@ const headers = new fetchAPI.Headers(); | ||
} | ||
return new fetchAPI.Request(url, { | ||
let buffer; | ||
function getBody() { | ||
if (!getReadableStream) { | ||
return null; | ||
} | ||
if (stopped) { | ||
return getBufferFromChunks(); | ||
} | ||
return getReadableStream(); | ||
} | ||
const request = new fetchAPI.Request(url, { | ||
method, | ||
headers, | ||
body: body, | ||
get body() { | ||
return getBody(); | ||
}, | ||
signal, | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore - not in the TS types yet | ||
duplex: 'half', | ||
duplex, | ||
}); | ||
function getBufferFromChunks() { | ||
if (!buffer) { | ||
buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks); | ||
} | ||
return buffer; | ||
} | ||
function collectBuffer() { | ||
if (stopped) { | ||
return fakePromise(getBufferFromChunks()); | ||
} | ||
return new Promise((resolve, reject) => { | ||
try { | ||
stopFns.push(() => { | ||
resolve(getBufferFromChunks()); | ||
}); | ||
} | ||
catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
} | ||
Object.defineProperties(request, { | ||
body: { | ||
get() { | ||
return getBody(); | ||
}, | ||
}, | ||
json: { | ||
value() { | ||
return collectBuffer() | ||
.then(b => b.toString('utf8')) | ||
.then(t => JSON.parse(t)); | ||
}, | ||
}, | ||
text: { | ||
value() { | ||
return collectBuffer().then(b => b.toString('utf8')); | ||
}, | ||
}, | ||
arrayBuffer: { | ||
value() { | ||
return collectBuffer(); | ||
}, | ||
}, | ||
}); | ||
return request; | ||
} | ||
@@ -125,1 +207,34 @@ async function forwardResponseBodyToUWSResponse(uwsResponse, fetchResponse, signal) { | ||
} | ||
function fakePromise(value) { | ||
if ((0, utils_js_1.isPromise)(value)) { | ||
return value; | ||
} | ||
// Write a fake promise to avoid the promise constructor | ||
// being called with `new Promise` in the browser. | ||
return { | ||
then(resolve) { | ||
if (resolve) { | ||
const callbackResult = resolve(value); | ||
if ((0, utils_js_1.isPromise)(callbackResult)) { | ||
return callbackResult; | ||
} | ||
return fakePromise(callbackResult); | ||
} | ||
return this; | ||
}, | ||
catch() { | ||
return this; | ||
}, | ||
finally(cb) { | ||
if (cb) { | ||
const callbackResult = cb(); | ||
if ((0, utils_js_1.isPromise)(callbackResult)) { | ||
return callbackResult.then(() => value); | ||
} | ||
return fakePromise(value); | ||
} | ||
return this; | ||
}, | ||
[Symbol.toStringTag]: 'Promise', | ||
}; | ||
} |
@@ -0,1 +1,2 @@ | ||
import { isPromise } from './utils.js'; | ||
export function isUWSResponse(res) { | ||
@@ -5,41 +6,63 @@ return !!res.onData; | ||
export function getRequestFromUWSRequest({ req, res, fetchAPI, signal }) { | ||
let body; | ||
const method = req.getMethod(); | ||
let duplex; | ||
const chunks = []; | ||
const pushFns = [ | ||
(chunk) => { | ||
chunks.push(chunk); | ||
}, | ||
]; | ||
const push = (chunk) => { | ||
for (const pushFn of pushFns) { | ||
pushFn(chunk); | ||
} | ||
}; | ||
let stopped = false; | ||
const stopFns = [ | ||
() => { | ||
stopped = true; | ||
}, | ||
]; | ||
const stop = () => { | ||
for (const stopFn of stopFns) { | ||
stopFn(); | ||
} | ||
}; | ||
res.onData(function (ab, isLast) { | ||
push(Buffer.from(Buffer.from(ab, 0, ab.byteLength))); | ||
if (isLast) { | ||
stop(); | ||
} | ||
}); | ||
let getReadableStream; | ||
if (method !== 'get' && method !== 'head') { | ||
let controller; | ||
body = new fetchAPI.ReadableStream({ | ||
start(c) { | ||
controller = c; | ||
}, | ||
duplex = 'half'; | ||
signal.addEventListener('abort', () => { | ||
stop(); | ||
}); | ||
const readable = body.readable; | ||
if (readable) { | ||
signal.addEventListener('abort', () => { | ||
readable.push(null); | ||
}); | ||
res.onData(function (ab, isLast) { | ||
const chunk = Buffer.from(ab, 0, ab.byteLength); | ||
readable.push(Buffer.from(chunk)); | ||
if (isLast) { | ||
readable.push(null); | ||
} | ||
}); | ||
} | ||
else { | ||
let closed = false; | ||
signal.addEventListener('abort', () => { | ||
if (!closed) { | ||
closed = true; | ||
controller.close(); | ||
} | ||
}); | ||
res.onData(function (ab, isLast) { | ||
const chunk = Buffer.from(ab, 0, ab.byteLength); | ||
controller.enqueue(Buffer.from(chunk)); | ||
if (isLast) { | ||
closed = true; | ||
controller.close(); | ||
} | ||
}); | ||
} | ||
let readableStream; | ||
getReadableStream = () => { | ||
if (!readableStream) { | ||
readableStream = new fetchAPI.ReadableStream({ | ||
start(controller) { | ||
for (const chunk of chunks) { | ||
controller.enqueue(chunk); | ||
} | ||
if (stopped) { | ||
controller.close(); | ||
return; | ||
} | ||
pushFns.push((chunk) => { | ||
controller.enqueue(chunk); | ||
}); | ||
stopFns.push(() => { | ||
if (controller.desiredSize) { | ||
controller.close(); | ||
} | ||
}); | ||
}, | ||
}); | ||
} | ||
return readableStream; | ||
}; | ||
} | ||
@@ -55,11 +78,69 @@ const headers = new fetchAPI.Headers(); | ||
} | ||
return new fetchAPI.Request(url, { | ||
let buffer; | ||
function getBody() { | ||
if (!getReadableStream) { | ||
return null; | ||
} | ||
if (stopped) { | ||
return getBufferFromChunks(); | ||
} | ||
return getReadableStream(); | ||
} | ||
const request = new fetchAPI.Request(url, { | ||
method, | ||
headers, | ||
body: body, | ||
get body() { | ||
return getBody(); | ||
}, | ||
signal, | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore - not in the TS types yet | ||
duplex: 'half', | ||
duplex, | ||
}); | ||
function getBufferFromChunks() { | ||
if (!buffer) { | ||
buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks); | ||
} | ||
return buffer; | ||
} | ||
function collectBuffer() { | ||
if (stopped) { | ||
return fakePromise(getBufferFromChunks()); | ||
} | ||
return new Promise((resolve, reject) => { | ||
try { | ||
stopFns.push(() => { | ||
resolve(getBufferFromChunks()); | ||
}); | ||
} | ||
catch (e) { | ||
reject(e); | ||
} | ||
}); | ||
} | ||
Object.defineProperties(request, { | ||
body: { | ||
get() { | ||
return getBody(); | ||
}, | ||
}, | ||
json: { | ||
value() { | ||
return collectBuffer() | ||
.then(b => b.toString('utf8')) | ||
.then(t => JSON.parse(t)); | ||
}, | ||
}, | ||
text: { | ||
value() { | ||
return collectBuffer().then(b => b.toString('utf8')); | ||
}, | ||
}, | ||
arrayBuffer: { | ||
value() { | ||
return collectBuffer(); | ||
}, | ||
}, | ||
}); | ||
return request; | ||
} | ||
@@ -119,1 +200,34 @@ async function forwardResponseBodyToUWSResponse(uwsResponse, fetchResponse, signal) { | ||
} | ||
export function fakePromise(value) { | ||
if (isPromise(value)) { | ||
return value; | ||
} | ||
// Write a fake promise to avoid the promise constructor | ||
// being called with `new Promise` in the browser. | ||
return { | ||
then(resolve) { | ||
if (resolve) { | ||
const callbackResult = resolve(value); | ||
if (isPromise(callbackResult)) { | ||
return callbackResult; | ||
} | ||
return fakePromise(callbackResult); | ||
} | ||
return this; | ||
}, | ||
catch() { | ||
return this; | ||
}, | ||
finally(cb) { | ||
if (cb) { | ||
const callbackResult = cb(); | ||
if (isPromise(callbackResult)) { | ||
return callbackResult.then(() => value); | ||
} | ||
return fakePromise(value); | ||
} | ||
return this; | ||
}, | ||
[Symbol.toStringTag]: 'Promise', | ||
}; | ||
} |
{ | ||
"name": "@whatwg-node/server", | ||
"version": "0.9.49", | ||
"version": "0.9.50-rc-20241021101256-81d8f1da00e4bf6af4554659e281a14cc06847a5", | ||
"description": "Fetch API compliant HTTP Server adapter", | ||
@@ -5,0 +5,0 @@ "sideEffects": false, |
@@ -31,2 +31,3 @@ import type { FetchAPI } from './types.js'; | ||
export declare function sendResponseToUwsOpts(uwsResponse: UWSResponse, fetchResponse: Response, signal: ServerAdapterRequestAbortSignal): Promise<void> | undefined; | ||
export declare function fakePromise<T>(value: T): Promise<T>; | ||
export {}; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
149200
3174