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

balena-request

Package Overview
Dependencies
Maintainers
1
Versions
177
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

balena-request - npm Package Compare versions

Comparing version 11.0.0-11-x-0b9fa20803d50fba3fa44bb8c914db76f9dfaaf3 to 11.0.0-11-x-2d5ad56a7b9dcdf90fee3758c2573e9fdfbf4700

109

build/progress.js

@@ -17,2 +17,11 @@ "use strict";

*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -78,57 +87,59 @@ exports.estimate = void 0;

// @ts-expect-error
return async function (options) {
if (requestAsync == null) {
requestAsync = utils.getRequestAsync();
}
options.gzip = false;
options.headers['Accept-Encoding'] = 'gzip, deflate';
let reader = null;
if (options.signal != null) {
options.signal.addEventListener('abort', function () {
// We need to react to Abort events at this level, because otherwise our
// reader locks the stream and lower-level cancellation causes error.
if (reader) {
reader.cancel().catch(function () {
// ignore
});
return reader.releaseLock();
return function (options) {
return __awaiter(this, void 0, void 0, function* () {
if (requestAsync == null) {
requestAsync = utils.getRequestAsync();
}
options.gzip = false;
options.headers['Accept-Encoding'] = 'gzip, deflate';
let reader = null;
if (options.signal != null) {
options.signal.addEventListener('abort', function () {
// We need to react to Abort events at this level, because otherwise our
// reader locks the stream and lower-level cancellation causes error.
if (reader) {
reader.cancel().catch(function () {
// ignore
});
return reader.releaseLock();
}
}, { once: true });
}
const response = yield requestAsync(options);
let responseStream;
const output = new stream.PassThrough();
// @ts-expect-error
output.response = response;
const responseLength = utils.getResponseLength(response);
const total = responseLength.uncompressed || responseLength.compressed;
if (response.body.getReader) {
// Convert browser (WHATWG) streams to Node streams
responseStream = webStreams.toNodeReadable(response.body);
reader = responseStream._reader;
}
else {
responseStream = response.body;
}
const progressStream = getProgressStream(total, (state) => output.emit('progress', state));
if (!isBrowser && utils.isResponseCompressed(response)) {
const gunzip = zlib.createGunzip();
// Uncompress after or before piping through progress
// depending on the response length available to us
if (responseLength.compressed != null &&
responseLength.uncompressed == null) {
responseStream.pipe(progressStream).pipe(gunzip).pipe(output);
}
}, { once: true });
}
const response = await requestAsync(options);
let responseStream;
const output = new stream.PassThrough();
// @ts-expect-error
output.response = response;
const responseLength = utils.getResponseLength(response);
const total = responseLength.uncompressed || responseLength.compressed;
if (response.body.getReader) {
// Convert browser (WHATWG) streams to Node streams
responseStream = webStreams.toNodeReadable(response.body);
reader = responseStream._reader;
}
else {
responseStream = response.body;
}
const progressStream = getProgressStream(total, (state) => output.emit('progress', state));
if (!isBrowser && utils.isResponseCompressed(response)) {
const gunzip = zlib.createGunzip();
// Uncompress after or before piping through progress
// depending on the response length available to us
if (responseLength.compressed != null &&
responseLength.uncompressed == null) {
responseStream.pipe(progressStream).pipe(gunzip).pipe(output);
else {
responseStream.pipe(gunzip).pipe(progressStream).pipe(output);
}
}
else {
responseStream.pipe(gunzip).pipe(progressStream).pipe(output);
responseStream.pipe(progressStream).pipe(output);
}
}
else {
responseStream.pipe(progressStream).pipe(output);
}
// Stream any request errors on downstream
responseStream.on('error', (e) => output.emit('error', e));
return output;
// Stream any request errors on downstream
responseStream.on('error', (e) => output.emit('error', e));
return output;
});
};
}
exports.estimate = estimate;

@@ -17,2 +17,11 @@ "use strict";

*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -45,47 +54,49 @@ /**

const exports = {};
const prepareOptions = async function (options) {
if (options == null) {
options = {};
}
options = Object.assign({
method: 'GET',
json: true,
strictSSL: true,
headers: {},
sendToken: true,
refreshToken: true,
retries,
}, options);
if (options.uri) {
options.url = options.uri;
delete options.uri;
}
if (urlLib.parse(options.url).protocol != null) {
delete options.baseUrl;
}
// Only refresh if we have balena-auth, we're going to use it to send a
// token, and we haven't opted out of refresh
if (auth != null && options.sendToken && options.refreshToken) {
const shouldRefreshKey = await utils.shouldRefreshKey(auth);
if (shouldRefreshKey) {
await exports.refreshToken(options);
const prepareOptions = function (options) {
return __awaiter(this, void 0, void 0, function* () {
if (options == null) {
options = {};
}
}
const authorizationHeader = options.sendToken
? await utils.getAuthorizationHeader(auth)
: undefined;
if (authorizationHeader != null) {
options.headers.Authorization = authorizationHeader;
}
if (typeof options.apiKey === 'string' && options.apiKey.length > 0) {
// Using `request` qs object results in dollar signs, or other
// special characters used to query our OData API, being escaped
// and thus leading to all sort of weird error.
// The workaround is to append the `apikey` query string manually
// to prevent affecting the rest of the query strings.
// See https://github.com/request/request/issues/2129
options.url += urlLib.parse(options.url).query != null ? '&' : '?';
options.url += `apikey=${options.apiKey}`;
}
return options;
options = Object.assign({
method: 'GET',
json: true,
strictSSL: true,
headers: {},
sendToken: true,
refreshToken: true,
retries,
}, options);
if (options.uri) {
options.url = options.uri;
delete options.uri;
}
if (urlLib.parse(options.url).protocol != null) {
delete options.baseUrl;
}
// Only refresh if we have balena-auth, we're going to use it to send a
// token, and we haven't opted out of refresh
if (auth != null && options.sendToken && options.refreshToken) {
const shouldRefreshKey = yield utils.shouldRefreshKey(auth);
if (shouldRefreshKey) {
yield exports.refreshToken(options);
}
}
const authorizationHeader = options.sendToken
? yield utils.getAuthorizationHeader(auth)
: undefined;
if (authorizationHeader != null) {
options.headers.Authorization = authorizationHeader;
}
if (typeof options.apiKey === 'string' && options.apiKey.length > 0) {
// Using `request` qs object results in dollar signs, or other
// special characters used to query our OData API, being escaped
// and thus leading to all sort of weird error.
// The workaround is to append the `apikey` query string manually
// to prevent affecting the rest of the query strings.
// See https://github.com/request/request/issues/2129
options.url += urlLib.parse(options.url).query != null ? '&' : '?';
options.url += `apikey=${options.apiKey}`;
}
return options;
});
};

@@ -96,15 +107,6 @@ const interceptRequestOptions = (requestOptions) => interceptRequestOrError(Promise.resolve(requestOptions));

const interceptResponseError = (responseError) => interceptResponseOrError(Promise.reject(responseError));
var interceptRequestOrError = async (initialPromise) => exports.interceptors.reduce(function (promise, { request, requestError }) {
if (request != null || requestError != null) {
return promise.then(request, requestError);
}
else {
return promise;
}
}, initialPromise);
var interceptResponseOrError = async function (initialPromise) {
interceptors = exports.interceptors.slice().reverse();
return interceptors.reduce(function (promise, { response, responseError }) {
if (response != null || responseError != null) {
return promise.then(response, responseError);
var interceptRequestOrError = (initialPromise) => __awaiter(this, void 0, void 0, function* () {
return exports.interceptors.reduce(function (promise, { request, requestError }) {
if (request != null || requestError != null) {
return promise.then(request, requestError);
}

@@ -115,2 +117,15 @@ else {

}, initialPromise);
});
var interceptResponseOrError = function (initialPromise) {
return __awaiter(this, void 0, void 0, function* () {
interceptors = exports.interceptors.slice().reverse();
return interceptors.reduce(function (promise, { response, responseError }) {
if (response != null || responseError != null) {
return promise.then(response, responseError);
}
else {
return promise;
}
}, initialPromise);
});
};

@@ -158,30 +173,32 @@ /**

*/
exports.send = async function (options) {
// Only set the default timeout when doing a normal HTTP
// request and not also when streaming since in the latter
// case we might cause unnecessary ESOCKETTIMEDOUT errors.
if (options.timeout == null) {
options.timeout = 59000;
}
return prepareOptions(options)
.then(interceptRequestOptions, interceptRequestError)
.then(async (opts) => {
let response;
try {
response = await requestAsync(opts);
exports.send = function (options) {
return __awaiter(this, void 0, void 0, function* () {
// Only set the default timeout when doing a normal HTTP
// request and not also when streaming since in the latter
// case we might cause unnecessary ESOCKETTIMEDOUT errors.
if (options.timeout == null) {
options.timeout = 59000;
}
catch (err) {
err.requestOptions = opts;
throw err;
}
const body = await utils.getBody(response, options.responseFormat);
response = { ...response, body };
if (utils.isErrorCode(response.statusCode)) {
const responseError = utils.getErrorMessageFromResponse(response);
debugRequest(options, response);
throw new errors.BalenaRequestError(responseError, response.statusCode, options);
}
return response;
})
.then(interceptResponse, interceptResponseError);
return prepareOptions(options)
.then(interceptRequestOptions, interceptRequestError)
.then((opts) => __awaiter(this, void 0, void 0, function* () {
let response;
try {
response = yield requestAsync(opts);
}
catch (err) {
err.requestOptions = opts;
throw err;
}
const body = yield utils.getBody(response, options.responseFormat);
response = Object.assign(Object.assign({}, response), { body });
if (utils.isErrorCode(response.statusCode)) {
const responseError = utils.getErrorMessageFromResponse(response);
debugRequest(options, response);
throw new errors.BalenaRequestError(responseError, response.statusCode, options);
}
return response;
}))
.then(interceptResponse, interceptResponseError);
});
};

@@ -230,4 +247,4 @@ /**

.then(interceptRequestOptions, interceptRequestError)
.then(async (opts) => {
const download = await (progress.estimate(requestStream, isBrowser)(opts));
.then((opts) => __awaiter(this, void 0, void 0, function* () {
const download = yield (progress.estimate(requestStream, isBrowser)(opts));
// @ts-expect-error

@@ -242,3 +259,3 @@ if (!utils.isErrorCode(download.response.statusCode)) {

// the body of the request as an error.
const data = await rindle.extract(download);
const data = yield rindle.extract(download);
const responseError = data || 'The request was unsuccessful';

@@ -251,3 +268,3 @@ // @ts-expect-error

download.response.statusCode);
})
}))
.then(interceptResponse, interceptResponseError);

@@ -319,28 +336,30 @@ };

*/
exports.refreshToken = async function ({ baseUrl }) {
// Only refresh if we have balena-auth
if (auth == null) {
throw new Error('Auth module not provided in initializer');
}
let response;
try {
response = await exports.send({
url: '/whoami',
baseUrl,
refreshToken: false,
});
}
catch (err) {
if (err.code === 'BalenaRequestError' && err.statusCode === 401) {
const expiredKey = await auth.getKey();
await auth.removeKey();
throw new errors.BalenaExpiredToken(expiredKey);
exports.refreshToken = function ({ baseUrl }) {
return __awaiter(this, void 0, void 0, function* () {
// Only refresh if we have balena-auth
if (auth == null) {
throw new Error('Auth module not provided in initializer');
}
throw err;
}
const refreshedKey = response.body;
await auth.setKey(refreshedKey);
return refreshedKey;
let response;
try {
response = yield exports.send({
url: '/whoami',
baseUrl,
refreshToken: false,
});
}
catch (err) {
if (err.code === 'BalenaRequestError' && err.statusCode === 401) {
const expiredKey = yield auth.getKey();
yield auth.removeKey();
throw new errors.BalenaExpiredToken(expiredKey);
}
throw err;
}
const refreshedKey = response.body;
yield auth.setKey(refreshedKey);
return refreshedKey;
});
};
return exports;
};

@@ -17,2 +17,11 @@ "use strict";

*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -47,14 +56,16 @@ exports.getRequestAsync = exports.getBody = exports.debugRequest = exports.getResponseLength = exports.isResponseCompressed = exports.isErrorCode = exports.getErrorMessageFromResponse = exports.getAuthorizationHeader = exports.shouldRefreshKey = exports.TOKEN_REFRESH_INTERVAL = void 0;

*/
async function shouldRefreshKey(auth) {
const hasKey = await auth.hasKey();
if (!hasKey) {
return false;
}
const type = await auth.getType();
if (type !== token_1.TokenType.JWT) {
return false;
}
const age = await auth.getAge();
// @ts-expect-error
return age >= exports.TOKEN_REFRESH_INTERVAL;
function shouldRefreshKey(auth) {
return __awaiter(this, void 0, void 0, function* () {
const hasKey = yield auth.hasKey();
if (!hasKey) {
return false;
}
const type = yield auth.getType();
if (type !== token_1.TokenType.JWT) {
return false;
}
const age = yield auth.getAge();
// @ts-expect-error
return age >= exports.TOKEN_REFRESH_INTERVAL;
});
}

@@ -78,12 +89,14 @@ exports.shouldRefreshKey = shouldRefreshKey;

*/
exports.getAuthorizationHeader = async function (auth) {
if (auth == null) {
return;
}
const hasKey = await auth.hasKey();
if (!hasKey) {
return;
}
const key = await auth.getKey();
return `Bearer ${key}`;
exports.getAuthorizationHeader = function (auth) {
return __awaiter(this, void 0, void 0, function* () {
if (auth == null) {
return;
}
const hasKey = yield auth.hasKey();
if (!hasKey) {
return;
}
const key = yield auth.getKey();
return `Bearer ${key}`;
});
};

@@ -290,77 +303,81 @@ /**

*/
async function getBody(response, responseFormat) {
if (responseFormat === 'none') {
return null;
}
const contentType = response.headers.get('Content-Type');
if (responseFormat === 'blob' ||
(responseFormat == null && (contentType === null || contentType === void 0 ? void 0 : contentType.includes('binary/octet-stream')))) {
// this is according to the standard
if (typeof response.blob === 'function') {
return response.blob();
function getBody(response, responseFormat) {
return __awaiter(this, void 0, void 0, function* () {
if (responseFormat === 'none') {
return null;
}
// https://github.com/bitinn/node-fetch/blob/master/lib/body.js#L66
// @ts-expect-error
if (typeof response.buffer === 'function') {
const contentType = response.headers.get('Content-Type');
if (responseFormat === 'blob' ||
(responseFormat == null && (contentType === null || contentType === void 0 ? void 0 : contentType.includes('binary/octet-stream')))) {
// this is according to the standard
if (typeof response.blob === 'function') {
return response.blob();
}
// https://github.com/bitinn/node-fetch/blob/master/lib/body.js#L66
// @ts-expect-error
return response.buffer();
if (typeof response.buffer === 'function') {
// @ts-expect-error
return response.buffer();
}
throw new Error('This `fetch` implementation does not support decoding binary streams.');
}
throw new Error('This `fetch` implementation does not support decoding binary streams.');
}
if (responseFormat === 'json' ||
(responseFormat == null && (contentType === null || contentType === void 0 ? void 0 : contentType.includes('application/json')))) {
return response.json();
}
if (responseFormat == null || responseFormat === 'text') {
return response.text();
}
throw new errors.BalenaInvalidParameterError('responseFormat', responseFormat);
if (responseFormat === 'json' ||
(responseFormat == null && (contentType === null || contentType === void 0 ? void 0 : contentType.includes('application/json')))) {
return response.json();
}
if (responseFormat == null || responseFormat === 'text') {
return response.text();
}
throw new errors.BalenaInvalidParameterError('responseFormat', responseFormat);
});
}
exports.getBody = getBody;
// This is the actual implementation that hides the internal `retriesRemaining` parameter
var requestAsync = async function (fetch, options, retriesRemaining) {
const [url, opts] = processRequestOptions(options);
if (retriesRemaining == null) {
retriesRemaining = opts.retries;
}
// When streaming, prefer using the native Headers object if available
if (fetch !== normalFetch && typeof Headers === 'function') {
// Edge's Headers(args) ctor doesn't work as expected when passed in a headers object
// from fetch-ponyfill, treating it as a plain object instead of using the iterator symbol.
// As a result when fetch-readablestream uses the native fetch on Edge, the headers sent
// to the server only contain a `map` property and not the actual headers that we want.
const nativeHeaders = new Headers();
opts.headers.forEach((value, name) => nativeHeaders.append(name, value));
opts.headers = nativeHeaders;
}
try {
const requestTime = Date.now();
let p = fetch(url, opts);
if (opts.timeout && IS_BROWSER) {
p = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('request timed out'));
}, opts.timeout);
p.then(resolve, reject);
});
var requestAsync = function (fetch, options, retriesRemaining) {
return __awaiter(this, void 0, void 0, function* () {
const [url, opts] = processRequestOptions(options);
if (retriesRemaining == null) {
retriesRemaining = opts.retries;
}
const response = await p;
if (opts.signal) {
handleAbortIfNotSupported(opts.signal, response);
// When streaming, prefer using the native Headers object if available
if (fetch !== normalFetch && typeof Headers === 'function') {
// Edge's Headers(args) ctor doesn't work as expected when passed in a headers object
// from fetch-ponyfill, treating it as a plain object instead of using the iterator symbol.
// As a result when fetch-readablestream uses the native fetch on Edge, the headers sent
// to the server only contain a `map` property and not the actual headers that we want.
const nativeHeaders = new Headers();
opts.headers.forEach((value, name) => nativeHeaders.append(name, value));
opts.headers = nativeHeaders;
}
const responseTime = Date.now();
response.duration = responseTime - requestTime;
response.statusCode = response.status;
response.request = {
headers: options.headers,
uri: urlLib.parse(url),
};
return response;
}
catch (err) {
if (retriesRemaining > 0) {
return await requestAsync(fetch, options, retriesRemaining - 1);
try {
const requestTime = Date.now();
let p = fetch(url, opts);
if (opts.timeout && IS_BROWSER) {
p = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('request timed out'));
}, opts.timeout);
p.then(resolve, reject);
});
}
const response = yield p;
if (opts.signal) {
handleAbortIfNotSupported(opts.signal, response);
}
const responseTime = Date.now();
response.duration = responseTime - requestTime;
response.statusCode = response.status;
response.request = {
headers: options.headers,
uri: urlLib.parse(url),
};
return response;
}
throw err;
}
catch (err) {
if (retriesRemaining > 0) {
return yield requestAsync(fetch, options, retriesRemaining - 1);
}
throw err;
}
});
};

@@ -367,0 +384,0 @@ var handleAbortIfNotSupported = function (signal, response) {

{
"name": "balena-request",
"version": "11.0.0-11-x-0b9fa20803d50fba3fa44bb8c914db76f9dfaaf3",
"version": "11.0.0-11-x-2d5ad56a7b9dcdf90fee3758c2573e9fdfbf4700",
"description": "Balena HTTP client",

@@ -5,0 +5,0 @@ "main": "build/request.js",

@@ -11,3 +11,3 @@ {

"sourceMap": false,
"target": "es2018",
"target": "es2015",
"noUnusedParameters": true,

@@ -14,0 +14,0 @@ "noUnusedLocals": true,

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