UNPKG

13.1 kBJavaScriptView Raw
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License. See License.txt in the project root for license information.
3import { HttpHeaders, isHttpHeadersLike } from "./httpHeaders";
4import { Serializer } from "./serializer";
5import { generateUuid } from "./util/utils";
6export function isWebResourceLike(object) {
7 if (typeof object !== "object") {
8 return false;
9 }
10 if (typeof object.url === "string" &&
11 typeof object.method === "string" &&
12 typeof object.headers === "object" &&
13 isHttpHeadersLike(object.headers) &&
14 typeof object.validateRequestProperties === "function" &&
15 typeof object.prepare === "function" &&
16 typeof object.clone === "function") {
17 return true;
18 }
19 return false;
20}
21/**
22 * Creates a new WebResource object.
23 *
24 * This class provides an abstraction over a REST call by being library / implementation agnostic and wrapping the necessary
25 * properties to initiate a request.
26 *
27 * @constructor
28 */
29var WebResource = /** @class */ (function () {
30 function WebResource(url, method, body, query, headers, streamResponseBody, withCredentials, abortSignal, timeout, onUploadProgress, onDownloadProgress, proxySettings, keepAlive, agentSettings, redirectLimit) {
31 this.streamResponseBody = streamResponseBody;
32 this.url = url || "";
33 this.method = method || "GET";
34 this.headers = isHttpHeadersLike(headers) ? headers : new HttpHeaders(headers);
35 this.body = body;
36 this.query = query;
37 this.formData = undefined;
38 this.withCredentials = withCredentials || false;
39 this.abortSignal = abortSignal;
40 this.timeout = timeout || 0;
41 this.onUploadProgress = onUploadProgress;
42 this.onDownloadProgress = onDownloadProgress;
43 this.proxySettings = proxySettings;
44 this.keepAlive = keepAlive;
45 this.agentSettings = agentSettings;
46 this.redirectLimit = redirectLimit;
47 }
48 /**
49 * Validates that the required properties such as method, url, headers["Content-Type"],
50 * headers["accept-language"] are defined. It will throw an error if one of the above
51 * mentioned properties are not defined.
52 */
53 WebResource.prototype.validateRequestProperties = function () {
54 if (!this.method) {
55 throw new Error("WebResource.method is required.");
56 }
57 if (!this.url) {
58 throw new Error("WebResource.url is required.");
59 }
60 };
61 /**
62 * Prepares the request.
63 * @param {RequestPrepareOptions} options Options to provide for preparing the request.
64 * @returns {WebResource} Returns the prepared WebResource (HTTP Request) object that needs to be given to the request pipeline.
65 */
66 WebResource.prototype.prepare = function (options) {
67 if (!options) {
68 throw new Error("options object is required");
69 }
70 if (options.method == undefined || typeof options.method.valueOf() !== "string") {
71 throw new Error("options.method must be a string.");
72 }
73 if (options.url && options.pathTemplate) {
74 throw new Error("options.url and options.pathTemplate are mutually exclusive. Please provide exactly one of them.");
75 }
76 if ((options.pathTemplate == undefined || typeof options.pathTemplate.valueOf() !== "string") &&
77 (options.url == undefined || typeof options.url.valueOf() !== "string")) {
78 throw new Error("Please provide exactly one of options.pathTemplate or options.url.");
79 }
80 // set the url if it is provided.
81 if (options.url) {
82 if (typeof options.url !== "string") {
83 throw new Error('options.url must be of type "string".');
84 }
85 this.url = options.url;
86 }
87 // set the method
88 if (options.method) {
89 var validMethods = ["GET", "PUT", "HEAD", "DELETE", "OPTIONS", "POST", "PATCH", "TRACE"];
90 if (validMethods.indexOf(options.method.toUpperCase()) === -1) {
91 throw new Error('The provided method "' +
92 options.method +
93 '" is invalid. Supported HTTP methods are: ' +
94 JSON.stringify(validMethods));
95 }
96 }
97 this.method = options.method.toUpperCase();
98 // construct the url if path template is provided
99 if (options.pathTemplate) {
100 var pathTemplate_1 = options.pathTemplate, pathParameters_1 = options.pathParameters;
101 if (typeof pathTemplate_1 !== "string") {
102 throw new Error('options.pathTemplate must be of type "string".');
103 }
104 if (!options.baseUrl) {
105 options.baseUrl = "https://management.azure.com";
106 }
107 var baseUrl = options.baseUrl;
108 var url_1 = baseUrl +
109 (baseUrl.endsWith("/") ? "" : "/") +
110 (pathTemplate_1.startsWith("/") ? pathTemplate_1.slice(1) : pathTemplate_1);
111 var segments = url_1.match(/({\w*\s*\w*})/gi);
112 if (segments && segments.length) {
113 if (!pathParameters_1) {
114 throw new Error("pathTemplate: " + pathTemplate_1 + " has been provided. Hence, options.pathParameters must also be provided.");
115 }
116 segments.forEach(function (item) {
117 var pathParamName = item.slice(1, -1);
118 var pathParam = pathParameters_1[pathParamName];
119 if (pathParam === null ||
120 pathParam === undefined ||
121 !(typeof pathParam === "string" || typeof pathParam === "object")) {
122 throw new Error("pathTemplate: " + pathTemplate_1 + " contains the path parameter " + pathParamName +
123 (" however, it is not present in " + pathParameters_1 + " - " + JSON.stringify(pathParameters_1, undefined, 2) + ".") +
124 ("The value of the path parameter can either be a \"string\" of the form { " + pathParamName + ": \"some sample value\" } or ") +
125 ("it can be an \"object\" of the form { \"" + pathParamName + "\": { value: \"some sample value\", skipUrlEncoding: true } }."));
126 }
127 if (typeof pathParam.valueOf() === "string") {
128 url_1 = url_1.replace(item, encodeURIComponent(pathParam));
129 }
130 if (typeof pathParam.valueOf() === "object") {
131 if (!pathParam.value) {
132 throw new Error("options.pathParameters[" + pathParamName + "] is of type \"object\" but it does not contain a \"value\" property.");
133 }
134 if (pathParam.skipUrlEncoding) {
135 url_1 = url_1.replace(item, pathParam.value);
136 }
137 else {
138 url_1 = url_1.replace(item, encodeURIComponent(pathParam.value));
139 }
140 }
141 });
142 }
143 this.url = url_1;
144 }
145 // append query parameters to the url if they are provided. They can be provided with pathTemplate or url option.
146 if (options.queryParameters) {
147 var queryParameters = options.queryParameters;
148 if (typeof queryParameters !== "object") {
149 throw new Error("options.queryParameters must be of type object. It should be a JSON object " +
150 "of \"query-parameter-name\" as the key and the \"query-parameter-value\" as the value. " +
151 "The \"query-parameter-value\" may be fo type \"string\" or an \"object\" of the form { value: \"query-parameter-value\", skipUrlEncoding: true }.");
152 }
153 // append question mark if it is not present in the url
154 if (this.url && this.url.indexOf("?") === -1) {
155 this.url += "?";
156 }
157 // construct queryString
158 var queryParams = [];
159 // We need to populate this.query as a dictionary if the request is being used for Sway's validateRequest().
160 this.query = {};
161 for (var queryParamName in queryParameters) {
162 var queryParam = queryParameters[queryParamName];
163 if (queryParam) {
164 if (typeof queryParam === "string") {
165 queryParams.push(queryParamName + "=" + encodeURIComponent(queryParam));
166 this.query[queryParamName] = encodeURIComponent(queryParam);
167 }
168 else if (typeof queryParam === "object") {
169 if (!queryParam.value) {
170 throw new Error("options.queryParameters[" + queryParamName + "] is of type \"object\" but it does not contain a \"value\" property.");
171 }
172 if (queryParam.skipUrlEncoding) {
173 queryParams.push(queryParamName + "=" + queryParam.value);
174 this.query[queryParamName] = queryParam.value;
175 }
176 else {
177 queryParams.push(queryParamName + "=" + encodeURIComponent(queryParam.value));
178 this.query[queryParamName] = encodeURIComponent(queryParam.value);
179 }
180 }
181 }
182 } // end-of-for
183 // append the queryString
184 this.url += queryParams.join("&");
185 }
186 // add headers to the request if they are provided
187 if (options.headers) {
188 var headers = options.headers;
189 for (var _i = 0, _a = Object.keys(options.headers); _i < _a.length; _i++) {
190 var headerName = _a[_i];
191 this.headers.set(headerName, headers[headerName]);
192 }
193 }
194 // ensure accept-language is set correctly
195 if (!this.headers.get("accept-language")) {
196 this.headers.set("accept-language", "en-US");
197 }
198 // ensure the request-id is set correctly
199 if (!this.headers.get("x-ms-client-request-id") && !options.disableClientRequestId) {
200 this.headers.set("x-ms-client-request-id", generateUuid());
201 }
202 // default
203 if (!this.headers.get("Content-Type")) {
204 this.headers.set("Content-Type", "application/json; charset=utf-8");
205 }
206 // set the request body. request.js automatically sets the Content-Length request header, so we need not set it explicilty
207 this.body = options.body;
208 if (options.body != undefined) {
209 // body as a stream special case. set the body as-is and check for some special request headers specific to sending a stream.
210 if (options.bodyIsStream) {
211 if (!this.headers.get("Transfer-Encoding")) {
212 this.headers.set("Transfer-Encoding", "chunked");
213 }
214 if (this.headers.get("Content-Type") !== "application/octet-stream") {
215 this.headers.set("Content-Type", "application/octet-stream");
216 }
217 }
218 else {
219 if (options.serializationMapper) {
220 this.body = new Serializer(options.mappers).serialize(options.serializationMapper, options.body, "requestBody");
221 }
222 if (!options.disableJsonStringifyOnBody) {
223 this.body = JSON.stringify(options.body);
224 }
225 }
226 }
227 this.abortSignal = options.abortSignal;
228 this.onDownloadProgress = options.onDownloadProgress;
229 this.onUploadProgress = options.onUploadProgress;
230 this.redirectLimit = options.redirectLimit;
231 this.streamResponseBody = options.streamResponseBody;
232 return this;
233 };
234 /**
235 * Clone this WebResource HTTP request object.
236 * @returns {WebResource} The clone of this WebResource HTTP request object.
237 */
238 WebResource.prototype.clone = function () {
239 var result = new WebResource(this.url, this.method, this.body, this.query, this.headers && this.headers.clone(), this.streamResponseBody, this.withCredentials, this.abortSignal, this.timeout, this.onUploadProgress, this.onDownloadProgress, this.proxySettings, this.keepAlive, this.agentSettings, this.redirectLimit);
240 if (this.formData) {
241 result.formData = this.formData;
242 }
243 if (this.operationSpec) {
244 result.operationSpec = this.operationSpec;
245 }
246 if (this.shouldDeserialize) {
247 result.shouldDeserialize = this.shouldDeserialize;
248 }
249 if (this.operationResponseGetter) {
250 result.operationResponseGetter = this.operationResponseGetter;
251 }
252 return result;
253 };
254 return WebResource;
255}());
256export { WebResource };
257//# sourceMappingURL=webResource.js.map
\No newline at end of file