"use strict"; // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const httpm = require("./HttpClient"); const util = require("./Util"); class RestClient { /** * Creates an instance of the RestClient * @constructor * @param {string} userAgent - userAgent for requests * @param {string} baseUrl - (Optional) If not specified, use full urls per request. If supplied and a function passes a relative url, it will be appended to this * @param {ifm.IRequestHandler[]} handlers - handlers are typically auth handlers (basic, bearer, ntlm supplied) * @param {ifm.IRequestOptions} requestOptions - options for each http requests (http proxy setting, socket timeout) */ constructor(userAgent, baseUrl, handlers, requestOptions) { this.client = new httpm.HttpClient(userAgent, handlers, requestOptions); if (baseUrl) { this._baseUrl = baseUrl; } } /** * Gets a resource from an endpoint * Be aware that not found returns a null. Other error conditions reject the promise * @param {string} requestUrl - fully qualified or relative url * @param {IRequestOptions} requestOptions - (optional) requestOptions object */ options(requestUrl, options) { return __awaiter(this, void 0, void 0, function* () { let url = util.getUrl(requestUrl, this._baseUrl); let res = yield this.client.options(url, this._headersFromOptions(options)); return this._processResponse(res, options); }); } /** * Gets a resource from an endpoint * Be aware that not found returns a null. Other error conditions reject the promise * @param {string} resource - fully qualified url or relative path * @param {IRequestOptions} requestOptions - (optional) requestOptions object */ get(resource, options) { return __awaiter(this, void 0, void 0, function* () { let url = util.getUrl(resource, this._baseUrl); let res = yield this.client.get(url, this._headersFromOptions(options)); return this._processResponse(res, options); }); } /** * Deletes a resource from an endpoint * Be aware that not found returns a null. Other error conditions reject the promise * @param {string} resource - fully qualified or relative url * @param {IRequestOptions} requestOptions - (optional) requestOptions object */ del(resource, options) { return __awaiter(this, void 0, void 0, function* () { let url = util.getUrl(resource, this._baseUrl); let res = yield this.client.del(url, this._headersFromOptions(options)); return this._processResponse(res, options); }); } /** * Creates resource(s) from an endpoint * T type of object returned. * Be aware that not found returns a null. Other error conditions reject the promise * @param {string} resource - fully qualified or relative url * @param {IRequestOptions} requestOptions - (optional) requestOptions object */ create(resource, resources, options) { return __awaiter(this, void 0, void 0, function* () { let url = util.getUrl(resource, this._baseUrl); let headers = this._headersFromOptions(options, true); let data = JSON.stringify(resources, null, 2); let res = yield this.client.post(url, data, headers); return this._processResponse(res, options); }); } /** * Updates resource(s) from an endpoint * T type of object returned. * Be aware that not found returns a null. Other error conditions reject the promise * @param {string} resource - fully qualified or relative url * @param {IRequestOptions} requestOptions - (optional) requestOptions object */ update(resource, resources, options) { return __awaiter(this, void 0, void 0, function* () { let url = util.getUrl(resource, this._baseUrl); let headers = this._headersFromOptions(options, true); let data = JSON.stringify(resources, null, 2); let res = yield this.client.patch(url, data, headers); return this._processResponse(res, options); }); } /** * Replaces resource(s) from an endpoint * T type of object returned. * Be aware that not found returns a null. Other error conditions reject the promise * @param {string} resource - fully qualified or relative url * @param {IRequestOptions} requestOptions - (optional) requestOptions object */ replace(resource, resources, options) { return __awaiter(this, void 0, void 0, function* () { let url = util.getUrl(resource, this._baseUrl); let headers = this._headersFromOptions(options, true); let data = JSON.stringify(resources, null, 2); let res = yield this.client.put(url, data, headers); return this._processResponse(res, options); }); } uploadStream(verb, requestUrl, stream, options) { return __awaiter(this, void 0, void 0, function* () { let url = util.getUrl(requestUrl, this._baseUrl); let headers = this._headersFromOptions(options, true); let res = yield this.client.sendStream(verb, url, stream, headers); return this._processResponse(res, options); }); } _headersFromOptions(options, contentType) { options = options || {}; let headers = options.additionalHeaders || {}; headers["Accept"] = options.acceptHeader || "application/json"; if (contentType) { let found = false; for (let header in headers) { if (header.toLowerCase() == "content-type") { found = true; } } if (!found) { headers["Content-Type"] = 'application/json; charset=utf-8'; } } return headers; } static dateTimeDeserializer(key, value) { if (typeof value === 'string') { let a = new Date(value); if (!isNaN(a.valueOf())) { return a; } } return value; } _processResponse(res, options) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { const statusCode = res.message.statusCode; const response = { statusCode: statusCode, result: null, headers: {} }; // not found leads to null obj returned if (statusCode == httpm.HttpCodes.NotFound) { resolve(response); } let obj; let contents; // get the result from the body try { contents = yield res.readBody(); if (contents && contents.length > 0) { if (options && options.deserializeDates) { obj = JSON.parse(contents, RestClient.dateTimeDeserializer); } else { obj = JSON.parse(contents); } if (options && options.responseProcessor) { response.result = options.responseProcessor(obj); } else { response.result = obj; } } response.headers = res.message.headers; } catch (err) { // Invalid resource (contents not json); leaving result obj null } // note that 3xx redirects are handled by the http layer. if (statusCode > 299) { let msg; // if exception/error in body, attempt to get better error if (obj && obj.message) { msg = obj.message; } else if (contents && contents.length > 0) { // it may be the case that the exception is in the body message as string msg = contents; } else { msg = "Failed request: (" + statusCode + ")"; } let err = new Error(msg); // attach statusCode and body obj (if available) to the error object err['statusCode'] = statusCode; if (response.result) { err['result'] = response.result; } reject(err); } else { resolve(response); } })); }); } } exports.RestClient = RestClient;