Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

@aws-sdk/middleware-websocket

Package Overview
Dependencies
Maintainers
2
Versions
127
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@aws-sdk/middleware-websocket - npm Package Compare versions

Comparing version
3.972.4
to
3.972.5
+31
dist-es/middlewares/websocketEndpointMiddleware.js
import { HttpRequest } from "@smithy/protocol-http";
export const websocketEndpointMiddleware = (config, options) => (next) => (args) => {
const { request } = args;
if (HttpRequest.isInstance(request) &&
config.requestHandler.metadata?.handlerProtocol?.toLowerCase().includes("websocket")) {
request.protocol = "wss:";
request.method = "GET";
request.path = `${request.path}-websocket`;
const { headers } = request;
delete headers["content-type"];
delete headers["x-amz-content-sha256"];
for (const name of Object.keys(headers)) {
if (name.indexOf(options.headerPrefix) === 0) {
const chunkedName = name.replace(options.headerPrefix, "");
request.query[chunkedName] = headers[name];
}
}
if (headers["x-amz-user-agent"]) {
request.query["user-agent"] = headers["x-amz-user-agent"];
}
request.headers = { host: headers.host ?? request.hostname };
}
return next(args);
};
export const websocketEndpointMiddlewareOptions = {
name: "websocketEndpointMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM"],
relation: "after",
toMiddleware: "eventStreamHeaderMiddleware",
override: true,
};
export const injectSessionIdMiddleware = () => (next) => async (args) => {
const requestParams = {
...args.input,
};
const response = await next(args);
const output = response.output;
if (requestParams.SessionId && output.SessionId == null) {
output.SessionId = requestParams.SessionId;
}
return response;
};
export const injectSessionIdMiddlewareOptions = {
step: "initialize",
name: "injectSessionIdMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM"],
override: true,
};
import { WebsocketSignatureV4 } from "./WebsocketSignatureV4";
export const resolveWebSocketConfig = (input) => {
const { signer } = input;
return Object.assign(input, {
signer: async (authScheme) => {
const signerObj = await signer(authScheme);
if (validateSigner(signerObj)) {
return new WebsocketSignatureV4({ signer: signerObj });
}
throw new Error("Expected WebsocketSignatureV4 signer, please check the client constructor.");
},
});
};
const validateSigner = (signer) => !!signer;
import { formatUrl } from "@aws-sdk/util-format-url";
import { iterableToReadableStream, readableStreamtoIterable } from "@smithy/eventstream-serde-browser";
import { FetchHttpHandler } from "@smithy/fetch-http-handler";
import { HttpResponse } from "@smithy/protocol-http";
import { fromBase64 } from "@smithy/util-base64";
import { isWebSocketRequest } from "./utils";
const DEFAULT_WS_CONNECTION_TIMEOUT_MS = 3000;
export class WebSocketFetchHandler {
metadata = {
handlerProtocol: "websocket/h1.1",
};
config = {};
configPromise;
httpHandler;
sockets = {};
static create(instanceOrOptions, httpHandler = new FetchHttpHandler()) {
if (typeof instanceOrOptions?.handle === "function") {
return instanceOrOptions;
}
return new WebSocketFetchHandler(instanceOrOptions, httpHandler);
}
constructor(options, httpHandler = new FetchHttpHandler()) {
this.httpHandler = httpHandler;
const setConfig = (opts) => {
this.config = {
...(opts ?? {}),
};
return this.config;
};
if (typeof options === "function") {
this.config = {};
this.configPromise = options().then((opts) => {
return setConfig(opts);
});
}
else {
this.configPromise = Promise.resolve(setConfig(options));
}
}
destroy() {
for (const [key, sockets] of Object.entries(this.sockets)) {
for (const socket of sockets) {
socket.close(1000, `Socket closed through destroy() call`);
}
delete this.sockets[key];
}
}
async handle(request) {
this.config = await this.configPromise;
const { logger } = this.config;
if (!isWebSocketRequest(request)) {
logger?.debug?.(`@aws-sdk - ws fetching ${request.protocol}${request.hostname}${request.path}`);
return this.httpHandler.handle(request);
}
const url = formatUrl(request);
logger?.debug?.(`@aws-sdk - ws connecting ${url.split("?")[0]}`);
const socket = new WebSocket(url);
if (!this.sockets[url]) {
this.sockets[url] = [];
}
this.sockets[url].push(socket);
socket.binaryType = "arraybuffer";
const { connectionTimeout = DEFAULT_WS_CONNECTION_TIMEOUT_MS } = this.config;
await this.waitForReady(socket, connectionTimeout);
const { body } = request;
const bodyStream = getIterator(body);
const asyncIterable = this.connect(socket, bodyStream);
const outputPayload = toReadableStream(asyncIterable);
return {
response: new HttpResponse({
statusCode: 200,
body: outputPayload,
}),
};
}
updateHttpClientConfig(key, value) {
this.configPromise = this.configPromise.then((config) => {
config[key] = value;
return config;
});
}
httpHandlerConfigs() {
return this.config ?? {};
}
removeNotUsableSockets(url) {
this.sockets[url] = (this.sockets[url] ?? []).filter((socket) => ![WebSocket.CLOSING, WebSocket.CLOSED].includes(socket.readyState));
}
waitForReady(socket, connectionTimeout) {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
this.removeNotUsableSockets(socket.url);
reject({
$metadata: {
httpStatusCode: 500,
websocketSynthetic500Error: true,
},
});
}, connectionTimeout);
socket.onopen = () => {
clearTimeout(timeout);
resolve();
};
});
}
connect(socket, data) {
const messageQueue = [];
let pendingResolve = null;
let pendingReject = null;
const push = (item) => {
if (pendingResolve) {
if (item.error) {
pendingReject(item.error);
}
else {
pendingResolve({ done: item.done, value: item.value });
}
pendingResolve = null;
pendingReject = null;
}
else {
messageQueue.push(item);
}
};
socket.onmessage = (event) => {
const { data } = event;
if (typeof data === "string") {
push({
done: false,
value: fromBase64(data),
});
}
else {
push({
done: false,
value: new Uint8Array(data),
});
}
};
socket.onerror = (event) => {
socket.close();
push({ done: true, error: event });
};
socket.onclose = () => {
this.removeNotUsableSockets(socket.url);
push({ done: true });
};
const outputStream = {
[Symbol.asyncIterator]: () => ({
async next() {
if (messageQueue.length > 0) {
const item = messageQueue.shift();
if (item.error) {
throw item.error;
}
return { done: item.done, value: item.value };
}
return new Promise((resolve, reject) => {
pendingResolve = resolve;
pendingReject = reject;
});
},
}),
};
const send = async () => {
try {
for await (const chunk of data) {
if (socket.readyState >= WebSocket.CLOSING) {
break;
}
else {
socket.send(chunk);
}
}
}
catch (err) {
push({
done: true,
error: err,
});
}
finally {
socket.close(1000);
}
};
send();
return outputStream;
}
}
const getIterator = (stream) => {
if (stream[Symbol.asyncIterator]) {
return stream;
}
if (isReadableStream(stream)) {
return readableStreamtoIterable(stream);
}
return {
[Symbol.asyncIterator]: async function* () {
yield stream;
},
};
};
const toReadableStream = (asyncIterable) => typeof ReadableStream === "function" ? iterableToReadableStream(asyncIterable) : asyncIterable;
const isReadableStream = (payload) => typeof ReadableStream === "function" && payload instanceof ReadableStream;
import { fromHex } from "@smithy/util-hex-encoding";
export class EventSigningTransformStream extends TransformStream {
constructor(initialSignature, messageSigner, eventStreamCodec, systemClockOffsetProvider) {
let priorSignature = initialSignature;
super({
start() { },
async transform(chunk, controller) {
try {
const now = new Date(Date.now() + (await systemClockOffsetProvider()));
const dateHeader = {
":date": { type: "timestamp", value: now },
};
const signedMessage = await messageSigner.sign({
message: {
body: chunk,
headers: dateHeader,
},
priorSignature: priorSignature,
}, {
signingDate: now,
});
priorSignature = signedMessage.signature;
const serializedSigned = eventStreamCodec.encode({
headers: {
...dateHeader,
":chunk-signature": {
type: "binary",
value: fromHex(signedMessage.signature),
},
},
body: chunk,
});
controller.enqueue(serializedSigned);
}
catch (error) {
controller.error(error);
}
},
});
}
}
import { EventStreamCodec } from "@smithy/eventstream-codec";
import { EventSigningTransformStream } from "./EventSigningTransformStream";
export class EventStreamPayloadHandler {
messageSigner;
eventStreamCodec;
systemClockOffsetProvider;
constructor(options) {
this.messageSigner = options.messageSigner;
this.eventStreamCodec = new EventStreamCodec(options.utf8Encoder, options.utf8Decoder);
this.systemClockOffsetProvider = async () => options.systemClockOffset ?? 0;
}
async handle(next, args, context = {}) {
const request = args.request;
const { body: payload, headers, query } = request;
if (!(payload instanceof ReadableStream)) {
throw new Error("Eventstream payload must be a ReadableStream.");
}
const placeHolderStream = new TransformStream();
request.body = placeHolderStream.readable;
const match = (headers?.authorization ?? "").match(/Signature=(\w+)$/);
const priorSignature = (match ?? [])[1] ?? (query && query["X-Amz-Signature"]) ?? "";
const signingStream = new EventSigningTransformStream(priorSignature, await this.messageSigner(), this.eventStreamCodec, this.systemClockOffsetProvider);
payload.pipeThrough(signingStream).pipeThrough(placeHolderStream);
let result;
try {
result = await next(args);
}
catch (e) {
const p = payload.cancel?.();
if (p instanceof Promise) {
p.catch(() => { });
}
throw e;
}
return result;
}
}
import { EventStreamPayloadHandler } from "./EventStreamPayloadHandler";
export const eventStreamPayloadHandlerProvider = (options) => new EventStreamPayloadHandler(options);
import type { BuildMiddleware, RelativeMiddlewareOptions, RequestHandler } from "@smithy/types";
/**
* Middleware that modify the request to from http to WebSocket
* This middleware can only be applied to commands that supports bi-directional event streaming via WebSocket.
* Example of headerPrefix is "x-amz-rekognition-streaming-liveness-*" prefix exists for all rekognition streaming
* websocket API's headers. The common prefix are to be removed when moving them from headers to querystring.
*/
export declare const websocketEndpointMiddleware: (config: {
requestHandler: RequestHandler<any, any>;
}, options: {
headerPrefix: string;
}) => BuildMiddleware<any, any>;
export declare const websocketEndpointMiddlewareOptions: RelativeMiddlewareOptions;
import type { InitializeHandlerOptions, InitializeMiddleware } from "@smithy/types";
/**
* Most WebSocket operations contains `SessionId` parameter in both input and
* output, with the same value. This middleware populates the `SessionId`
* parameter from request to the response. This is necessary because in
* WebSocket, the SDK cannot access any parameters other than the response
* stream. So we fake response parameter.
*/
export declare const injectSessionIdMiddleware: () => InitializeMiddleware<any, any>;
export declare const injectSessionIdMiddlewareOptions: InitializeHandlerOptions;
import type { AuthScheme, RequestHandler, RequestSigner } from "@smithy/types";
/**
* @public
*/
export interface WebSocketInputConfig {
}
interface PreviouslyResolved {
signer: (authScheme: AuthScheme) => Promise<RequestSigner>;
requestHandler: RequestHandler<any, any>;
}
export interface WebSocketResolvedConfig {
/**
* Resolved value of input config {@link AwsAuthInputConfig.signer}
*/
signer: (authScheme: AuthScheme) => Promise<RequestSigner>;
/**
* The HTTP handler to use. Fetch in browser and Https in Nodejs.
*/
requestHandler: RequestHandler<any, any>;
}
export declare const resolveWebSocketConfig: <T>(input: T & WebSocketInputConfig & PreviouslyResolved) => T & WebSocketResolvedConfig;
export {};
import {
BuildMiddleware,
RelativeMiddlewareOptions,
RequestHandler,
} from "@smithy/types";
export declare const websocketEndpointMiddleware: (
config: {
requestHandler: RequestHandler<any, any>;
},
options: {
headerPrefix: string;
}
) => BuildMiddleware<any, any>;
export declare const websocketEndpointMiddlewareOptions: RelativeMiddlewareOptions;
import { InitializeHandlerOptions, InitializeMiddleware } from "@smithy/types";
export declare const injectSessionIdMiddleware: () => InitializeMiddleware<
any,
any
>;
export declare const injectSessionIdMiddlewareOptions: InitializeHandlerOptions;
import { AuthScheme, RequestHandler, RequestSigner } from "@smithy/types";
export interface WebSocketInputConfig {}
interface PreviouslyResolved {
signer: (authScheme: AuthScheme) => Promise<RequestSigner>;
requestHandler: RequestHandler<any, any>;
}
export interface WebSocketResolvedConfig {
signer: (authScheme: AuthScheme) => Promise<RequestSigner>;
requestHandler: RequestHandler<any, any>;
}
export declare const resolveWebSocketConfig: <T>(
input: T & WebSocketInputConfig & PreviouslyResolved
) => T & WebSocketResolvedConfig;
export {};
import { HttpRequest } from "@smithy/protocol-http";
import { HttpResponse } from "@smithy/protocol-http";
import {
Logger,
Provider,
RequestHandler,
RequestHandlerMetadata,
} from "@smithy/types";
export interface WebSocketFetchHandlerOptions {
connectionTimeout?: number;
logger?: Logger;
}
export declare class WebSocketFetchHandler {
readonly metadata: RequestHandlerMetadata;
private config;
private configPromise;
private readonly httpHandler;
private readonly sockets;
static create(
instanceOrOptions?:
| WebSocketFetchHandler
| WebSocketFetchHandlerOptions
| Provider<WebSocketFetchHandlerOptions | void>,
httpHandler?: RequestHandler<any, any>
): WebSocketFetchHandler;
constructor(
options?:
| WebSocketFetchHandlerOptions
| Provider<WebSocketFetchHandlerOptions>,
httpHandler?: RequestHandler<any, any>
);
destroy(): void;
handle(request: HttpRequest): Promise<{
response: HttpResponse;
}>;
updateHttpClientConfig(
key: keyof WebSocketFetchHandlerOptions,
value: WebSocketFetchHandlerOptions[typeof key]
): void;
httpHandlerConfigs(): WebSocketFetchHandlerOptions;
private removeNotUsableSockets;
private waitForReady;
private connect;
}
import { EventStreamCodec } from "@smithy/eventstream-codec";
import { MessageSigner, Provider } from "@smithy/types";
export declare class EventSigningTransformStream extends TransformStream<
Uint8Array,
Uint8Array
> {
readable: ReadableStream<Uint8Array>;
writable: WritableStream<Uint8Array>;
constructor(
initialSignature: string,
messageSigner: MessageSigner,
eventStreamCodec: EventStreamCodec,
systemClockOffsetProvider: Provider<number>
);
}
import {
Decoder,
Encoder,
EventStreamPayloadHandler as IEventStreamPayloadHandler,
FinalizeHandler,
FinalizeHandlerArguments,
FinalizeHandlerOutput,
HandlerExecutionContext,
MessageSigner,
MetadataBearer,
Provider,
} from "@smithy/types";
export interface EventStreamPayloadHandlerOptions {
messageSigner: Provider<MessageSigner>;
utf8Encoder: Encoder;
utf8Decoder: Decoder;
systemClockOffset?: number;
}
export declare class EventStreamPayloadHandler
implements IEventStreamPayloadHandler
{
private readonly messageSigner;
private readonly eventStreamCodec;
private readonly systemClockOffsetProvider;
constructor(options: EventStreamPayloadHandlerOptions);
handle<T extends MetadataBearer>(
next: FinalizeHandler<any, T>,
args: FinalizeHandlerArguments<any>,
context?: HandlerExecutionContext
): Promise<FinalizeHandlerOutput<T>>;
}
import { EventStreamPayloadHandlerProvider } from "@smithy/types";
export declare const eventStreamPayloadHandlerProvider: EventStreamPayloadHandlerProvider;
import type { HttpRequest } from "@smithy/protocol-http";
import { HttpResponse } from "@smithy/protocol-http";
import type { Logger, Provider, RequestHandler, RequestHandlerMetadata } from "@smithy/types";
export interface WebSocketFetchHandlerOptions {
/**
* The maximum time in milliseconds that the connection phase of a request
* may take before the connection attempt is abandoned.
*/
connectionTimeout?: number;
/**
* Optional logger.
*/
logger?: Logger;
}
/**
* Base handler for websocket requests and HTTP request. By default, the request input and output
* body will be in a ReadableStream, because of interface consistency among middleware.
* If ReadableStream is not available, like in React-Native, the response body
* will be an async iterable.
*/
export declare class WebSocketFetchHandler {
readonly metadata: RequestHandlerMetadata;
private config;
private configPromise;
private readonly httpHandler;
private readonly sockets;
/**
* @returns the input if it is an HttpHandler of any class,
* or instantiates a new instance of this handler.
*/
static create(instanceOrOptions?: WebSocketFetchHandler | WebSocketFetchHandlerOptions | Provider<WebSocketFetchHandlerOptions | void>, httpHandler?: RequestHandler<any, any>): WebSocketFetchHandler;
constructor(options?: WebSocketFetchHandlerOptions | Provider<WebSocketFetchHandlerOptions>, httpHandler?: RequestHandler<any, any>);
/**
* Destroys the WebSocketHandler.
* Closes all sockets from the socket pool.
*/
destroy(): void;
handle(request: HttpRequest): Promise<{
response: HttpResponse;
}>;
updateHttpClientConfig(key: keyof WebSocketFetchHandlerOptions, value: WebSocketFetchHandlerOptions[typeof key]): void;
httpHandlerConfigs(): WebSocketFetchHandlerOptions;
/**
* Removes all closing/closed sockets from the socket pool for URL.
*/
private removeNotUsableSockets;
private waitForReady;
private connect;
}
import type { EventStreamCodec } from "@smithy/eventstream-codec";
import type { MessageSigner, Provider } from "@smithy/types";
/**
* A transform stream that signs the eventstream.
*
* Implementation replicated from @aws-sdk/eventstream-handler-node::EventSigningStream
* but modified to be compatible with web stream interface.
*
* @internal
*/
export declare class EventSigningTransformStream extends TransformStream<Uint8Array, Uint8Array> {
/**
* @override
*/
readable: ReadableStream<Uint8Array>;
/**
* @override
*/
writable: WritableStream<Uint8Array>;
constructor(initialSignature: string, messageSigner: MessageSigner, eventStreamCodec: EventStreamCodec, systemClockOffsetProvider: Provider<number>);
}
import type { Decoder, Encoder, EventStreamPayloadHandler as IEventStreamPayloadHandler, FinalizeHandler, FinalizeHandlerArguments, FinalizeHandlerOutput, HandlerExecutionContext, MessageSigner, MetadataBearer, Provider } from "@smithy/types";
/**
* @internal
*/
export interface EventStreamPayloadHandlerOptions {
messageSigner: Provider<MessageSigner>;
utf8Encoder: Encoder;
utf8Decoder: Decoder;
systemClockOffset?: number;
}
/**
* @internal
*/
export declare class EventStreamPayloadHandler implements IEventStreamPayloadHandler {
private readonly messageSigner;
private readonly eventStreamCodec;
private readonly systemClockOffsetProvider;
constructor(options: EventStreamPayloadHandlerOptions);
handle<T extends MetadataBearer>(next: FinalizeHandler<any, T>, args: FinalizeHandlerArguments<any>, context?: HandlerExecutionContext): Promise<FinalizeHandlerOutput<T>>;
}
import type { EventStreamPayloadHandlerProvider } from "@smithy/types";
/**
* @internal
*/
export declare const eventStreamPayloadHandlerProvider: EventStreamPayloadHandlerProvider;
+248
-210
'use strict';
var eventstreamCodec = require('@smithy/eventstream-codec');
var utilHexEncoding = require('@smithy/util-hex-encoding');
var protocolHttp = require('@smithy/protocol-http');
var utilFormatUrl = require('@aws-sdk/util-format-url');
var eventstreamSerdeBrowser = require('@smithy/eventstream-serde-browser');
var fetchHttpHandler = require('@smithy/fetch-http-handler');
var protocolHttp = require('@smithy/protocol-http');
var utilBase64 = require('@smithy/util-base64');
var eventstreamCodec = require('@smithy/eventstream-codec');
var utilHexEncoding = require('@smithy/util-hex-encoding');
const getEventSigningTransformStream = (initialSignature, messageSigner, eventStreamCodec, systemClockOffsetProvider) => {
let priorSignature = initialSignature;
const transformer = {
start() { },
async transform(chunk, controller) {
try {
const now = new Date(Date.now() + (await systemClockOffsetProvider()));
const dateHeader = {
":date": { type: "timestamp", value: now },
};
const signedMessage = await messageSigner.sign({
message: {
body: chunk,
headers: dateHeader,
},
priorSignature: priorSignature,
}, {
signingDate: now,
});
priorSignature = signedMessage.signature;
const serializedSigned = eventStreamCodec.encode({
headers: {
...dateHeader,
":chunk-signature": {
type: "binary",
value: utilHexEncoding.fromHex(signedMessage.signature),
},
},
body: chunk,
});
controller.enqueue(serializedSigned);
}
catch (error) {
controller.error(error);
}
},
};
return new TransformStream({ ...transformer });
};
class EventStreamPayloadHandler {
messageSigner;
eventStreamCodec;
systemClockOffsetProvider;
constructor(options) {
this.messageSigner = options.messageSigner;
this.eventStreamCodec = new eventstreamCodec.EventStreamCodec(options.utf8Encoder, options.utf8Decoder);
this.systemClockOffsetProvider = async () => options.systemClockOffset ?? 0;
}
async handle(next, args, context = {}) {
const request = args.request;
const { body: payload, headers, query } = request;
if (!(payload instanceof ReadableStream)) {
throw new Error("Eventstream payload must be a ReadableStream.");
}
const placeHolderStream = new TransformStream();
request.body = placeHolderStream.readable;
const match = (headers?.authorization ?? "").match(/Signature=(\w+)$/);
const priorSignature = (match ?? [])[1] ?? (query && query["X-Amz-Signature"]) ?? "";
const signingStream = getEventSigningTransformStream(priorSignature, await this.messageSigner(), this.eventStreamCodec, this.systemClockOffsetProvider);
payload.pipeThrough(signingStream).pipeThrough(placeHolderStream);
let result;
try {
result = await next(args);
}
catch (e) {
const p = payload.cancel?.();
if (p instanceof Promise) {
p.catch(() => { });
}
throw e;
}
return result;
}
}
const eventStreamPayloadHandlerProvider = (options) => new EventStreamPayloadHandler(options);
const injectSessionIdMiddleware = () => (next) => async (args) => {
const requestParams = {
...args.input,
};
const response = await next(args);
const output = response.output;
if (requestParams.SessionId && output.SessionId == null) {
output.SessionId = requestParams.SessionId;
}
return response;
};
const injectSessionIdMiddlewareOptions = {
step: "initialize",
name: "injectSessionIdMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM"],
override: true,
};
const websocketEndpointMiddleware = (config, options) => (next) => (args) => {
const { request } = args;
if (protocolHttp.HttpRequest.isInstance(request) &&
config.requestHandler.metadata?.handlerProtocol?.toLowerCase().includes("websocket")) {
request.protocol = "wss:";
request.method = "GET";
request.path = `${request.path}-websocket`;
const { headers } = request;
delete headers["content-type"];
delete headers["x-amz-content-sha256"];
for (const name of Object.keys(headers)) {
if (name.indexOf(options.headerPrefix) === 0) {
const chunkedName = name.replace(options.headerPrefix, "");
request.query[chunkedName] = headers[name];
}
}
if (headers["x-amz-user-agent"]) {
request.query["user-agent"] = headers["x-amz-user-agent"];
}
request.headers = { host: headers.host ?? request.hostname };
}
return next(args);
};
const websocketEndpointMiddlewareOptions = {
name: "websocketEndpointMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM"],
relation: "after",
toMiddleware: "eventStreamHeaderMiddleware",
override: true,
};
const getWebSocketPlugin = (config, options) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(websocketEndpointMiddleware(config, options), websocketEndpointMiddlewareOptions);
clientStack.add(injectSessionIdMiddleware(), injectSessionIdMiddlewareOptions);
},
});
const isWebSocketRequest = (request) => request.protocol === "ws:" || request.protocol === "wss:";
class WebsocketSignatureV4 {
signer;
constructor(options) {
this.signer = options.signer;
}
presign(originalRequest, options = {}) {
return this.signer.presign(originalRequest, options);
}
async sign(toSign, options) {
if (protocolHttp.HttpRequest.isInstance(toSign) && isWebSocketRequest(toSign)) {
const signedRequest = await this.signer.presign({ ...toSign, body: "" }, {
...options,
expiresIn: 60,
unsignableHeaders: new Set(Object.keys(toSign.headers).filter((header) => header !== "host")),
});
return {
...signedRequest,
body: toSign.body,
};
}
else {
return this.signer.sign(toSign, options);
}
}
}
const resolveWebSocketConfig = (input) => {
const { signer } = input;
return Object.assign(input, {
signer: async (authScheme) => {
const signerObj = await signer(authScheme);
if (validateSigner(signerObj)) {
return new WebsocketSignatureV4({ signer: signerObj });
}
throw new Error("Expected WebsocketSignatureV4 signer, please check the client constructor.");
},
});
};
const validateSigner = (signer) => !!signer;
const DEFAULT_WS_CONNECTION_TIMEOUT_MS = 2000;
const DEFAULT_WS_CONNECTION_TIMEOUT_MS = 3000;
class WebSocketFetchHandler {

@@ -191,3 +18,3 @@ metadata = {

};
config;
config = {};
configPromise;

@@ -204,9 +31,16 @@ httpHandler;

this.httpHandler = httpHandler;
const setConfig = (opts) => {
this.config = {
...(opts ?? {}),
};
return this.config;
};
if (typeof options === "function") {
this.config = {};
this.configPromise = options().then((opts) => (this.config = opts ?? {}));
this.configPromise = options().then((opts) => {
return setConfig(opts);
});
}
else {
this.config = options ?? {};
this.configPromise = Promise.resolve(this.config);
this.configPromise = Promise.resolve(setConfig(options));
}

@@ -223,6 +57,10 @@ }

async handle(request) {
this.config = await this.configPromise;
const { logger } = this.config;
if (!isWebSocketRequest(request)) {
logger?.debug?.(`@aws-sdk - ws fetching ${request.protocol}${request.hostname}${request.path}`);
return this.httpHandler.handle(request);
}
const url = utilFormatUrl.formatUrl(request);
logger?.debug?.(`@aws-sdk - ws connecting ${url.split("?")[0]}`);
const socket = new WebSocket(url);

@@ -234,3 +72,2 @@ if (!this.sockets[url]) {

socket.binaryType = "arraybuffer";
this.config = await this.configPromise;
const { connectionTimeout = DEFAULT_WS_CONNECTION_TIMEOUT_MS } = this.config;

@@ -268,2 +105,3 @@ await this.waitForReady(socket, connectionTimeout);

httpStatusCode: 500,
websocketSynthetic500Error: true,
},

@@ -279,37 +117,56 @@ });

connect(socket, data) {
let streamError = undefined;
let socketErrorOccurred = false;
let reject = () => { };
let resolve = () => { };
const messageQueue = [];
let pendingResolve = null;
let pendingReject = null;
const push = (item) => {
if (pendingResolve) {
if (item.error) {
pendingReject(item.error);
}
else {
pendingResolve({ done: item.done, value: item.value });
}
pendingResolve = null;
pendingReject = null;
}
else {
messageQueue.push(item);
}
};
socket.onmessage = (event) => {
resolve({
done: false,
value: new Uint8Array(event.data),
});
const { data } = event;
if (typeof data === "string") {
push({
done: false,
value: utilBase64.fromBase64(data),
});
}
else {
push({
done: false,
value: new Uint8Array(data),
});
}
};
socket.onerror = (error) => {
socketErrorOccurred = true;
socket.onerror = (event) => {
socket.close();
reject(error);
push({ done: true, error: event });
};
socket.onclose = () => {
this.removeNotUsableSockets(socket.url);
if (socketErrorOccurred)
return;
if (streamError) {
reject(streamError);
}
else {
resolve({
done: true,
value: undefined,
});
}
push({ done: true });
};
const outputStream = {
[Symbol.asyncIterator]: () => ({
next: () => {
return new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
async next() {
if (messageQueue.length > 0) {
const item = messageQueue.shift();
if (item.error) {
throw item.error;
}
return { done: item.done, value: item.value };
}
return new Promise((resolve, reject) => {
pendingResolve = resolve;
pendingReject = reject;
});

@@ -331,3 +188,6 @@ },

catch (err) {
streamError = err;
push({
done: true,
error: err,
});
}

@@ -358,2 +218,180 @@ finally {

const websocketEndpointMiddleware = (config, options) => (next) => (args) => {
const { request } = args;
if (protocolHttp.HttpRequest.isInstance(request) &&
config.requestHandler.metadata?.handlerProtocol?.toLowerCase().includes("websocket")) {
request.protocol = "wss:";
request.method = "GET";
request.path = `${request.path}-websocket`;
const { headers } = request;
delete headers["content-type"];
delete headers["x-amz-content-sha256"];
for (const name of Object.keys(headers)) {
if (name.indexOf(options.headerPrefix) === 0) {
const chunkedName = name.replace(options.headerPrefix, "");
request.query[chunkedName] = headers[name];
}
}
if (headers["x-amz-user-agent"]) {
request.query["user-agent"] = headers["x-amz-user-agent"];
}
request.headers = { host: headers.host ?? request.hostname };
}
return next(args);
};
const websocketEndpointMiddlewareOptions = {
name: "websocketEndpointMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM"],
relation: "after",
toMiddleware: "eventStreamHeaderMiddleware",
override: true,
};
const injectSessionIdMiddleware = () => (next) => async (args) => {
const requestParams = {
...args.input,
};
const response = await next(args);
const output = response.output;
if (requestParams.SessionId && output.SessionId == null) {
output.SessionId = requestParams.SessionId;
}
return response;
};
const injectSessionIdMiddlewareOptions = {
step: "initialize",
name: "injectSessionIdMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM"],
override: true,
};
const getWebSocketPlugin = (config, options) => ({
applyToStack: (clientStack) => {
clientStack.addRelativeTo(websocketEndpointMiddleware(config, options), websocketEndpointMiddlewareOptions);
clientStack.add(injectSessionIdMiddleware(), injectSessionIdMiddlewareOptions);
},
});
class WebsocketSignatureV4 {
signer;
constructor(options) {
this.signer = options.signer;
}
presign(originalRequest, options = {}) {
return this.signer.presign(originalRequest, options);
}
async sign(toSign, options) {
if (protocolHttp.HttpRequest.isInstance(toSign) && isWebSocketRequest(toSign)) {
const signedRequest = await this.signer.presign({ ...toSign, body: "" }, {
...options,
expiresIn: 60,
unsignableHeaders: new Set(Object.keys(toSign.headers).filter((header) => header !== "host")),
});
return {
...signedRequest,
body: toSign.body,
};
}
else {
return this.signer.sign(toSign, options);
}
}
signMessage(message, args) {
return this.signer.signMessage(message, args);
}
}
const resolveWebSocketConfig = (input) => {
const { signer } = input;
return Object.assign(input, {
signer: async (authScheme) => {
const signerObj = await signer(authScheme);
if (validateSigner(signerObj)) {
return new WebsocketSignatureV4({ signer: signerObj });
}
throw new Error("Expected WebsocketSignatureV4 signer, please check the client constructor.");
},
});
};
const validateSigner = (signer) => !!signer;
class EventSigningTransformStream extends TransformStream {
constructor(initialSignature, messageSigner, eventStreamCodec, systemClockOffsetProvider) {
let priorSignature = initialSignature;
super({
start() { },
async transform(chunk, controller) {
try {
const now = new Date(Date.now() + (await systemClockOffsetProvider()));
const dateHeader = {
":date": { type: "timestamp", value: now },
};
const signedMessage = await messageSigner.sign({
message: {
body: chunk,
headers: dateHeader,
},
priorSignature: priorSignature,
}, {
signingDate: now,
});
priorSignature = signedMessage.signature;
const serializedSigned = eventStreamCodec.encode({
headers: {
...dateHeader,
":chunk-signature": {
type: "binary",
value: utilHexEncoding.fromHex(signedMessage.signature),
},
},
body: chunk,
});
controller.enqueue(serializedSigned);
}
catch (error) {
controller.error(error);
}
},
});
}
}
class EventStreamPayloadHandler {
messageSigner;
eventStreamCodec;
systemClockOffsetProvider;
constructor(options) {
this.messageSigner = options.messageSigner;
this.eventStreamCodec = new eventstreamCodec.EventStreamCodec(options.utf8Encoder, options.utf8Decoder);
this.systemClockOffsetProvider = async () => options.systemClockOffset ?? 0;
}
async handle(next, args, context = {}) {
const request = args.request;
const { body: payload, headers, query } = request;
if (!(payload instanceof ReadableStream)) {
throw new Error("Eventstream payload must be a ReadableStream.");
}
const placeHolderStream = new TransformStream();
request.body = placeHolderStream.readable;
const match = (headers?.authorization ?? "").match(/Signature=(\w+)$/);
const priorSignature = (match ?? [])[1] ?? (query && query["X-Amz-Signature"]) ?? "";
const signingStream = new EventSigningTransformStream(priorSignature, await this.messageSigner(), this.eventStreamCodec, this.systemClockOffsetProvider);
payload.pipeThrough(signingStream).pipeThrough(placeHolderStream);
let result;
try {
result = await next(args);
}
catch (e) {
const p = payload.cancel?.();
if (p instanceof Promise) {
p.catch(() => { });
}
throw e;
}
return result;
}
}
const eventStreamPayloadHandlerProvider = (options) => new EventStreamPayloadHandler(options);
exports.WebSocketFetchHandler = WebSocketFetchHandler;

@@ -360,0 +398,0 @@ exports.eventStreamPayloadHandlerProvider = eventStreamPayloadHandlerProvider;

@@ -1,3 +0,3 @@

import { injectSessionIdMiddleware, injectSessionIdMiddlewareOptions } from "./middleware-session-id";
import { websocketEndpointMiddleware, websocketEndpointMiddlewareOptions } from "./middleware-websocket-endpoint";
import { websocketEndpointMiddleware, websocketEndpointMiddlewareOptions, } from "./middlewares/websocketEndpointMiddleware";
import { injectSessionIdMiddleware, injectSessionIdMiddlewareOptions, } from "./middlewares/websocketInjectSessionIdMiddleware";
export const getWebSocketPlugin = (config, options) => ({

@@ -4,0 +4,0 @@ applyToStack: (clientStack) => {

@@ -1,4 +0,4 @@

export * from "./eventstream-payload-handler-provider";
export * from "./WebSocketFetchHandler";
export * from "./getWebSocketPlugin";
export * from "./websocket-configuration";
export * from "./websocket-fetch-handler";
export * from "./resolveWebSocketConfig";
export * from "./ws-eventstream/eventStreamPayloadHandlerProvider";

@@ -27,2 +27,5 @@ import { HttpRequest } from "@smithy/protocol-http";

}
signMessage(message, args) {
return this.signer.signMessage(message, args);
}
}

@@ -1,2 +0,2 @@

import { Pluggable, RequestHandler } from "@smithy/types";
import type { Pluggable, RequestHandler } from "@smithy/types";
interface WebSocketResolvedConfig {

@@ -3,0 +3,0 @@ requestHandler: RequestHandler<any, any>;

@@ -1,4 +0,4 @@

export * from "./eventstream-payload-handler-provider";
export * from "./WebSocketFetchHandler";
export * from "./getWebSocketPlugin";
export * from "./websocket-configuration";
export * from "./websocket-fetch-handler";
export * from "./resolveWebSocketConfig";
export * from "./ws-eventstream/eventStreamPayloadHandlerProvider";

@@ -1,4 +0,4 @@

export * from "./eventstream-payload-handler-provider";
export * from "./WebSocketFetchHandler";
export * from "./getWebSocketPlugin";
export * from "./websocket-configuration";
export * from "./websocket-fetch-handler";
export * from "./resolveWebSocketConfig";
export * from "./ws-eventstream/eventStreamPayloadHandlerProvider";
import { SignatureV4 as BaseSignatureV4 } from "@smithy/signature-v4";
import {
EventSigner,
EventSigningArguments,
FormattedEvent,
HttpRequest as IHttpRequest,
MessageSigner,
RequestPresigner,

@@ -8,5 +12,14 @@ RequestPresigningArguments,

RequestSigningArguments,
SignableMessage,
SignedMessage,
SigningArguments,
StringSigner,
} from "@smithy/types";
export declare class WebsocketSignatureV4
implements RequestSigner, RequestPresigner
implements
RequestPresigner,
RequestSigner,
StringSigner,
EventSigner,
MessageSigner
{

@@ -19,6 +32,16 @@ private readonly signer;

): Promise<IHttpRequest>;
sign(stringToSign: string, options?: SigningArguments): Promise<string>;
sign(event: FormattedEvent, options: EventSigningArguments): Promise<string>;
sign(
toSign: IHttpRequest,
event: SignableMessage,
options: SigningArguments
): Promise<SignedMessage>;
sign(
requestToSign: IHttpRequest,
options?: RequestSigningArguments
): Promise<IHttpRequest>;
signMessage(
message: SignableMessage,
args: SigningArguments
): Promise<SignedMessage>;
}

@@ -1,2 +0,2 @@

import { HttpRequest } from "@smithy/types";
import type { HttpRequest } from "@smithy/types";
export declare const isWebSocketRequest: (request: HttpRequest) => boolean;

@@ -1,4 +0,10 @@

import { SignatureV4 as BaseSignatureV4 } from "@smithy/signature-v4";
import { HttpRequest as IHttpRequest, RequestPresigner, RequestPresigningArguments, RequestSigner, RequestSigningArguments } from "@smithy/types";
export declare class WebsocketSignatureV4 implements RequestSigner, RequestPresigner {
import type { SignatureV4 as BaseSignatureV4 } from "@smithy/signature-v4";
import type { EventSigner, EventSigningArguments, FormattedEvent, HttpRequest as IHttpRequest, MessageSigner, RequestPresigner, RequestPresigningArguments, RequestSigner, RequestSigningArguments, SignableMessage, SignedMessage, SigningArguments, StringSigner } from "@smithy/types";
/**
* Because this signer defers to sigv4, it implements all signing interfaces that
* the sigv4 signer does, including message signing.
*
* @internal
*/
export declare class WebsocketSignatureV4 implements RequestPresigner, RequestSigner, StringSigner, EventSigner, MessageSigner {
private readonly signer;

@@ -9,3 +15,7 @@ constructor(options: {

presign(originalRequest: IHttpRequest, options?: RequestPresigningArguments): Promise<IHttpRequest>;
sign(toSign: IHttpRequest, options?: RequestSigningArguments): Promise<IHttpRequest>;
sign(stringToSign: string, options?: SigningArguments): Promise<string>;
sign(event: FormattedEvent, options: EventSigningArguments): Promise<string>;
sign(event: SignableMessage, options: SigningArguments): Promise<SignedMessage>;
sign(requestToSign: IHttpRequest, options?: RequestSigningArguments): Promise<IHttpRequest>;
signMessage(message: SignableMessage, args: SigningArguments): Promise<SignedMessage>;
}
{
"name": "@aws-sdk/middleware-websocket",
"version": "3.972.4",
"version": "3.972.5",
"main": "./dist-cjs/index.js",

@@ -35,3 +35,5 @@ "module": "./dist-es/index.js",

"@smithy/types": "^4.12.0",
"@smithy/util-base64": "^4.3.0",
"@smithy/util-hex-encoding": "^4.2.0",
"@smithy/util-utf8": "^4.2.0",
"tslib": "^2.6.2"

@@ -38,0 +40,0 @@ },

import { EventStreamPayloadHandler } from "./EventStreamPayloadHandler";
export const eventStreamPayloadHandlerProvider = (options) => new EventStreamPayloadHandler(options);
import { EventStreamCodec } from "@smithy/eventstream-codec";
import { getEventSigningTransformStream } from "./get-event-signing-stream";
export class EventStreamPayloadHandler {
messageSigner;
eventStreamCodec;
systemClockOffsetProvider;
constructor(options) {
this.messageSigner = options.messageSigner;
this.eventStreamCodec = new EventStreamCodec(options.utf8Encoder, options.utf8Decoder);
this.systemClockOffsetProvider = async () => options.systemClockOffset ?? 0;
}
async handle(next, args, context = {}) {
const request = args.request;
const { body: payload, headers, query } = request;
if (!(payload instanceof ReadableStream)) {
throw new Error("Eventstream payload must be a ReadableStream.");
}
const placeHolderStream = new TransformStream();
request.body = placeHolderStream.readable;
const match = (headers?.authorization ?? "").match(/Signature=(\w+)$/);
const priorSignature = (match ?? [])[1] ?? (query && query["X-Amz-Signature"]) ?? "";
const signingStream = getEventSigningTransformStream(priorSignature, await this.messageSigner(), this.eventStreamCodec, this.systemClockOffsetProvider);
payload.pipeThrough(signingStream).pipeThrough(placeHolderStream);
let result;
try {
result = await next(args);
}
catch (e) {
const p = payload.cancel?.();
if (p instanceof Promise) {
p.catch(() => { });
}
throw e;
}
return result;
}
}
import { fromHex } from "@smithy/util-hex-encoding";
export const getEventSigningTransformStream = (initialSignature, messageSigner, eventStreamCodec, systemClockOffsetProvider) => {
let priorSignature = initialSignature;
const transformer = {
start() { },
async transform(chunk, controller) {
try {
const now = new Date(Date.now() + (await systemClockOffsetProvider()));
const dateHeader = {
":date": { type: "timestamp", value: now },
};
const signedMessage = await messageSigner.sign({
message: {
body: chunk,
headers: dateHeader,
},
priorSignature: priorSignature,
}, {
signingDate: now,
});
priorSignature = signedMessage.signature;
const serializedSigned = eventStreamCodec.encode({
headers: {
...dateHeader,
":chunk-signature": {
type: "binary",
value: fromHex(signedMessage.signature),
},
},
body: chunk,
});
controller.enqueue(serializedSigned);
}
catch (error) {
controller.error(error);
}
},
};
return new TransformStream({ ...transformer });
};
export const injectSessionIdMiddleware = () => (next) => async (args) => {
const requestParams = {
...args.input,
};
const response = await next(args);
const output = response.output;
if (requestParams.SessionId && output.SessionId == null) {
output.SessionId = requestParams.SessionId;
}
return response;
};
export const injectSessionIdMiddlewareOptions = {
step: "initialize",
name: "injectSessionIdMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM"],
override: true,
};
import { HttpRequest } from "@smithy/protocol-http";
export const websocketEndpointMiddleware = (config, options) => (next) => (args) => {
const { request } = args;
if (HttpRequest.isInstance(request) &&
config.requestHandler.metadata?.handlerProtocol?.toLowerCase().includes("websocket")) {
request.protocol = "wss:";
request.method = "GET";
request.path = `${request.path}-websocket`;
const { headers } = request;
delete headers["content-type"];
delete headers["x-amz-content-sha256"];
for (const name of Object.keys(headers)) {
if (name.indexOf(options.headerPrefix) === 0) {
const chunkedName = name.replace(options.headerPrefix, "");
request.query[chunkedName] = headers[name];
}
}
if (headers["x-amz-user-agent"]) {
request.query["user-agent"] = headers["x-amz-user-agent"];
}
request.headers = { host: headers.host ?? request.hostname };
}
return next(args);
};
export const websocketEndpointMiddlewareOptions = {
name: "websocketEndpointMiddleware",
tags: ["WEBSOCKET", "EVENT_STREAM"],
relation: "after",
toMiddleware: "eventStreamHeaderMiddleware",
override: true,
};
import { WebsocketSignatureV4 } from "./WebsocketSignatureV4";
export const resolveWebSocketConfig = (input) => {
const { signer } = input;
return Object.assign(input, {
signer: async (authScheme) => {
const signerObj = await signer(authScheme);
if (validateSigner(signerObj)) {
return new WebsocketSignatureV4({ signer: signerObj });
}
throw new Error("Expected WebsocketSignatureV4 signer, please check the client constructor.");
},
});
};
const validateSigner = (signer) => !!signer;
import { formatUrl } from "@aws-sdk/util-format-url";
import { iterableToReadableStream, readableStreamtoIterable } from "@smithy/eventstream-serde-browser";
import { FetchHttpHandler } from "@smithy/fetch-http-handler";
import { HttpResponse } from "@smithy/protocol-http";
import { isWebSocketRequest } from "./utils";
const DEFAULT_WS_CONNECTION_TIMEOUT_MS = 2000;
export class WebSocketFetchHandler {
metadata = {
handlerProtocol: "websocket/h1.1",
};
config;
configPromise;
httpHandler;
sockets = {};
static create(instanceOrOptions, httpHandler = new FetchHttpHandler()) {
if (typeof instanceOrOptions?.handle === "function") {
return instanceOrOptions;
}
return new WebSocketFetchHandler(instanceOrOptions, httpHandler);
}
constructor(options, httpHandler = new FetchHttpHandler()) {
this.httpHandler = httpHandler;
if (typeof options === "function") {
this.config = {};
this.configPromise = options().then((opts) => (this.config = opts ?? {}));
}
else {
this.config = options ?? {};
this.configPromise = Promise.resolve(this.config);
}
}
destroy() {
for (const [key, sockets] of Object.entries(this.sockets)) {
for (const socket of sockets) {
socket.close(1000, `Socket closed through destroy() call`);
}
delete this.sockets[key];
}
}
async handle(request) {
if (!isWebSocketRequest(request)) {
return this.httpHandler.handle(request);
}
const url = formatUrl(request);
const socket = new WebSocket(url);
if (!this.sockets[url]) {
this.sockets[url] = [];
}
this.sockets[url].push(socket);
socket.binaryType = "arraybuffer";
this.config = await this.configPromise;
const { connectionTimeout = DEFAULT_WS_CONNECTION_TIMEOUT_MS } = this.config;
await this.waitForReady(socket, connectionTimeout);
const { body } = request;
const bodyStream = getIterator(body);
const asyncIterable = this.connect(socket, bodyStream);
const outputPayload = toReadableStream(asyncIterable);
return {
response: new HttpResponse({
statusCode: 200,
body: outputPayload,
}),
};
}
updateHttpClientConfig(key, value) {
this.configPromise = this.configPromise.then((config) => {
config[key] = value;
return config;
});
}
httpHandlerConfigs() {
return this.config ?? {};
}
removeNotUsableSockets(url) {
this.sockets[url] = (this.sockets[url] ?? []).filter((socket) => ![WebSocket.CLOSING, WebSocket.CLOSED].includes(socket.readyState));
}
waitForReady(socket, connectionTimeout) {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
this.removeNotUsableSockets(socket.url);
reject({
$metadata: {
httpStatusCode: 500,
},
});
}, connectionTimeout);
socket.onopen = () => {
clearTimeout(timeout);
resolve();
};
});
}
connect(socket, data) {
let streamError = undefined;
let socketErrorOccurred = false;
let reject = () => { };
let resolve = () => { };
socket.onmessage = (event) => {
resolve({
done: false,
value: new Uint8Array(event.data),
});
};
socket.onerror = (error) => {
socketErrorOccurred = true;
socket.close();
reject(error);
};
socket.onclose = () => {
this.removeNotUsableSockets(socket.url);
if (socketErrorOccurred)
return;
if (streamError) {
reject(streamError);
}
else {
resolve({
done: true,
value: undefined,
});
}
};
const outputStream = {
[Symbol.asyncIterator]: () => ({
next: () => {
return new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
},
}),
};
const send = async () => {
try {
for await (const chunk of data) {
if (socket.readyState >= WebSocket.CLOSING) {
break;
}
else {
socket.send(chunk);
}
}
}
catch (err) {
streamError = err;
}
finally {
socket.close(1000);
}
};
send();
return outputStream;
}
}
const getIterator = (stream) => {
if (stream[Symbol.asyncIterator]) {
return stream;
}
if (isReadableStream(stream)) {
return readableStreamtoIterable(stream);
}
return {
[Symbol.asyncIterator]: async function* () {
yield stream;
},
};
};
const toReadableStream = (asyncIterable) => typeof ReadableStream === "function" ? iterableToReadableStream(asyncIterable) : asyncIterable;
const isReadableStream = (payload) => typeof ReadableStream === "function" && payload instanceof ReadableStream;
import { EventStreamPayloadHandlerProvider } from "@smithy/types";
/**
* @internal
*/
export declare const eventStreamPayloadHandlerProvider: EventStreamPayloadHandlerProvider;
import { Decoder, Encoder, EventStreamPayloadHandler as IEventStreamPayloadHandler, FinalizeHandler, FinalizeHandlerArguments, FinalizeHandlerOutput, HandlerExecutionContext, MessageSigner, MetadataBearer, Provider } from "@smithy/types";
/**
* @internal
*/
export interface EventStreamPayloadHandlerOptions {
messageSigner: Provider<MessageSigner>;
utf8Encoder: Encoder;
utf8Decoder: Decoder;
systemClockOffset?: number;
}
/**
* A handler that control the eventstream payload flow:
* 1. Pause stream for initial request.
* 2. Close the stream if initial request fails.
* 3. Start piping payload when connection is established.
* 4. Sign the payload after payload stream starting to flow.
*
* @internal
*/
export declare class EventStreamPayloadHandler implements IEventStreamPayloadHandler {
private readonly messageSigner;
private readonly eventStreamCodec;
private readonly systemClockOffsetProvider;
constructor(options: EventStreamPayloadHandlerOptions);
handle<T extends MetadataBearer>(next: FinalizeHandler<any, T>, args: FinalizeHandlerArguments<any>, context?: HandlerExecutionContext): Promise<FinalizeHandlerOutput<T>>;
}
import { EventStreamCodec } from "@smithy/eventstream-codec";
import { MessageSigner, Provider } from "@smithy/types";
/**
* Get a transform stream that signs the eventstream
* Implementation replicated from @aws-sdk/eventstream-handler-node::EventSigningStream
* but modified to be compatible with WHATWG stream interface
*
* @internal
*/
export declare const getEventSigningTransformStream: (initialSignature: string, messageSigner: MessageSigner, eventStreamCodec: EventStreamCodec, systemClockOffsetProvider: Provider<number>) => TransformStream<Uint8Array, Uint8Array>;
import { InitializeHandlerOptions, InitializeMiddleware } from "@smithy/types";
/**
* Most WebSocket operations contains `SessionId` parameter in both input and
* output, with the same value. This middleware populates the `SessionId`
* parameter from request to the response. This is necessary because in
* WebSocket, the SDK cannot access any parameters other than the response
* stream. So we fake response parameter.
*/
export declare const injectSessionIdMiddleware: () => InitializeMiddleware<any, any>;
export declare const injectSessionIdMiddlewareOptions: InitializeHandlerOptions;
import { BuildMiddleware, RelativeMiddlewareOptions, RequestHandler } from "@smithy/types";
/**
* Middleware that modify the request to from http to WebSocket
* This middleware can only be applied to commands that supports bi-directional event streaming via WebSocket.
* Example of headerPrefix is "x-amz-rekognition-streaming-liveness-*" prefix exists for all rekognition streaming
* websocket API's headers. The common prefix are to be removed when moving them from headers to querystring.
*/
export declare const websocketEndpointMiddleware: (config: {
requestHandler: RequestHandler<any, any>;
}, options: {
headerPrefix: string;
}) => BuildMiddleware<any, any>;
export declare const websocketEndpointMiddlewareOptions: RelativeMiddlewareOptions;
import { EventStreamPayloadHandlerProvider } from "@smithy/types";
export declare const eventStreamPayloadHandlerProvider: EventStreamPayloadHandlerProvider;
import {
Decoder,
Encoder,
EventStreamPayloadHandler as IEventStreamPayloadHandler,
FinalizeHandler,
FinalizeHandlerArguments,
FinalizeHandlerOutput,
HandlerExecutionContext,
MessageSigner,
MetadataBearer,
Provider,
} from "@smithy/types";
export interface EventStreamPayloadHandlerOptions {
messageSigner: Provider<MessageSigner>;
utf8Encoder: Encoder;
utf8Decoder: Decoder;
systemClockOffset?: number;
}
export declare class EventStreamPayloadHandler
implements IEventStreamPayloadHandler
{
private readonly messageSigner;
private readonly eventStreamCodec;
private readonly systemClockOffsetProvider;
constructor(options: EventStreamPayloadHandlerOptions);
handle<T extends MetadataBearer>(
next: FinalizeHandler<any, T>,
args: FinalizeHandlerArguments<any>,
context?: HandlerExecutionContext
): Promise<FinalizeHandlerOutput<T>>;
}
import { EventStreamCodec } from "@smithy/eventstream-codec";
import { MessageSigner, Provider } from "@smithy/types";
export declare const getEventSigningTransformStream: (
initialSignature: string,
messageSigner: MessageSigner,
eventStreamCodec: EventStreamCodec,
systemClockOffsetProvider: Provider<number>
) => TransformStream<Uint8Array, Uint8Array>;
import { InitializeHandlerOptions, InitializeMiddleware } from "@smithy/types";
export declare const injectSessionIdMiddleware: () => InitializeMiddleware<
any,
any
>;
export declare const injectSessionIdMiddlewareOptions: InitializeHandlerOptions;
import {
BuildMiddleware,
RelativeMiddlewareOptions,
RequestHandler,
} from "@smithy/types";
export declare const websocketEndpointMiddleware: (
config: {
requestHandler: RequestHandler<any, any>;
},
options: {
headerPrefix: string;
}
) => BuildMiddleware<any, any>;
export declare const websocketEndpointMiddlewareOptions: RelativeMiddlewareOptions;
import { AuthScheme, RequestHandler, RequestSigner } from "@smithy/types";
export interface WebSocketInputConfig {}
interface PreviouslyResolved {
signer: (authScheme: AuthScheme) => Promise<RequestSigner>;
requestHandler: RequestHandler<any, any>;
}
export interface WebSocketResolvedConfig {
signer: (authScheme: AuthScheme) => Promise<RequestSigner>;
requestHandler: RequestHandler<any, any>;
}
export declare const resolveWebSocketConfig: <T>(
input: T & WebSocketInputConfig & PreviouslyResolved
) => T & WebSocketResolvedConfig;
export {};
import { HttpRequest, HttpResponse } from "@smithy/protocol-http";
import {
Provider,
RequestHandler,
RequestHandlerMetadata,
} from "@smithy/types";
export interface WebSocketFetchHandlerOptions {
connectionTimeout?: number;
}
export declare class WebSocketFetchHandler {
readonly metadata: RequestHandlerMetadata;
private config;
private configPromise;
private readonly httpHandler;
private readonly sockets;
static create(
instanceOrOptions?:
| WebSocketFetchHandler
| WebSocketFetchHandlerOptions
| Provider<WebSocketFetchHandlerOptions | void>,
httpHandler?: RequestHandler<any, any>
): WebSocketFetchHandler;
constructor(
options?:
| WebSocketFetchHandlerOptions
| Provider<WebSocketFetchHandlerOptions>,
httpHandler?: RequestHandler<any, any>
);
destroy(): void;
handle(request: HttpRequest): Promise<{
response: HttpResponse;
}>;
updateHttpClientConfig(
key: keyof WebSocketFetchHandlerOptions,
value: WebSocketFetchHandlerOptions[typeof key]
): void;
httpHandlerConfigs(): WebSocketFetchHandlerOptions;
private removeNotUsableSockets;
private waitForReady;
private connect;
}
import { AuthScheme, RequestHandler, RequestSigner } from "@smithy/types";
/**
* @public
*/
export interface WebSocketInputConfig {
}
interface PreviouslyResolved {
signer: (authScheme: AuthScheme) => Promise<RequestSigner>;
requestHandler: RequestHandler<any, any>;
}
export interface WebSocketResolvedConfig {
/**
* Resolved value of input config {@link AwsAuthInputConfig.signer}
*/
signer: (authScheme: AuthScheme) => Promise<RequestSigner>;
/**
* The HTTP handler to use. Fetch in browser and Https in Nodejs.
*/
requestHandler: RequestHandler<any, any>;
}
export declare const resolveWebSocketConfig: <T>(input: T & WebSocketInputConfig & PreviouslyResolved) => T & WebSocketResolvedConfig;
export {};
import { HttpRequest, HttpResponse } from "@smithy/protocol-http";
import { Provider, RequestHandler, RequestHandlerMetadata } from "@smithy/types";
export interface WebSocketFetchHandlerOptions {
/**
* The maximum time in milliseconds that the connection phase of a request
* may take before the connection attempt is abandoned.
*/
connectionTimeout?: number;
}
/**
* Base handler for websocket requests and HTTP request. By default, the request input and output
* body will be in a ReadableStream, because of interface consistency among middleware.
* If ReadableStream is not available, like in React-Native, the response body
* will be an async iterable.
*/
export declare class WebSocketFetchHandler {
readonly metadata: RequestHandlerMetadata;
private config;
private configPromise;
private readonly httpHandler;
private readonly sockets;
/**
* @returns the input if it is an HttpHandler of any class,
* or instantiates a new instance of this handler.
*/
static create(instanceOrOptions?: WebSocketFetchHandler | WebSocketFetchHandlerOptions | Provider<WebSocketFetchHandlerOptions | void>, httpHandler?: RequestHandler<any, any>): WebSocketFetchHandler;
constructor(options?: WebSocketFetchHandlerOptions | Provider<WebSocketFetchHandlerOptions>, httpHandler?: RequestHandler<any, any>);
/**
* Destroys the WebSocketHandler.
* Closes all sockets from the socket pool.
*/
destroy(): void;
handle(request: HttpRequest): Promise<{
response: HttpResponse;
}>;
updateHttpClientConfig(key: keyof WebSocketFetchHandlerOptions, value: WebSocketFetchHandlerOptions[typeof key]): void;
httpHandlerConfigs(): WebSocketFetchHandlerOptions;
/**
* Removes all closing/closed sockets from the socket pool for URL.
*/
private removeNotUsableSockets;
private waitForReady;
private connect;
}