UNPKG

5.31 kBPlain TextView Raw
1/**
2 * -------------------------------------------------------------------------------------------
3 * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4 * See License in the project root for license information.
5 * -------------------------------------------------------------------------------------------
6 */
7
8/**
9 * @module GraphRequestUtil
10 */
11import { GRAPH_URLS } from "./Constants";
12import { GraphClientError } from "./GraphClientError";
13/**
14 * To hold list of OData query params
15 */
16export const oDataQueryNames = ["$select", "$expand", "$orderby", "$filter", "$top", "$skip", "$skipToken", "$count"];
17
18/**
19 * To construct the URL by appending the segments with "/"
20 * @param {string[]} urlSegments - The array of strings
21 * @returns The constructed URL string
22 */
23export const urlJoin = (urlSegments: string[]): string => {
24 const removePostSlash = (s) => s.replace(/\/+$/, "");
25 const removePreSlash = (s) => s.replace(/^\/+/, "");
26 const joiner = (pre, cur) => [removePostSlash(pre), removePreSlash(cur)].join("/");
27 const parts = Array.prototype.slice.call(urlSegments);
28 return parts.reduce(joiner);
29};
30
31/**
32 * Serializes the content
33 * @param {any} content - The content value that needs to be serialized
34 * @returns The serialized content
35 *
36 * Note:
37 * This conversion is required due to the following reasons:
38 * Body parameter of Request method of isomorphic-fetch only accepts Blob, ArrayBuffer, FormData, TypedArrays string.
39 * Node.js platform does not support Blob, FormData. Javascript File object inherits from Blob so it is also not supported in node. Therefore content of type Blob, File, FormData will only come from browsers.
40 * Parallel to ArrayBuffer in javascript, node provides Buffer interface. Node's Buffer is able to send the arbitrary binary data to the server successfully for both Browser and Node platform. Whereas sending binary data via ArrayBuffer or TypedArrays was only possible using Browser. To support both Node and Browser, `serializeContent` converts TypedArrays or ArrayBuffer to `Node Buffer`.
41 * If the data received is in JSON format, `serializeContent` converts the JSON to string.
42 */
43
44export const serializeContent = (content: any): any => {
45 const className: string = content && content.constructor && content.constructor.name;
46 if (className === "Buffer" || className === "Blob" || className === "File" || className === "FormData" || typeof content === "string") {
47 return content;
48 }
49 if (className === "ArrayBuffer") {
50 content = Buffer.from(content);
51 } else if (className === "Int8Array" || className === "Int16Array" || className === "Int32Array" || className === "Uint8Array" || className === "Uint16Array" || className === "Uint32Array" || className === "Uint8ClampedArray" || className === "Float32Array" || className === "Float64Array" || className === "DataView") {
52 content = Buffer.from(content.buffer);
53 } else {
54 try {
55 content = JSON.stringify(content);
56 } catch (error) {
57 throw new Error("Unable to stringify the content");
58 }
59 }
60 return content;
61};
62
63/**
64 * Checks if the url is one of the service root endpoints for Microsoft Graph and Graph Explorer.
65 * @param {string} url - The url to be verified
66 * @returns {boolean} - Returns true if the url is a Graph URL
67 */
68export const isGraphURL = (url: string): boolean => {
69 return isValidEndpoint(url);
70};
71
72/**
73 * Checks if the url is for one of the custom hosts provided during client initialization
74 * @param {string} url - The url to be verified
75 * @param {Set} customHosts - The url to be verified
76 * @returns {boolean} - Returns true if the url is a for a custom host
77 */
78export const isCustomHost = (url: string, customHosts: Set<string>): boolean => {
79 customHosts.forEach((host) => isCustomHostValid(host));
80 return isValidEndpoint(url, customHosts);
81};
82
83/**
84 * Checks if the url is for one of the provided hosts.
85 * @param {string} url - The url to be verified
86 * @param {Set<string>} allowedHosts - A set of hosts.
87 * @returns {boolean} - Returns true is for one of the provided endpoints.
88 */
89const isValidEndpoint = (url: string, allowedHosts: Set<string> = GRAPH_URLS): boolean => {
90 // Valid Graph URL pattern - https://graph.microsoft.com/{version}/{resource}?{query-parameters}
91 // Valid Graph URL example - https://graph.microsoft.com/v1.0/
92 url = url.toLowerCase();
93
94 if (url.indexOf("https://") !== -1) {
95 url = url.replace("https://", "");
96
97 // Find where the host ends
98 const startofPortNoPos = url.indexOf(":");
99 const endOfHostStrPos = url.indexOf("/");
100 let hostName = "";
101 if (endOfHostStrPos !== -1) {
102 if (startofPortNoPos !== -1 && startofPortNoPos < endOfHostStrPos) {
103 hostName = url.substring(0, startofPortNoPos);
104 return allowedHosts.has(hostName);
105 }
106 // Parse out the host
107 hostName = url.substring(0, endOfHostStrPos);
108 return allowedHosts.has(hostName);
109 }
110 }
111
112 return false;
113};
114
115/**
116 * Throws error if the string is not a valid host/hostname and contains other url parts.
117 * @param {string} host - The host to be verified
118 */
119const isCustomHostValid = (host: string) => {
120 if (host.indexOf("/") !== -1) {
121 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`");
122 }
123};