@aws-sdk/xhr-http-handler
Advanced tools
Comparing version 3.489.0 to 3.495.0
@@ -1,4 +0,268 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const tslib_1 = require("tslib"); | ||
tslib_1.__exportStar(require("./xhr-http-handler"), exports); | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
XhrHttpHandler: () => XhrHttpHandler | ||
}); | ||
module.exports = __toCommonJS(src_exports); | ||
// src/xhr-http-handler.ts | ||
var import_protocol_http = require("@smithy/protocol-http"); | ||
var import_querystring_builder = require("@smithy/querystring-builder"); | ||
var import_events = require("events"); | ||
// src/request-timeout.ts | ||
var requestTimeout = /* @__PURE__ */ __name((timeoutInMs = 0) => new Promise((resolve, reject) => { | ||
if (timeoutInMs) { | ||
setTimeout(() => { | ||
const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`); | ||
timeoutError.name = "TimeoutError"; | ||
reject(timeoutError); | ||
}, timeoutInMs); | ||
} | ||
}), "requestTimeout"); | ||
// src/xhr-http-handler.ts | ||
var EVENTS = { | ||
get PROGRESS() { | ||
return "xhr.progress"; | ||
}, | ||
get UPLOAD_PROGRESS() { | ||
return "xhr.upload.progress"; | ||
}, | ||
get XHR_INSTANTIATED() { | ||
return "after.xhr.new"; | ||
}, | ||
get BEFORE_XHR_SEND() { | ||
return "before.xhr.send"; | ||
} | ||
}; | ||
var _XhrHttpHandler = class _XhrHttpHandler extends import_events.EventEmitter { | ||
constructor(options) { | ||
super(); | ||
if (typeof options === "function") { | ||
this.configProvider = options(); | ||
} else { | ||
this.config = options ?? {}; | ||
this.configProvider = Promise.resolve(this.config); | ||
} | ||
} | ||
/** | ||
* @returns the input if it is an HttpHandler of any class, | ||
* or instantiates a new instance of this handler. | ||
*/ | ||
static create(instanceOrOptions) { | ||
if (typeof (instanceOrOptions == null ? void 0 : instanceOrOptions.handle) === "function") { | ||
return instanceOrOptions; | ||
} | ||
return new _XhrHttpHandler(instanceOrOptions); | ||
} | ||
updateHttpClientConfig(key, value) { | ||
this.config = void 0; | ||
this.configProvider = this.configProvider.then((config) => { | ||
config[key] = value; | ||
return config; | ||
}); | ||
} | ||
httpHandlerConfigs() { | ||
return this.config ?? {}; | ||
} | ||
destroy() { | ||
} | ||
async handle(request, { abortSignal } = {}) { | ||
if (!this.config) { | ||
this.config = await this.configProvider; | ||
} | ||
const requestTimeoutInMs = Number(this.config.requestTimeout) | 0; | ||
if (abortSignal == null ? void 0 : abortSignal.aborted) { | ||
const abortError = new Error("Request aborted"); | ||
abortError.name = "AbortError"; | ||
throw abortError; | ||
} | ||
let path = request.path; | ||
if (request.query) { | ||
const queryString = (0, import_querystring_builder.buildQueryString)(request.query); | ||
if (queryString) { | ||
path += `?${queryString}`; | ||
} | ||
} | ||
const { port, method } = request; | ||
const url = `${request.protocol}//${request.hostname}${port ? `:${port}` : ""}${path}`; | ||
const body = method === "GET" || method === "HEAD" ? void 0 : request.body; | ||
const xhr = new XMLHttpRequest(); | ||
this.emit(EVENTS.XHR_INSTANTIATED, xhr); | ||
const raceOfPromises = [ | ||
new Promise((resolve, reject) => { | ||
let streamCursor = 0; | ||
let stream; | ||
let writer; | ||
xhr.upload.addEventListener("progress", (event) => { | ||
this.emit(_XhrHttpHandler.EVENTS.UPLOAD_PROGRESS, event, request); | ||
}); | ||
xhr.addEventListener("progress", (event) => { | ||
this.emit(_XhrHttpHandler.EVENTS.PROGRESS, event, request); | ||
}); | ||
xhr.addEventListener("error", (err) => { | ||
const error = new Error(_XhrHttpHandler.ERROR_IDENTIFIER + ": " + err); | ||
reject(error); | ||
}); | ||
xhr.addEventListener("timeout", () => { | ||
reject(new Error("XMLHttpRequest timed out.")); | ||
}); | ||
xhr.addEventListener("readystatechange", () => { | ||
const isArrayBuffer = xhr.responseType === "arraybuffer" && xhr.response; | ||
const isText = !isArrayBuffer && typeof xhr.responseText === "string"; | ||
if (isText && !stream) { | ||
({ stream, writer } = this.initializeTransformStream()); | ||
} | ||
switch (xhr.readyState) { | ||
case XMLHttpRequest.LOADING: | ||
if (isText) { | ||
writer.write(streamCursor > 0 ? xhr.responseText.slice(streamCursor) : xhr.responseText); | ||
streamCursor = xhr.responseText.length; | ||
} | ||
break; | ||
case XMLHttpRequest.DONE: | ||
const body2 = (() => { | ||
var _a; | ||
if (isArrayBuffer) { | ||
return new Blob([xhr.response]); | ||
} | ||
if (isText) { | ||
streamCursor !== xhr.responseText.length && ((_a = writer.write) == null ? void 0 : _a.call(writer, streamCursor > 0 ? xhr.responseText.slice(streamCursor) : xhr.responseText)); | ||
writer.releaseLock(); | ||
stream.writable.close(); | ||
return stream.readable; | ||
} | ||
reject(new Error(`Unexpected XHR response type ${xhr.responseType}. Expected string or arraybuffer.`)); | ||
})(); | ||
resolve({ | ||
response: new import_protocol_http.HttpResponse({ | ||
headers: this.responseHeaders(xhr.getAllResponseHeaders()), | ||
statusCode: xhr.status, | ||
body: body2 | ||
}) | ||
}); | ||
break; | ||
} | ||
}); | ||
xhr.open(method, url); | ||
for (const [header, value] of Object.entries(request.headers)) { | ||
if (!isForbiddenRequestHeader(header)) { | ||
xhr.setRequestHeader(header, value); | ||
} | ||
} | ||
this.emit(EVENTS.BEFORE_XHR_SEND, xhr); | ||
xhr.send(body); | ||
}), | ||
requestTimeout(requestTimeoutInMs) | ||
]; | ||
if (abortSignal) { | ||
raceOfPromises.push( | ||
new Promise((resolve, reject) => { | ||
abortSignal.onabort = () => { | ||
xhr.abort(); | ||
const abortError = new Error("Request aborted"); | ||
abortError.name = "AbortError"; | ||
reject(abortError); | ||
}; | ||
}) | ||
); | ||
} | ||
return Promise.race(raceOfPromises); | ||
} | ||
/** | ||
* Converts XHR response headers to a map. | ||
* @param xhrHeaders - string to be parsed. | ||
*/ | ||
responseHeaders(xhrHeaders) { | ||
if (!xhrHeaders) { | ||
return {}; | ||
} | ||
return xhrHeaders.split("\r\n").reduce((headerMap, line) => { | ||
const parts = line.split(": "); | ||
const header = parts.shift(); | ||
const value = parts.join(": "); | ||
headerMap[header] = value; | ||
return headerMap; | ||
}, {}); | ||
} | ||
/** | ||
* @returns a stream and its default writer to be used to map the xhr response text to a readable stream. | ||
*/ | ||
initializeTransformStream() { | ||
const textEncoder = new TextEncoder(); | ||
const stream = new TransformStream({ | ||
start() { | ||
}, | ||
async transform(chunk, controller) { | ||
controller.enqueue(textEncoder.encode(String(chunk))); | ||
}, | ||
flush() { | ||
} | ||
}); | ||
const writer = stream.writable.getWriter(); | ||
return { | ||
stream, | ||
writer | ||
}; | ||
} | ||
}; | ||
__name(_XhrHttpHandler, "XhrHttpHandler"); | ||
_XhrHttpHandler.EVENTS = EVENTS; | ||
_XhrHttpHandler.ERROR_IDENTIFIER = "XHR_HTTP_HANDLER_ERROR"; | ||
var XhrHttpHandler = _XhrHttpHandler; | ||
var isForbiddenRequestHeader = /* @__PURE__ */ __name((header) => { | ||
header = header.toLowerCase(); | ||
if (header.startsWith("proxy-")) { | ||
return true; | ||
} | ||
if (header.startsWith("sec-")) { | ||
return true; | ||
} | ||
return forbiddenHeaders.includes(header); | ||
}, "isForbiddenRequestHeader"); | ||
var forbiddenHeaders = [ | ||
"Accept-Charset", | ||
"Accept-Encoding", | ||
"Access-Control-Request-Headers", | ||
"Access-Control-Request-Method", | ||
"Connection", | ||
"Content-Length", | ||
"Cookie", | ||
"Date", | ||
"DNT", | ||
"Expect", | ||
"Feature-Policy", | ||
"Host", | ||
"Keep-Alive", | ||
"Origin", | ||
"Referer", | ||
"TE", | ||
"Trailer", | ||
"Transfer-Encoding", | ||
"Upgrade", | ||
"Via" | ||
].map((_) => _.toLowerCase()); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
XhrHttpHandler | ||
}); |
@@ -1,13 +0,1 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.requestTimeout = void 0; | ||
const requestTimeout = (timeoutInMs = 0) => new Promise((resolve, reject) => { | ||
if (timeoutInMs) { | ||
setTimeout(() => { | ||
const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`); | ||
timeoutError.name = "TimeoutError"; | ||
reject(timeoutError); | ||
}, timeoutInMs); | ||
} | ||
}); | ||
exports.requestTimeout = requestTimeout; | ||
module.exports = require("./index.js"); |
@@ -1,215 +0,1 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.XhrHttpHandler = void 0; | ||
const protocol_http_1 = require("@smithy/protocol-http"); | ||
const querystring_builder_1 = require("@smithy/querystring-builder"); | ||
const events_1 = require("events"); | ||
const request_timeout_1 = require("./request-timeout"); | ||
const EVENTS = { | ||
get PROGRESS() { | ||
return "xhr.progress"; | ||
}, | ||
get UPLOAD_PROGRESS() { | ||
return "xhr.upload.progress"; | ||
}, | ||
get XHR_INSTANTIATED() { | ||
return "after.xhr.new"; | ||
}, | ||
get BEFORE_XHR_SEND() { | ||
return "before.xhr.send"; | ||
}, | ||
}; | ||
class XhrHttpHandler extends events_1.EventEmitter { | ||
static create(instanceOrOptions) { | ||
if (typeof (instanceOrOptions === null || instanceOrOptions === void 0 ? void 0 : instanceOrOptions.handle) === "function") { | ||
return instanceOrOptions; | ||
} | ||
return new XhrHttpHandler(instanceOrOptions); | ||
} | ||
constructor(options) { | ||
super(); | ||
if (typeof options === "function") { | ||
this.configProvider = options(); | ||
} | ||
else { | ||
this.config = options !== null && options !== void 0 ? options : {}; | ||
this.configProvider = Promise.resolve(this.config); | ||
} | ||
} | ||
updateHttpClientConfig(key, value) { | ||
this.config = undefined; | ||
this.configProvider = this.configProvider.then((config) => { | ||
config[key] = value; | ||
return config; | ||
}); | ||
} | ||
httpHandlerConfigs() { | ||
var _a; | ||
return (_a = this.config) !== null && _a !== void 0 ? _a : {}; | ||
} | ||
destroy() { | ||
} | ||
async handle(request, { abortSignal } = {}) { | ||
if (!this.config) { | ||
this.config = await this.configProvider; | ||
} | ||
const requestTimeoutInMs = Number(this.config.requestTimeout) | 0; | ||
if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) { | ||
const abortError = new Error("Request aborted"); | ||
abortError.name = "AbortError"; | ||
throw abortError; | ||
} | ||
let path = request.path; | ||
if (request.query) { | ||
const queryString = (0, querystring_builder_1.buildQueryString)(request.query); | ||
if (queryString) { | ||
path += `?${queryString}`; | ||
} | ||
} | ||
const { port, method } = request; | ||
const url = `${request.protocol}//${request.hostname}${port ? `:${port}` : ""}${path}`; | ||
const body = method === "GET" || method === "HEAD" ? undefined : request.body; | ||
const xhr = new XMLHttpRequest(); | ||
this.emit(EVENTS.XHR_INSTANTIATED, xhr); | ||
const raceOfPromises = [ | ||
new Promise((resolve, reject) => { | ||
let streamCursor = 0; | ||
let stream; | ||
let writer; | ||
xhr.upload.addEventListener("progress", (event) => { | ||
this.emit(XhrHttpHandler.EVENTS.UPLOAD_PROGRESS, event, request); | ||
}); | ||
xhr.addEventListener("progress", (event) => { | ||
this.emit(XhrHttpHandler.EVENTS.PROGRESS, event, request); | ||
}); | ||
xhr.addEventListener("error", (err) => { | ||
const error = new Error(XhrHttpHandler.ERROR_IDENTIFIER + ": " + err); | ||
reject(error); | ||
}); | ||
xhr.addEventListener("timeout", () => { | ||
reject(new Error("XMLHttpRequest timed out.")); | ||
}); | ||
xhr.addEventListener("readystatechange", () => { | ||
const isArrayBuffer = xhr.responseType === "arraybuffer" && xhr.response; | ||
const isText = !isArrayBuffer && typeof xhr.responseText === "string"; | ||
if (isText && !stream) { | ||
({ stream, writer } = this.initializeTransformStream()); | ||
} | ||
switch (xhr.readyState) { | ||
case XMLHttpRequest.LOADING: | ||
if (isText) { | ||
writer.write(streamCursor > 0 ? xhr.responseText.slice(streamCursor) : xhr.responseText); | ||
streamCursor = xhr.responseText.length; | ||
} | ||
break; | ||
case XMLHttpRequest.DONE: | ||
const body = (() => { | ||
var _a; | ||
if (isArrayBuffer) { | ||
return new Blob([xhr.response]); | ||
} | ||
if (isText) { | ||
streamCursor !== xhr.responseText.length && | ||
((_a = writer.write) === null || _a === void 0 ? void 0 : _a.call(writer, streamCursor > 0 ? xhr.responseText.slice(streamCursor) : xhr.responseText)); | ||
writer.releaseLock(); | ||
stream.writable.close(); | ||
return stream.readable; | ||
} | ||
reject(new Error(`Unexpected XHR response type ${xhr.responseType}. Expected string or arraybuffer.`)); | ||
})(); | ||
resolve({ | ||
response: new protocol_http_1.HttpResponse({ | ||
headers: this.responseHeaders(xhr.getAllResponseHeaders()), | ||
statusCode: xhr.status, | ||
body, | ||
}), | ||
}); | ||
break; | ||
} | ||
}); | ||
xhr.open(method, url); | ||
for (const [header, value] of Object.entries(request.headers)) { | ||
if (!isForbiddenRequestHeader(header)) { | ||
xhr.setRequestHeader(header, value); | ||
} | ||
} | ||
this.emit(EVENTS.BEFORE_XHR_SEND, xhr); | ||
xhr.send(body); | ||
}), | ||
(0, request_timeout_1.requestTimeout)(requestTimeoutInMs), | ||
]; | ||
if (abortSignal) { | ||
raceOfPromises.push(new Promise((resolve, reject) => { | ||
abortSignal.onabort = () => { | ||
xhr.abort(); | ||
const abortError = new Error("Request aborted"); | ||
abortError.name = "AbortError"; | ||
reject(abortError); | ||
}; | ||
})); | ||
} | ||
return Promise.race(raceOfPromises); | ||
} | ||
responseHeaders(xhrHeaders) { | ||
if (!xhrHeaders) { | ||
return {}; | ||
} | ||
return xhrHeaders.split("\r\n").reduce((headerMap, line) => { | ||
const parts = line.split(": "); | ||
const header = parts.shift(); | ||
const value = parts.join(": "); | ||
headerMap[header] = value; | ||
return headerMap; | ||
}, {}); | ||
} | ||
initializeTransformStream() { | ||
const textEncoder = new TextEncoder(); | ||
const stream = new TransformStream({ | ||
start() { }, | ||
async transform(chunk, controller) { | ||
controller.enqueue(textEncoder.encode(String(chunk))); | ||
}, | ||
flush() { }, | ||
}); | ||
const writer = stream.writable.getWriter(); | ||
return { | ||
stream, | ||
writer, | ||
}; | ||
} | ||
} | ||
exports.XhrHttpHandler = XhrHttpHandler; | ||
XhrHttpHandler.EVENTS = EVENTS; | ||
XhrHttpHandler.ERROR_IDENTIFIER = "XHR_HTTP_HANDLER_ERROR"; | ||
const isForbiddenRequestHeader = (header) => { | ||
header = header.toLowerCase(); | ||
if (header.startsWith("proxy-")) { | ||
return true; | ||
} | ||
if (header.startsWith("sec-")) { | ||
return true; | ||
} | ||
return forbiddenHeaders.includes(header); | ||
}; | ||
const forbiddenHeaders = [ | ||
"Accept-Charset", | ||
"Accept-Encoding", | ||
"Access-Control-Request-Headers", | ||
"Access-Control-Request-Method", | ||
"Connection", | ||
"Content-Length", | ||
"Cookie", | ||
"Date", | ||
"DNT", | ||
"Expect", | ||
"Feature-Policy", | ||
"Host", | ||
"Keep-Alive", | ||
"Origin", | ||
"Referer", | ||
"TE", | ||
"Trailer", | ||
"Transfer-Encoding", | ||
"Upgrade", | ||
"Via", | ||
].map((_) => _.toLowerCase()); | ||
module.exports = require("./index.js"); |
{ | ||
"name": "@aws-sdk/xhr-http-handler", | ||
"version": "3.489.0", | ||
"version": "3.495.0", | ||
"description": "Provides a way to make requests using XMLHttpRequest", | ||
"scripts": { | ||
"build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'", | ||
"build:cjs": "tsc -p tsconfig.cjs.json", | ||
"build:cjs": "node ../../scripts/compilation/inline xhr-http-handler", | ||
"build:es": "tsc -p tsconfig.es.json", | ||
@@ -22,6 +22,6 @@ "build:include:deps": "lerna run --scope $npm_package_name --include-dependencies build", | ||
"dependencies": { | ||
"@aws-sdk/types": "3.489.0", | ||
"@smithy/protocol-http": "^3.0.12", | ||
"@smithy/querystring-builder": "^2.0.16", | ||
"@smithy/types": "^2.8.0", | ||
"@aws-sdk/types": "3.495.0", | ||
"@smithy/protocol-http": "^3.1.0", | ||
"@smithy/querystring-builder": "^2.1.0", | ||
"@smithy/types": "^2.9.0", | ||
"events": "3.3.0", | ||
@@ -31,3 +31,3 @@ "tslib": "^2.5.0" | ||
"devDependencies": { | ||
"@smithy/abort-controller": "^2.0.1", | ||
"@smithy/abort-controller": "^2.1.0", | ||
"@tsconfig/recommended": "1.0.1", | ||
@@ -34,0 +34,0 @@ "concurrently": "7.0.0", |
600
38581
+ Added@aws-sdk/types@3.495.0(transitive)
- Removed@aws-sdk/types@3.489.0(transitive)
Updated@aws-sdk/types@3.495.0
Updated@smithy/protocol-http@^3.1.0
Updated@smithy/types@^2.9.0