webResource.js 12 KB

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