"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 qs = require("qs"); | |
const url = require("url"); | |
const path = require("path"); | |
const zlib = require("zlib"); | |
/** | |
* creates an url from a request url and optional base url (http://server:8080) | |
* @param {string} resource - a fully qualified url or relative path | |
* @param {string} baseUrl - an optional baseUrl (http://server:8080) | |
* @param {IRequestOptions} options - an optional options object, could include QueryParameters e.g. | |
* @return {string} - resultant url | |
*/ | |
function getUrl(resource, baseUrl, queryParams) { | |
const pathApi = path.posix || path; | |
let requestUrl = ''; | |
if (!baseUrl) { | |
requestUrl = resource; | |
} | |
else if (!resource) { | |
requestUrl = baseUrl; | |
} | |
else { | |
const base = url.parse(baseUrl); | |
const resultantUrl = url.parse(resource); | |
// resource (specific per request) elements take priority | |
resultantUrl.protocol = resultantUrl.protocol || base.protocol; | |
resultantUrl.auth = resultantUrl.auth || base.auth; | |
resultantUrl.host = resultantUrl.host || base.host; | |
resultantUrl.pathname = pathApi.resolve(base.pathname, resultantUrl.pathname); | |
if (!resultantUrl.pathname.endsWith('/') && resource.endsWith('/')) { | |
resultantUrl.pathname += '/'; | |
} | |
requestUrl = url.format(resultantUrl); | |
} | |
return queryParams ? | |
getUrlWithParsedQueryParams(requestUrl, queryParams) : | |
requestUrl; | |
} | |
exports.getUrl = getUrl; | |
/** | |
* | |
* @param {string} requestUrl | |
* @param {IRequestQueryParams} queryParams | |
* @return {string} - Request's URL with Query Parameters appended/parsed. | |
*/ | |
function getUrlWithParsedQueryParams(requestUrl, queryParams) { | |
const url = requestUrl.replace(/\?$/g, ''); // Clean any extra end-of-string "?" character | |
const parsedQueryParams = qs.stringify(queryParams.params, buildParamsStringifyOptions(queryParams)); | |
return `${url}${parsedQueryParams}`; | |
} | |
/** | |
* Build options for QueryParams Stringifying. | |
* | |
* @param {IRequestQueryParams} queryParams | |
* @return {object} | |
*/ | |
function buildParamsStringifyOptions(queryParams) { | |
let options = { | |
addQueryPrefix: true, | |
delimiter: (queryParams.options || {}).separator || '&', | |
allowDots: (queryParams.options || {}).shouldAllowDots || false, | |
arrayFormat: (queryParams.options || {}).arrayFormat || 'repeat', | |
encodeValuesOnly: (queryParams.options || {}).shouldOnlyEncodeValues || true | |
}; | |
return options; | |
} | |
/** | |
* Decompress/Decode gzip encoded JSON | |
* Using Node.js built-in zlib module | |
* | |
* @param {Buffer} buffer | |
* @param {string} charset? - optional; defaults to 'utf-8' | |
* @return {Promise<string>} | |
*/ | |
function decompressGzippedContent(buffer, charset) { | |
return __awaiter(this, void 0, void 0, function* () { | |
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { | |
zlib.gunzip(buffer, function (error, buffer) { | |
if (error) { | |
reject(error); | |
} | |
resolve(buffer.toString(charset || 'utf-8')); | |
}); | |
})); | |
}); | |
} | |
exports.decompressGzippedContent = decompressGzippedContent; | |
/** | |
* Obtain Response's Content Charset. | |
* Through inspecting `content-type` response header. | |
* It Returns 'utf-8' if NO charset specified/matched. | |
* | |
* @param {IHttpClientResponse} response | |
* @return {string} - Content Encoding Charset; Default=utf-8 | |
*/ | |
function obtainContentCharset(response) { | |
// Find the charset, if specified. | |
// Search for the `charset=CHARSET` string, not including `;,\r\n` | |
// Example: content-type: 'application/json;charset=utf-8' | |
// |__ matches would be ['charset=utf-8', 'utf-8', index: 18, input: 'application/json; charset=utf-8'] | |
// |_____ matches[1] would have the charset :tada: , in our example it's utf-8 | |
// However, if the matches Array was empty or no charset found, 'utf-8' would be returned by default. | |
const nodeSupportedEncodings = ['ascii', 'utf8', 'utf16le', 'ucs2', 'base64', 'binary', 'hex']; | |
const contentType = response.message.headers['content-type'] || ''; | |
const matches = contentType.match(/charset=([^;,\r\n]+)/i); | |
return (matches && matches[1] && nodeSupportedEncodings.indexOf(matches[1]) != -1) ? matches[1] : 'utf-8'; | |
} | |
exports.obtainContentCharset = obtainContentCharset; |