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

@microsoft/microsoft-graph-client

Package Overview
Dependencies
Maintainers
4
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@microsoft/microsoft-graph-client - npm Package Compare versions

Comparing version 3.0.0-Preview.1 to 3.0.0-Preview.2

3

lib/es/src/GraphRequest.js

@@ -274,2 +274,3 @@ /**

send(request, options, callback) {
var _a;
return __awaiter(this, void 0, void 0, function* () {

@@ -279,2 +280,3 @@ let rawResponse;

this.updateRequestOptions(options);
const customHosts = (_a = this.config) === null || _a === void 0 ? void 0 : _a.customHosts;
try {

@@ -285,2 +287,3 @@ const context = yield this.httpClient.sendRequest({

middlewareControl,
customHosts,
});

@@ -287,0 +290,0 @@ rawResponse = context.response;

@@ -36,1 +36,8 @@ /**

export declare const isGraphURL: (url: string) => boolean;
/**
* Checks if the url is for one of the custom hosts provided during client initialization
* @param {string} url - The url to be verified
* @param {Set} customHosts - The url to be verified
* @returns {boolean} - Returns true if the url is a for a custom host
*/
export declare const isCustomHost: (url: string, customHosts: Set<string>) => boolean;

@@ -11,2 +11,3 @@ /**

import { GRAPH_URLS } from "./Constants";
import { GraphClientError } from "./GraphClientError";
/**

@@ -67,2 +68,21 @@ * To hold list of OData query params

export const isGraphURL = (url) => {
return isValidEndpoint(url);
};
/**
* Checks if the url is for one of the custom hosts provided during client initialization
* @param {string} url - The url to be verified
* @param {Set} customHosts - The url to be verified
* @returns {boolean} - Returns true if the url is a for a custom host
*/
export const isCustomHost = (url, customHosts) => {
customHosts.forEach((host) => isCustomHostValid(host));
return isValidEndpoint(url, customHosts);
};
/**
* Checks if the url is for one of the provided hosts.
* @param {string} url - The url to be verified
* @param {Set<string>} allowedHosts - A set of hosts.
* @returns {boolean} - Returns true is for one of the provided endpoints.
*/
const isValidEndpoint = (url, allowedHosts = GRAPH_URLS) => {
// Valid Graph URL pattern - https://graph.microsoft.com/{version}/{resource}?{query-parameters}

@@ -80,7 +100,7 @@ // Valid Graph URL example - https://graph.microsoft.com/v1.0/

hostName = url.substring(0, startofPortNoPos);
return GRAPH_URLS.has(hostName);
return allowedHosts.has(hostName);
}
// Parse out the host
hostName = url.substring(0, endOfHostStrPos);
return GRAPH_URLS.has(hostName);
return allowedHosts.has(hostName);
}

@@ -90,2 +110,11 @@ }

};
/**
* Throws error if the string is not a valid host/hostname and contains other url parts.
* @param {string} url - The host to be verified
*/
const isCustomHostValid = (host) => {
if (host.indexOf("/") !== -1) {
throw new GraphClientError("Please add only hosts or hostnames to the CustomHosts config. If the url is `http://example.com:3000/`, host is `example:3000`");
}
};
//# sourceMappingURL=GraphRequestUtil.js.map

@@ -19,2 +19,3 @@ /**

* @property {Middleware| Middleware[]} [middleware] - The first middleware of the middleware chain or an array of the Middleware handlers
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*/

@@ -28,2 +29,6 @@ export interface ClientOptions {

middleware?: Middleware | Middleware[];
/**
* Example - If URL is "https://test_host/v1.0", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

@@ -15,2 +15,4 @@ /**

* @property {MiddlewareControl} [middlewareControl] - The options for the middleware chain
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*
*/

@@ -22,2 +24,6 @@ export interface Context {

middlewareControl?: MiddlewareControl;
/**
* Example - If URL is "https://test_host", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

@@ -17,2 +17,3 @@ /**

* @property {FetchOptions} [fetchOptions] - The options for fetch request
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*/

@@ -25,2 +26,6 @@ export interface Options {

fetchOptions?: FetchOptions;
/**
* Example - If URL is "https://test_host/v1.0", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

4

lib/es/src/middleware/AuthenticationHandler.js

@@ -11,3 +11,3 @@ /**

*/
import { isGraphURL } from "../GraphRequestUtil";
import { isCustomHost, isGraphURL } from "../GraphRequestUtil";
import { MiddlewareControl } from "./MiddlewareControl";

@@ -42,3 +42,3 @@ import { appendRequestHeader } from "./MiddlewareUtil";

const url = typeof context.request === "string" ? context.request : context.request.url;
if (isGraphURL(url)) {
if (isGraphURL(url) || (context.customHosts && isCustomHost(url, context.customHosts))) {
let options;

@@ -45,0 +45,0 @@ if (context.middlewareControl instanceof MiddlewareControl) {

@@ -11,3 +11,3 @@ /**

*/
import { isGraphURL } from "../GraphRequestUtil";
import { isCustomHost, isGraphURL } from "../GraphRequestUtil";
import { PACKAGE_VERSION } from "../Version";

@@ -33,3 +33,3 @@ import { MiddlewareControl } from "./MiddlewareControl";

const url = typeof context.request === "string" ? context.request : context.request.url;
if (isGraphURL(url)) {
if (isGraphURL(url) || (context.customHosts && isCustomHost(url, context.customHosts))) {
// Add telemetry only if the request url is a Graph URL.

@@ -36,0 +36,0 @@ // Errors are reported as in issue #265 if headers are present when redirecting to a non Graph URL

@@ -5,2 +5,6 @@ /// <reference types="node" />

import { Range } from "../Range";
/**
* @class
* FileObject class for Readable Stream upload
*/
export declare class StreamUpload implements FileObject<Readable> {

@@ -10,2 +14,8 @@ content: Readable;

size: number;
/**
* @private
* Represents a cache of the last attempted upload slice.
* This can be used when resuming a previously failed slice upload.
*/
private previousSlice;
constructor(content: Readable, name: string, size: number);

@@ -12,0 +22,0 @@ /**

import { __awaiter } from "tslib";
import { GraphClientError } from "../../../GraphClientError";
/**
* @class
* FileObject class for Readable Stream upload
*/
export class StreamUpload {

@@ -20,12 +24,50 @@ constructor(content, name, size) {

return __awaiter(this, void 0, void 0, function* () {
const rangeSize = range.maxValue - range.minValue + 1;
let rangeSize = range.maxValue - range.minValue + 1;
/* readable.readable Is true if it is safe to call readable.read(),
* which means the stream has not been destroyed or emitted 'error' or 'end'
*/
const bufs = [];
/**
* The sliceFile reads the first `rangeSize` number of bytes from the stream.
* The previousSlice property is used to seek the range of bytes in the previous slice.
* Suppose, the sliceFile reads bytes from `10 - 20` from the stream but the upload of this slice fails.
* When the user resumes, the stream will have bytes from position 21.
* The previousSlice.Range is used to compare if the requested range is cached in the previousSlice property or present in the Readable Stream.
*/
if (this.previousSlice) {
if (range.minValue < this.previousSlice.range.minValue) {
throw new GraphClientError("An error occurred while uploading the stream. Please restart the stream upload from the first byte of the file.");
}
if (range.minValue < this.previousSlice.range.maxValue) {
const previousRangeMin = this.previousSlice.range.minValue;
const previousRangeMax = this.previousSlice.range.maxValue;
// Check if the requested range is same as previously sliced range
if (range.minValue === previousRangeMin && range.maxValue === previousRangeMax) {
return this.previousSlice.fileSlice;
}
/**
* The following check considers a possibility
* of an upload failing after some of the bytes of the previous slice
* were successfully uploaded.
* Example - Previous slice range - `10 - 20`. Current requested range is `15 - 20`.
*/
if (range.maxValue === previousRangeMax) {
return this.previousSlice.fileSlice.slice(range.minValue, range.maxValue + 1);
}
/**
* If an upload fails after some of the bytes of the previous slice
* were successfully uploaded and the new Range.Maximum is greater than the previous Range.Maximum
* Example - Previous slice range - `10 - 20`. Current requested range is `15 - 25`,
* then read the bytes from position 15 to 20 from previousSlice.fileSlice and read bytes from position 21 to 25 from the Readable Stream
*/
bufs.push(this.previousSlice.fileSlice.slice(range.minValue, previousRangeMax + 1));
rangeSize = range.maxValue - previousRangeMax;
}
}
if (this.content && this.content.readable) {
if (this.content.readableLength >= rangeSize) {
return this.content.read(rangeSize);
bufs.push(this.content.read(rangeSize));
}
else {
return yield this.readNBytesFromStream(rangeSize);
bufs.push(yield this.readNBytesFromStream(rangeSize));
}

@@ -36,2 +78,5 @@ }

}
const slicedChunk = Buffer.concat(bufs);
this.previousSlice = { fileSlice: slicedChunk, range };
return slicedChunk;
});

@@ -38,0 +83,0 @@ }

@@ -24,2 +24,3 @@ /**

* @property {number} [rangeSize = LargeFileUploadTask.DEFAULT_FILE_SIZE] - Specifies the range chunk size
* @property {UploadEventHandlers} uploadEventHandlers - UploadEventHandlers attached to an upload task
*/

@@ -26,0 +27,0 @@ export interface LargeFileUploadTaskOptions {

@@ -10,2 +10,2 @@ /**

*/
export declare const PACKAGE_VERSION = "3.0.0-Preview.1";
export declare const PACKAGE_VERSION = "3.0.0-Preview.2";

@@ -12,3 +12,3 @@ /**

*/
export const PACKAGE_VERSION = "3.0.0-Preview.1";
export const PACKAGE_VERSION = "3.0.0-Preview.2";
//# sourceMappingURL=Version.js.map

@@ -281,12 +281,14 @@ "use strict";

GraphRequest.prototype.send = function (request, options, callback) {
var _a;
return tslib_1.__awaiter(this, void 0, void 0, function () {
var rawResponse, middlewareControl, context_1, response, error_1, statusCode, gError;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
var rawResponse, middlewareControl, customHosts, context_1, response, error_1, statusCode, gError;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
middlewareControl = new MiddlewareControl_1.MiddlewareControl(this._middlewareOptions);
this.updateRequestOptions(options);
_a.label = 1;
customHosts = (_a = this.config) === null || _a === void 0 ? void 0 : _a.customHosts;
_b.label = 1;
case 1:
_a.trys.push([1, 4, , 6]);
_b.trys.push([1, 4, , 6]);
return [4 /*yield*/, this.httpClient.sendRequest({

@@ -296,12 +298,13 @@ request: request,

middlewareControl: middlewareControl,
customHosts: customHosts,
})];
case 2:
context_1 = _a.sent();
context_1 = _b.sent();
rawResponse = context_1.response;
return [4 /*yield*/, GraphResponseHandler_1.GraphResponseHandler.getResponse(rawResponse, this._responseType, callback)];
case 3:
response = _a.sent();
response = _b.sent();
return [2 /*return*/, response];
case 4:
error_1 = _a.sent();
error_1 = _b.sent();
if (error_1 instanceof GraphClientError_1.GraphClientError) {

@@ -316,3 +319,3 @@ throw error_1;

case 5:
gError = _a.sent();
gError = _b.sent();
throw gError;

@@ -319,0 +322,0 @@ case 6: return [2 /*return*/];

@@ -36,1 +36,8 @@ /**

export declare const isGraphURL: (url: string) => boolean;
/**
* Checks if the url is for one of the custom hosts provided during client initialization
* @param {string} url - The url to be verified
* @param {Set} customHosts - The url to be verified
* @returns {boolean} - Returns true if the url is a for a custom host
*/
export declare const isCustomHost: (url: string, customHosts: Set<string>) => boolean;

@@ -9,3 +9,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.isGraphURL = exports.serializeContent = exports.urlJoin = exports.oDataQueryNames = void 0;
exports.isCustomHost = exports.isGraphURL = exports.serializeContent = exports.urlJoin = exports.oDataQueryNames = void 0;
/**

@@ -15,2 +15,3 @@ * @module GraphRequestUtil

var Constants_1 = require("./Constants");
var GraphClientError_1 = require("./GraphClientError");
/**

@@ -73,2 +74,24 @@ * To hold list of OData query params

var isGraphURL = function (url) {
return isValidEndpoint(url);
};
exports.isGraphURL = isGraphURL;
/**
* Checks if the url is for one of the custom hosts provided during client initialization
* @param {string} url - The url to be verified
* @param {Set} customHosts - The url to be verified
* @returns {boolean} - Returns true if the url is a for a custom host
*/
var isCustomHost = function (url, customHosts) {
customHosts.forEach(function (host) { return isCustomHostValid(host); });
return isValidEndpoint(url, customHosts);
};
exports.isCustomHost = isCustomHost;
/**
* Checks if the url is for one of the provided hosts.
* @param {string} url - The url to be verified
* @param {Set<string>} allowedHosts - A set of hosts.
* @returns {boolean} - Returns true is for one of the provided endpoints.
*/
var isValidEndpoint = function (url, allowedHosts) {
if (allowedHosts === void 0) { allowedHosts = Constants_1.GRAPH_URLS; }
// Valid Graph URL pattern - https://graph.microsoft.com/{version}/{resource}?{query-parameters}

@@ -86,7 +109,7 @@ // Valid Graph URL example - https://graph.microsoft.com/v1.0/

hostName = url.substring(0, startofPortNoPos);
return Constants_1.GRAPH_URLS.has(hostName);
return allowedHosts.has(hostName);
}
// Parse out the host
hostName = url.substring(0, endOfHostStrPos);
return Constants_1.GRAPH_URLS.has(hostName);
return allowedHosts.has(hostName);
}

@@ -96,3 +119,11 @@ }

};
exports.isGraphURL = isGraphURL;
/**
* Throws error if the string is not a valid host/hostname and contains other url parts.
* @param {string} url - The host to be verified
*/
var isCustomHostValid = function (host) {
if (host.indexOf("/") !== -1) {
throw new GraphClientError_1.GraphClientError("Please add only hosts or hostnames to the CustomHosts config. If the url is `http://example.com:3000/`, host is `example:3000`");
}
};
//# sourceMappingURL=GraphRequestUtil.js.map

@@ -19,2 +19,3 @@ /**

* @property {Middleware| Middleware[]} [middleware] - The first middleware of the middleware chain or an array of the Middleware handlers
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*/

@@ -28,2 +29,6 @@ export interface ClientOptions {

middleware?: Middleware | Middleware[];
/**
* Example - If URL is "https://test_host/v1.0", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

@@ -15,2 +15,4 @@ /**

* @property {MiddlewareControl} [middlewareControl] - The options for the middleware chain
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*
*/

@@ -22,2 +24,6 @@ export interface Context {

middlewareControl?: MiddlewareControl;
/**
* Example - If URL is "https://test_host", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

@@ -17,2 +17,3 @@ /**

* @property {FetchOptions} [fetchOptions] - The options for fetch request
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*/

@@ -25,2 +26,6 @@ export interface Options {

fetchOptions?: FetchOptions;
/**
* Example - If URL is "https://test_host/v1.0", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

@@ -48,3 +48,3 @@ "use strict";

url = typeof context.request === "string" ? context.request : context.request.url;
if (!GraphRequestUtil_1.isGraphURL(url)) return [3 /*break*/, 2];
if (!(GraphRequestUtil_1.isGraphURL(url) || (context.customHosts && GraphRequestUtil_1.isCustomHost(url, context.customHosts)))) return [3 /*break*/, 2];
options = void 0;

@@ -51,0 +51,0 @@ if (context.middlewareControl instanceof MiddlewareControl_1.MiddlewareControl) {

@@ -41,3 +41,3 @@ "use strict";

url = typeof context.request === "string" ? context.request : context.request.url;
if (GraphRequestUtil_1.isGraphURL(url)) {
if (GraphRequestUtil_1.isGraphURL(url) || (context.customHosts && GraphRequestUtil_1.isCustomHost(url, context.customHosts))) {
clientRequestId = MiddlewareUtil_1.getRequestHeader(context.request, context.options, TelemetryHandler.CLIENT_REQUEST_ID_HEADER);

@@ -44,0 +44,0 @@ if (!clientRequestId) {

@@ -5,2 +5,6 @@ /// <reference types="node" />

import { Range } from "../Range";
/**
* @class
* FileObject class for Readable Stream upload
*/
export declare class StreamUpload implements FileObject<Readable> {

@@ -10,2 +14,8 @@ content: Readable;

size: number;
/**
* @private
* Represents a cache of the last attempted upload slice.
* This can be used when resuming a previously failed slice upload.
*/
private previousSlice;
constructor(content: Readable, name: string, size: number);

@@ -12,0 +22,0 @@ /**

@@ -6,2 +6,6 @@ "use strict";

var GraphClientError_1 = require("../../../GraphClientError");
/**
* @class
* FileObject class for Readable Stream upload
*/
var StreamUpload = /** @class */ (function () {

@@ -24,15 +28,61 @@ function StreamUpload(content, name, size) {

return tslib_1.__awaiter(this, void 0, void 0, function () {
var rangeSize;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
var rangeSize, bufs, previousRangeMin, previousRangeMax, _a, _b, slicedChunk;
return tslib_1.__generator(this, function (_c) {
switch (_c.label) {
case 0:
rangeSize = range.maxValue - range.minValue + 1;
bufs = [];
/**
* The sliceFile reads the first `rangeSize` number of bytes from the stream.
* The previousSlice property is used to seek the range of bytes in the previous slice.
* Suppose, the sliceFile reads bytes from `10 - 20` from the stream but the upload of this slice fails.
* When the user resumes, the stream will have bytes from position 21.
* The previousSlice.Range is used to compare if the requested range is cached in the previousSlice property or present in the Readable Stream.
*/
if (this.previousSlice) {
if (range.minValue < this.previousSlice.range.minValue) {
throw new GraphClientError_1.GraphClientError("An error occurred while uploading the stream. Please restart the stream upload from the first byte of the file.");
}
if (range.minValue < this.previousSlice.range.maxValue) {
previousRangeMin = this.previousSlice.range.minValue;
previousRangeMax = this.previousSlice.range.maxValue;
// Check if the requested range is same as previously sliced range
if (range.minValue === previousRangeMin && range.maxValue === previousRangeMax) {
return [2 /*return*/, this.previousSlice.fileSlice];
}
/**
* The following check considers a possibility
* of an upload failing after some of the bytes of the previous slice
* were successfully uploaded.
* Example - Previous slice range - `10 - 20`. Current requested range is `15 - 20`.
*/
if (range.maxValue === previousRangeMax) {
return [2 /*return*/, this.previousSlice.fileSlice.slice(range.minValue, range.maxValue + 1)];
}
/**
* If an upload fails after some of the bytes of the previous slice
* were successfully uploaded and the new Range.Maximum is greater than the previous Range.Maximum
* Example - Previous slice range - `10 - 20`. Current requested range is `15 - 25`,
* then read the bytes from position 15 to 20 from previousSlice.fileSlice and read bytes from position 21 to 25 from the Readable Stream
*/
bufs.push(this.previousSlice.fileSlice.slice(range.minValue, previousRangeMax + 1));
rangeSize = range.maxValue - previousRangeMax;
}
}
if (!(this.content && this.content.readable)) return [3 /*break*/, 4];
if (!(this.content.readableLength >= rangeSize)) return [3 /*break*/, 1];
return [2 /*return*/, this.content.read(rangeSize)];
case 1: return [4 /*yield*/, this.readNBytesFromStream(rangeSize)];
case 2: return [2 /*return*/, _a.sent()];
bufs.push(this.content.read(rangeSize));
return [3 /*break*/, 3];
case 1:
_b = (_a = bufs).push;
return [4 /*yield*/, this.readNBytesFromStream(rangeSize)];
case 2:
_b.apply(_a, [_c.sent()]);
_c.label = 3;
case 3: return [3 /*break*/, 5];
case 4: throw new GraphClientError_1.GraphClientError("Stream is not readable.");
case 5: return [2 /*return*/];
case 5:
slicedChunk = Buffer.concat(bufs);
this.previousSlice = { fileSlice: slicedChunk, range: range };
return [2 /*return*/, slicedChunk];
}

@@ -39,0 +89,0 @@ });

@@ -24,2 +24,3 @@ /**

* @property {number} [rangeSize = LargeFileUploadTask.DEFAULT_FILE_SIZE] - Specifies the range chunk size
* @property {UploadEventHandlers} uploadEventHandlers - UploadEventHandlers attached to an upload task
*/

@@ -26,0 +27,0 @@ export interface LargeFileUploadTaskOptions {

@@ -10,2 +10,2 @@ /**

*/
export declare const PACKAGE_VERSION = "3.0.0-Preview.1";
export declare const PACKAGE_VERSION = "3.0.0-Preview.2";

@@ -15,3 +15,3 @@ "use strict";

*/
exports.PACKAGE_VERSION = "3.0.0-Preview.1";
exports.PACKAGE_VERSION = "3.0.0-Preview.2";
//# sourceMappingURL=Version.js.map
{
"name": "@microsoft/microsoft-graph-client",
"version": "3.0.0-Preview.1",
"version": "3.0.0-Preview.2",
"description": "Microsoft Graph Client Library",

@@ -98,3 +98,3 @@ "keywords": [

"isomorphic-fetch": "^3.0.0",
"karma": "^5.2.3",
"karma": "^6.3.2",
"karma-chai": "^0.1.0",

@@ -105,3 +105,3 @@ "karma-chrome-launcher": "^3.1.0",

"karma-typescript": "^5.2.0",
"lint-staged": "^8.1.5",
"lint-staged": "^11.0.0",
"mocha": "^6.2.3",

@@ -108,0 +108,0 @@ "msal": "^1.0.0",

@@ -286,3 +286,3 @@ /**

/* The query key-value pair must be split on the first equals sign to avoid errors in parsing nested query parameters.
Example-> "/me?$expand=home($select=city)" */
Example-> "/me?$expand=home($select=city)" */
if (this.isValidQueryKeyValuePair(queryParameter)) {

@@ -295,3 +295,3 @@ const indexOfFirstEquals = queryParameter.indexOf("=");

/* Push values which are not of key-value structure.
Example-> Handle an invalid input->.query(test), .query($select($select=name)) and let the Graph API respond with the error in the URL*/
Example-> Handle an invalid input->.query(test), .query($select($select=name)) and let the Graph API respond with the error in the URL*/
this.urlComponents.otherURLQueryOptions.push(queryParameter);

@@ -372,2 +372,3 @@ }

this.updateRequestOptions(options);
const customHosts = this.config?.customHosts;
try {

@@ -378,3 +379,5 @@ const context: Context = await this.httpClient.sendRequest({

middlewareControl,
customHosts,
});
rawResponse = context.response;

@@ -381,0 +384,0 @@ const response: any = await GraphResponseHandler.getResponse(rawResponse, this._responseType, callback);

@@ -12,2 +12,3 @@ /**

import { GRAPH_URLS } from "./Constants";
import { GraphClientError } from "./GraphClientError";
/**

@@ -69,2 +70,23 @@ * To hold list of OData query params

export const isGraphURL = (url: string): boolean => {
return isValidEndpoint(url);
};
/**
* Checks if the url is for one of the custom hosts provided during client initialization
* @param {string} url - The url to be verified
* @param {Set} customHosts - The url to be verified
* @returns {boolean} - Returns true if the url is a for a custom host
*/
export const isCustomHost = (url: string, customHosts: Set<string>): boolean => {
customHosts.forEach((host) => isCustomHostValid(host));
return isValidEndpoint(url, customHosts);
};
/**
* Checks if the url is for one of the provided hosts.
* @param {string} url - The url to be verified
* @param {Set<string>} allowedHosts - A set of hosts.
* @returns {boolean} - Returns true is for one of the provided endpoints.
*/
const isValidEndpoint = (url: string, allowedHosts: Set<string> = GRAPH_URLS): boolean => {
// Valid Graph URL pattern - https://graph.microsoft.com/{version}/{resource}?{query-parameters}

@@ -84,7 +106,7 @@ // Valid Graph URL example - https://graph.microsoft.com/v1.0/

hostName = url.substring(0, startofPortNoPos);
return GRAPH_URLS.has(hostName);
return allowedHosts.has(hostName);
}
// Parse out the host
hostName = url.substring(0, endOfHostStrPos);
return GRAPH_URLS.has(hostName);
return allowedHosts.has(hostName);
}

@@ -95,1 +117,11 @@ }

};
/**
* Throws error if the string is not a valid host/hostname and contains other url parts.
* @param {string} url - The host to be verified
*/
const isCustomHostValid = (host: string) => {
if (host.indexOf("/") !== -1) {
throw new GraphClientError("Please add only hosts or hostnames to the CustomHosts config. If the url is `http://example.com:3000/`, host is `example:3000`");
}
};

@@ -21,3 +21,5 @@ /**

* @property {Middleware| Middleware[]} [middleware] - The first middleware of the middleware chain or an array of the Middleware handlers
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*/
export interface ClientOptions {

@@ -30,2 +32,6 @@ authProvider?: AuthenticationProvider;

middleware?: Middleware | Middleware[];
/**
* Example - If URL is "https://test_host/v1.0", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

@@ -17,2 +17,4 @@ /**

* @property {MiddlewareControl} [middlewareControl] - The options for the middleware chain
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*
*/

@@ -25,2 +27,6 @@

middlewareControl?: MiddlewareControl;
/**
* Example - If URL is "https://test_host", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

@@ -19,2 +19,3 @@ /**

* @property {FetchOptions} [fetchOptions] - The options for fetch request
* @property {Set<string>}[customHosts] - A set of custom host names. Should contain hostnames only.
*/

@@ -27,2 +28,6 @@ export interface Options {

fetchOptions?: FetchOptions;
/**
* Example - If URL is "https://test_host/v1.0", then set property "customHosts" as "customHosts: Set<string>(["test_host"])"
*/
customHosts?: Set<string>;
}

@@ -12,3 +12,3 @@ /**

import { isGraphURL } from "../GraphRequestUtil";
import { isCustomHost, isGraphURL } from "../GraphRequestUtil";
import { AuthenticationProvider } from "../IAuthenticationProvider";

@@ -66,3 +66,3 @@ import { AuthenticationProviderOptions } from "../IAuthenticationProviderOptions";

const url = typeof context.request === "string" ? context.request : context.request.url;
if (isGraphURL(url)) {
if (isGraphURL(url) || (context.customHosts && isCustomHost(url, context.customHosts))) {
let options: AuthenticationHandlerOptions;

@@ -69,0 +69,0 @@ if (context.middlewareControl instanceof MiddlewareControl) {

@@ -11,3 +11,3 @@ /**

*/
import { isGraphURL } from "../GraphRequestUtil";
import { isCustomHost, isGraphURL } from "../GraphRequestUtil";
import { Context } from "../IContext";

@@ -69,3 +69,3 @@ import { PACKAGE_VERSION } from "../Version";

const url = typeof context.request === "string" ? context.request : context.request.url;
if (isGraphURL(url)) {
if (isGraphURL(url) || (context.customHosts && isCustomHost(url, context.customHosts))) {
// Add telemetry only if the request url is a Graph URL.

@@ -72,0 +72,0 @@ // Errors are reported as in issue #265 if headers are present when redirecting to a non Graph URL

@@ -6,3 +6,26 @@ import { Readable } from "stream";

import { Range } from "../Range";
/**
* @interface
* Interface to store slice of a stream and range of the slice.
* @property {Buffer} fileSlice - The slice of the stream
* @property {Range} range - The range of the slice
*/
interface SliceRecord {
fileSlice: Buffer;
range: Range;
}
/**
* @class
* FileObject class for Readable Stream upload
*/
export class StreamUpload implements FileObject<Readable> {
/**
* @private
* Represents a cache of the last attempted upload slice.
* This can be used when resuming a previously failed slice upload.
*/
private previousSlice: SliceRecord;
public constructor(public content: Readable, public name: string, public size: number) {

@@ -21,11 +44,56 @@ if (!content || !name || !size) {

public async sliceFile(range: Range): Promise<SliceType> {
const rangeSize = range.maxValue - range.minValue + 1;
let rangeSize = range.maxValue - range.minValue + 1;
/* readable.readable Is true if it is safe to call readable.read(),
* which means the stream has not been destroyed or emitted 'error' or 'end'
*/
const bufs = [];
/**
* The sliceFile reads the first `rangeSize` number of bytes from the stream.
* The previousSlice property is used to seek the range of bytes in the previous slice.
* Suppose, the sliceFile reads bytes from `10 - 20` from the stream but the upload of this slice fails.
* When the user resumes, the stream will have bytes from position 21.
* The previousSlice.Range is used to compare if the requested range is cached in the previousSlice property or present in the Readable Stream.
*/
if (this.previousSlice) {
if (range.minValue < this.previousSlice.range.minValue) {
throw new GraphClientError("An error occurred while uploading the stream. Please restart the stream upload from the first byte of the file.");
}
if (range.minValue < this.previousSlice.range.maxValue) {
const previousRangeMin = this.previousSlice.range.minValue;
const previousRangeMax = this.previousSlice.range.maxValue;
// Check if the requested range is same as previously sliced range
if (range.minValue === previousRangeMin && range.maxValue === previousRangeMax) {
return this.previousSlice.fileSlice;
}
/**
* The following check considers a possibility
* of an upload failing after some of the bytes of the previous slice
* were successfully uploaded.
* Example - Previous slice range - `10 - 20`. Current requested range is `15 - 20`.
*/
if (range.maxValue === previousRangeMax) {
return this.previousSlice.fileSlice.slice(range.minValue, range.maxValue + 1);
}
/**
* If an upload fails after some of the bytes of the previous slice
* were successfully uploaded and the new Range.Maximum is greater than the previous Range.Maximum
* Example - Previous slice range - `10 - 20`. Current requested range is `15 - 25`,
* then read the bytes from position 15 to 20 from previousSlice.fileSlice and read bytes from position 21 to 25 from the Readable Stream
*/
bufs.push(this.previousSlice.fileSlice.slice(range.minValue, previousRangeMax + 1));
rangeSize = range.maxValue - previousRangeMax;
}
}
if (this.content && this.content.readable) {
if (this.content.readableLength >= rangeSize) {
return this.content.read(rangeSize);
bufs.push(this.content.read(rangeSize));
} else {
return await this.readNBytesFromStream(rangeSize);
bufs.push(await this.readNBytesFromStream(rangeSize));
}

@@ -35,2 +103,6 @@ } else {

}
const slicedChunk = Buffer.concat(bufs);
this.previousSlice = { fileSlice: slicedChunk, range };
return slicedChunk;
}

@@ -37,0 +109,0 @@

@@ -44,2 +44,3 @@ /**

* @property {number} [rangeSize = LargeFileUploadTask.DEFAULT_FILE_SIZE] - Specifies the range chunk size
* @property {UploadEventHandlers} uploadEventHandlers - UploadEventHandlers attached to an upload task
*/

@@ -46,0 +47,0 @@ export interface LargeFileUploadTaskOptions {

@@ -15,2 +15,2 @@ /**

export const PACKAGE_VERSION = "3.0.0-Preview.1";
export const PACKAGE_VERSION = "3.0.0-Preview.2";

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc