Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@whatwg-node/server

Package Overview
Dependencies
Maintainers
1
Versions
726
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@whatwg-node/server - npm Package Compare versions

Comparing version 0.10.0-alpha-20240717150008-1474b9d9b679a0e8f6225f44f11b95a6f4bf24ea to 0.10.0-alpha-20240726141316-c6ce93b3598457ebe73b3b725986723af8f5e609

cjs/plugins/useContentEncoding.js

10

cjs/createServerAdapter.js

@@ -57,2 +57,5 @@ "use strict";

request,
setRequest(newRequest) {
request = newRequest;
},
serverContext,

@@ -73,3 +76,3 @@ fetchAPI,

function handleResponse(response) {
if (onRequestHooks.length === 0) {
if (onResponseHooks.length === 0) {
return response;

@@ -81,2 +84,6 @@ }

serverContext,
setResponse(newResponse) {
response = newResponse;
},
fetchAPI,
};

@@ -105,2 +112,3 @@ const onResponseHooksIteration$ = (0, utils_js_1.iterateAsyncVoid)(onResponseHooks, onResponseHook => onResponseHook(onResponseHookPayload));

: givenHandleRequest;
// TODO: Remove this on the next major version
function handleNodeRequestAndResponse(nodeRequest, nodeResponseOrContainer, ...ctx) {

@@ -107,0 +115,0 @@ const nodeResponse = nodeResponseOrContainer.raw || nodeResponseOrContainer;

@@ -11,4 +11,5 @@ "use strict";

tslib_1.__exportStar(require("./plugins/useErrorHandling.js"), exports);
tslib_1.__exportStar(require("./plugins/useContentEncoding.js"), exports);
tslib_1.__exportStar(require("./uwebsockets.js"), exports);
var fetch_1 = require("@whatwg-node/fetch");
Object.defineProperty(exports, "Response", { enumerable: true, get: function () { return fetch_1.Response; } });
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServerAdapterRequestAbortSignal = void 0;
exports.decompressedResponseMap = exports.ServerAdapterRequestAbortSignal = void 0;
exports.isAsyncIterable = isAsyncIterable;

@@ -20,2 +20,4 @@ exports.normalizeNodeRequest = normalizeNodeRequest;

exports.handleAbortSignalAndPromiseResponse = handleAbortSignalAndPromiseResponse;
exports.getSupportedEncodings = getSupportedEncodings;
exports.handleResponseDecompression = handleResponseDecompression;
const fetch_1 = require("@whatwg-node/fetch");

@@ -116,3 +118,12 @@ function isAsyncIterable(body) {

let signal;
if (nodeResponse.once) {
let normalizedHeaders = nodeRequest.headers;
if (nodeRequest.headers?.[':method']) {
normalizedHeaders = {};
for (const key in nodeRequest.headers) {
if (!key.startsWith(':')) {
normalizedHeaders[key] = nodeRequest.headers[key];
}
}
}
if (nodeResponse?.once) {
let sendAbortSignal;

@@ -144,3 +155,3 @@ // If ponyfilled

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
signal,

@@ -160,3 +171,3 @@ });

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
body: maybeParsedBody,

@@ -168,3 +179,3 @@ signal,

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
signal,

@@ -197,3 +208,3 @@ });

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
duplex: 'half',

@@ -222,3 +233,3 @@ body: new ReadableStream({

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
body: rawRequest,

@@ -351,3 +362,6 @@ duplex: 'half',

const descriptors = Object.getOwnPropertyNames(source).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
const descriptor = Object.getOwnPropertyDescriptor(source, key);
if (descriptor) {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
}
return descriptors;

@@ -358,3 +372,3 @@ }, {});

const descriptor = Object.getOwnPropertyDescriptor(source, sym);
if (descriptor.enumerable) {
if (descriptor?.enumerable) {
descriptors[sym] = descriptor;

@@ -508,1 +522,53 @@ }

}
exports.decompressedResponseMap = new WeakMap();
const supportedEncodingsByFetchAPI = new WeakMap();
function getSupportedEncodings(fetchAPI) {
let supportedEncodings = supportedEncodingsByFetchAPI.get(fetchAPI);
if (!supportedEncodings) {
const possibleEncodings = ['deflate', 'gzip', 'deflate-raw', 'br'];
supportedEncodings = possibleEncodings.filter(encoding => {
// deflate-raw is not supported in Node.js >v20
if (globalThis.process?.version?.startsWith('v2') &&
fetchAPI.DecompressionStream === globalThis.DecompressionStream &&
encoding === 'deflate-raw') {
return false;
}
try {
// eslint-disable-next-line no-new
new fetchAPI.DecompressionStream(encoding);
return true;
}
catch {
return false;
}
});
supportedEncodingsByFetchAPI.set(fetchAPI, supportedEncodings);
}
return supportedEncodings;
}
function handleResponseDecompression(response, fetchAPI) {
const contentEncodingHeader = response?.headers.get('content-encoding');
if (!contentEncodingHeader || contentEncodingHeader === 'none') {
return response;
}
if (!response?.body) {
return response;
}
let decompressedResponse = exports.decompressedResponseMap.get(response);
if (!decompressedResponse || decompressedResponse.bodyUsed) {
let decompressedBody = response.body;
const contentEncodings = contentEncodingHeader.split(',');
if (!contentEncodings.every(encoding => getSupportedEncodings(fetchAPI).includes(encoding))) {
return new fetchAPI.Response(`Unsupported 'Content-Encoding': ${contentEncodingHeader}`, {
status: 415,
statusText: 'Unsupported Media Type',
});
}
for (const contentEncoding of contentEncodings) {
decompressedBody = decompressedBody.pipeThrough(new fetchAPI.DecompressionStream(contentEncoding));
}
decompressedResponse = new fetchAPI.Response(decompressedBody, response);
exports.decompressedResponseMap.set(response, decompressedResponse);
}
return decompressedResponse;
}

47

cjs/uwebsockets.js

@@ -13,14 +13,38 @@ "use strict";

if (method !== 'get' && method !== 'head') {
body = new fetchAPI.ReadableStream({});
let controller;
body = new fetchAPI.ReadableStream({
start(c) {
controller = c;
},
});
const readable = body.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) {
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();
}
});
}
}

@@ -41,2 +65,5 @@ const headers = new fetchAPI.Headers();

signal,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - not in the TS types yet
duplex: 'half',
});

@@ -43,0 +70,0 @@ }

@@ -53,2 +53,5 @@ /* eslint-disable @typescript-eslint/ban-types */

request,
setRequest(newRequest) {
request = newRequest;
},
serverContext,

@@ -69,3 +72,3 @@ fetchAPI,

function handleResponse(response) {
if (onRequestHooks.length === 0) {
if (onResponseHooks.length === 0) {
return response;

@@ -77,2 +80,6 @@ }

serverContext,
setResponse(newResponse) {
response = newResponse;
},
fetchAPI,
};

@@ -101,2 +108,3 @@ const onResponseHooksIteration$ = iterateAsyncVoid(onResponseHooks, onResponseHook => onResponseHook(onResponseHookPayload));

: givenHandleRequest;
// TODO: Remove this on the next major version
function handleNodeRequestAndResponse(nodeRequest, nodeResponseOrContainer, ...ctx) {

@@ -103,0 +111,0 @@ const nodeResponse = nodeResponseOrContainer.raw || nodeResponseOrContainer;

@@ -7,3 +7,4 @@ export * from './createServerAdapter.js';

export * from './plugins/useErrorHandling.js';
export * from './plugins/useContentEncoding.js';
export * from './uwebsockets.js';
export { Response } from '@whatwg-node/fetch';

@@ -95,3 +95,12 @@ import { URL } from '@whatwg-node/fetch';

let signal;
if (nodeResponse.once) {
let normalizedHeaders = nodeRequest.headers;
if (nodeRequest.headers?.[':method']) {
normalizedHeaders = {};
for (const key in nodeRequest.headers) {
if (!key.startsWith(':')) {
normalizedHeaders[key] = nodeRequest.headers[key];
}
}
}
if (nodeResponse?.once) {
let sendAbortSignal;

@@ -123,3 +132,3 @@ // If ponyfilled

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
signal,

@@ -139,3 +148,3 @@ });

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
body: maybeParsedBody,

@@ -147,3 +156,3 @@ signal,

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
signal,

@@ -176,3 +185,3 @@ });

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
duplex: 'half',

@@ -201,3 +210,3 @@ body: new ReadableStream({

method: nodeRequest.method,
headers: nodeRequest.headers,
headers: normalizedHeaders,
body: rawRequest,

@@ -330,3 +339,6 @@ duplex: 'half',

const descriptors = Object.getOwnPropertyNames(source).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
const descriptor = Object.getOwnPropertyDescriptor(source, key);
if (descriptor) {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
}
return descriptors;

@@ -337,3 +349,3 @@ }, {});

const descriptor = Object.getOwnPropertyDescriptor(source, sym);
if (descriptor.enumerable) {
if (descriptor?.enumerable) {
descriptors[sym] = descriptor;

@@ -487,1 +499,53 @@ }

}
export const decompressedResponseMap = new WeakMap();
const supportedEncodingsByFetchAPI = new WeakMap();
export function getSupportedEncodings(fetchAPI) {
let supportedEncodings = supportedEncodingsByFetchAPI.get(fetchAPI);
if (!supportedEncodings) {
const possibleEncodings = ['deflate', 'gzip', 'deflate-raw', 'br'];
supportedEncodings = possibleEncodings.filter(encoding => {
// deflate-raw is not supported in Node.js >v20
if (globalThis.process?.version?.startsWith('v2') &&
fetchAPI.DecompressionStream === globalThis.DecompressionStream &&
encoding === 'deflate-raw') {
return false;
}
try {
// eslint-disable-next-line no-new
new fetchAPI.DecompressionStream(encoding);
return true;
}
catch {
return false;
}
});
supportedEncodingsByFetchAPI.set(fetchAPI, supportedEncodings);
}
return supportedEncodings;
}
export function handleResponseDecompression(response, fetchAPI) {
const contentEncodingHeader = response?.headers.get('content-encoding');
if (!contentEncodingHeader || contentEncodingHeader === 'none') {
return response;
}
if (!response?.body) {
return response;
}
let decompressedResponse = decompressedResponseMap.get(response);
if (!decompressedResponse || decompressedResponse.bodyUsed) {
let decompressedBody = response.body;
const contentEncodings = contentEncodingHeader.split(',');
if (!contentEncodings.every(encoding => getSupportedEncodings(fetchAPI).includes(encoding))) {
return new fetchAPI.Response(`Unsupported 'Content-Encoding': ${contentEncodingHeader}`, {
status: 415,
statusText: 'Unsupported Media Type',
});
}
for (const contentEncoding of contentEncodings) {
decompressedBody = decompressedBody.pipeThrough(new fetchAPI.DecompressionStream(contentEncoding));
}
decompressedResponse = new fetchAPI.Response(decompressedBody, response);
decompressedResponseMap.set(response, decompressedResponse);
}
return decompressedResponse;
}

@@ -8,14 +8,38 @@ export function isUWSResponse(res) {

if (method !== 'get' && method !== 'head') {
body = new fetchAPI.ReadableStream({});
let controller;
body = new fetchAPI.ReadableStream({
start(c) {
controller = c;
},
});
const readable = body.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) {
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();
}
});
}
}

@@ -36,2 +60,5 @@ const headers = new fetchAPI.Headers();

signal,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - not in the TS types yet
duplex: 'half',
});

@@ -38,0 +65,0 @@ }

{
"name": "@whatwg-node/server",
"version": "0.10.0-alpha-20240717150008-1474b9d9b679a0e8f6225f44f11b95a6f4bf24ea",
"version": "0.10.0-alpha-20240726141316-c6ce93b3598457ebe73b3b725986723af8f5e609",
"description": "Fetch API compliant HTTP Server adapter",
"sideEffects": false,
"dependencies": {
"@whatwg-node/fetch": "^0.9.17",
"@whatwg-node/fetch": "^0.9.19",
"tslib": "^2.6.3"

@@ -9,0 +9,0 @@ },

@@ -7,3 +7,4 @@ export * from './createServerAdapter.js';

export * from './plugins/useErrorHandling.js';
export * from './plugins/useContentEncoding.js';
export * from './uwebsockets.js';
export { Response } from '@whatwg-node/fetch';

@@ -9,2 +9,3 @@ import { FetchAPI, ServerAdapterRequestHandler, type ServerAdapterInitialContext } from '../types.js';

request: Request;
setRequest(newRequest: Request): void;
serverContext: TServerContext;

@@ -22,2 +23,4 @@ fetchAPI: FetchAPI;

response: Response;
setResponse(newResponse: Response): void;
fetchAPI: FetchAPI;
}

@@ -7,7 +7,7 @@ import { ServerAdapterPlugin } from './types.js';

headers: HeadersInit;
details?: any | undefined;
details?: any;
name: string;
constructor(status: number, message: string, headers?: HeadersInit, details?: any | undefined);
constructor(status: number, message: string, headers?: HeadersInit, details?: any);
}
export type ErrorHandler<TServerContext> = (e: any, request: Request, ctx: TServerContext) => Response | Promise<Response>;
export declare function useErrorHandling<TServerContext>(onError?: ErrorHandler<TServerContext>): ServerAdapterPlugin<TServerContext>;

@@ -5,3 +5,3 @@ import type { IncomingMessage, ServerResponse } from 'http';

import type { Readable } from 'stream';
import type { FetchEvent } from './types.js';
import type { FetchAPI, FetchEvent } from './types.js';
export declare function isAsyncIterable(body: any): body is AsyncIterable<any>;

@@ -54,1 +54,4 @@ export interface NodeRequest {

export declare function handleAbortSignalAndPromiseResponse(response$: Promise<Response> | Response, abortSignal?: AbortSignal | null): Response | Promise<Response>;
export declare const decompressedResponseMap: WeakMap<Response, Response>;
export declare function getSupportedEncodings(fetchAPI: FetchAPI): CompressionFormat[];
export declare function handleResponseDecompression(response: Response, fetchAPI: FetchAPI): Response;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc