{"version":3,"file":"FetchHttpClient.js","sourceRoot":"","sources":["../../src/FetchHttpClient.ts"],"names":[],"mappings":";AAAA,sDAAsD;AACtD,+GAA+G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAK/G,mCAA+D;AAC/D,2CAAqE;AACrE,qCAA8C;AAC9C,iCAAmC;AAEnC;IAAqC,mCAAU;IAO3C,yBAAmB,MAAe;QAAlC,YACI,iBAAO,SAsBV;QArBG,KAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QAErB,IAAI,OAAO,KAAK,KAAK,WAAW,EAAE;YAC9B,oFAAoF;YACpF,gDAAgD;YAChD,IAAM,WAAW,GAAG,OAAO,mBAAmB,KAAK,UAAU,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC;YAElG,iHAAiH;YACjH,KAAI,CAAC,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;YACzD,KAAI,CAAC,SAAS,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;YAE3C,qEAAqE;YACrE,2FAA2F;YAC3F,KAAI,CAAC,SAAS,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC,KAAI,CAAC,SAAS,EAAE,KAAI,CAAC,GAAG,CAAC,CAAC;YAEvE,gGAAgG;YAChG,KAAI,CAAC,mBAAmB,GAAG,WAAW,CAAC,kBAAkB,CAAC,CAAC;SAC9D;aAAM;YACH,KAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,KAAI,CAAC,mBAAmB,GAAG,eAAe,CAAC;SAC9C;;IACL,CAAC;IAED,kBAAkB;IACL,8BAAI,GAAjB,UAAkB,OAAoB;;;;;;;wBAClC,wDAAwD;wBACxD,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE;4BACpD,MAAM,IAAI,mBAAU,EAAE,CAAC;yBAC1B;wBAED,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;4BACjB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;yBACzC;wBACD,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;4BACd,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;yBACtC;wBAEK,eAAe,GAAG,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;wBAGvD,iDAAiD;wBACjD,IAAI,OAAO,CAAC,WAAW,EAAE;4BACrB,OAAO,CAAC,WAAW,CAAC,OAAO,GAAG;gCAC1B,eAAe,CAAC,KAAK,EAAE,CAAC;gCACxB,KAAK,GAAG,IAAI,mBAAU,EAAE,CAAC;4BAC7B,CAAC,CAAC;yBACL;wBAIG,SAAS,GAAQ,IAAI,CAAC;wBAC1B,IAAI,OAAO,CAAC,OAAO,EAAE;4BACX,SAAS,GAAG,OAAO,CAAC,OAAQ,CAAC;4BACnC,SAAS,GAAG,UAAU,CAAC;gCACnB,eAAe,CAAC,KAAK,EAAE,CAAC;gCACxB,KAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC,CAAC;gCAChE,KAAK,GAAG,IAAI,qBAAY,EAAE,CAAC;4BAC/B,CAAC,EAAE,SAAS,CAAC,CAAC;yBACjB;;;;wBAIc,qBAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAI,EAAE;gCAC1C,IAAI,EAAE,OAAO,CAAC,OAAQ;gCACtB,KAAK,EAAE,UAAU;gCACjB,WAAW,EAAE,OAAO,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa;gCACzE,OAAO,aACH,cAAc,EAAE,0BAA0B,EAC1C,kBAAkB,EAAE,gBAAgB,IACjC,OAAO,CAAC,OAAO,CACrB;gCACD,MAAM,EAAE,OAAO,CAAC,MAAO;gCACvB,IAAI,EAAE,MAAM;gCACZ,QAAQ,EAAE,QAAQ;gCAClB,MAAM,EAAE,eAAe,CAAC,MAAM;6BACjC,CAAC,EAAA;;wBAbF,QAAQ,GAAG,SAaT,CAAC;;;;wBAEH,IAAI,KAAK,EAAE;4BACP,MAAM,KAAK,CAAC;yBACf;wBACD,IAAI,CAAC,MAAM,CAAC,GAAG,CACX,kBAAQ,CAAC,OAAO,EAChB,8BAA4B,GAAC,MAAG,CACnC,CAAC;wBACF,MAAM,GAAC,CAAC;;wBAER,IAAI,SAAS,EAAE;4BACX,YAAY,CAAC,SAAS,CAAC,CAAC;yBAC3B;wBACD,IAAI,OAAO,CAAC,WAAW,EAAE;4BACrB,OAAO,CAAC,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;yBACtC;;;wBAGL,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE;4BACd,MAAM,IAAI,kBAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;yBAC7D;wBAEK,OAAO,GAAG,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;wBACnD,qBAAM,OAAO,EAAA;;wBAAvB,OAAO,GAAG,SAAa;wBAE7B,sBAAO,IAAI,yBAAY,CACnB,QAAQ,CAAC,MAAM,EACf,QAAQ,CAAC,UAAU,EACnB,OAAO,CACV,EAAC;;;;KACL;IAEM,yCAAe,GAAtB,UAAuB,GAAW;QAC9B,IAAI,OAAO,GAAW,EAAE,CAAC;QACzB,IAAI,gBAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE;YAC7B,8BAA8B;YAC9B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAtB,CAAsB,CAAC,CAAC;SAC9D;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IACL,sBAAC;AAAD,CAAC,AA7HD,CAAqC,uBAAU,GA6H9C;AA7HY,0CAAe;AA+H5B,4BAA4B,QAAkB,EAAE,YAAyC;IACrF,IAAI,OAAO,CAAC;IACZ,QAAQ,YAAY,EAAE;QAClB,KAAK,aAAa;YACd,OAAO,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM;QACV,KAAK,MAAM;YACP,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC1B,MAAM;QACV,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU,CAAC;QAChB,KAAK,MAAM;YACP,MAAM,IAAI,KAAK,CAAI,YAAY,uBAAoB,CAAC,CAAC;QACzD;YACI,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC1B,MAAM;KACb;IAED,OAAO,OAAO,CAAC;AACnB,CAAC","sourcesContent":["// Copyright (c) .NET Foundation. All rights reserved.\r\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\r\n\r\n// @ts-ignore: This will be removed from built files and is here to make the types available during dev work\r\nimport * as tough from \"@types/tough-cookie\";\r\n\r\nimport { AbortError, HttpError, TimeoutError } from \"./Errors\";\r\nimport { HttpClient, HttpRequest, HttpResponse } from \"./HttpClient\";\r\nimport { ILogger, LogLevel } from \"./ILogger\";\r\nimport { Platform } from \"./Utils\";\r\n\r\nexport class FetchHttpClient extends HttpClient {\r\n private readonly abortControllerType: { prototype: AbortController, new(): AbortController };\r\n private readonly fetchType: (input: RequestInfo, init?: RequestInit) => Promise;\r\n private readonly jar?: tough.CookieJar;\r\n\r\n private readonly logger: ILogger;\r\n\r\n public constructor(logger: ILogger) {\r\n super();\r\n this.logger = logger;\r\n\r\n if (typeof fetch === \"undefined\") {\r\n // In order to ignore the dynamic require in webpack builds we need to do this magic\r\n // @ts-ignore: TS doesn't know about these names\r\n const requireFunc = typeof __webpack_require__ === \"function\" ? __non_webpack_require__ : require;\r\n\r\n // Cookies aren't automatically handled in Node so we need to add a CookieJar to preserve cookies across requests\r\n this.jar = new (requireFunc(\"tough-cookie\")).CookieJar();\r\n this.fetchType = requireFunc(\"node-fetch\");\r\n\r\n // node-fetch doesn't have a nice API for getting and setting cookies\r\n // fetch-cookie will wrap a fetch implementation with a default CookieJar or a provided one\r\n this.fetchType = requireFunc(\"fetch-cookie\")(this.fetchType, this.jar);\r\n\r\n // Node needs EventListener methods on AbortController which our custom polyfill doesn't provide\r\n this.abortControllerType = requireFunc(\"abort-controller\");\r\n } else {\r\n this.fetchType = fetch.bind(self);\r\n this.abortControllerType = AbortController;\r\n }\r\n }\r\n\r\n /** @inheritDoc */\r\n public async send(request: HttpRequest): Promise {\r\n // Check that abort was not signaled before calling send\r\n if (request.abortSignal && request.abortSignal.aborted) {\r\n throw new AbortError();\r\n }\r\n\r\n if (!request.method) {\r\n throw new Error(\"No method defined.\");\r\n }\r\n if (!request.url) {\r\n throw new Error(\"No url defined.\");\r\n }\r\n\r\n const abortController = new this.abortControllerType();\r\n\r\n let error: any;\r\n // Hook our abortSignal into the abort controller\r\n if (request.abortSignal) {\r\n request.abortSignal.onabort = () => {\r\n abortController.abort();\r\n error = new AbortError();\r\n };\r\n }\r\n\r\n // If a timeout has been passed in, setup a timeout to call abort\r\n // Type needs to be any to fit window.setTimeout and NodeJS.setTimeout\r\n let timeoutId: any = null;\r\n if (request.timeout) {\r\n const msTimeout = request.timeout!;\r\n timeoutId = setTimeout(() => {\r\n abortController.abort();\r\n this.logger.log(LogLevel.Warning, `Timeout from HTTP request.`);\r\n error = new TimeoutError();\r\n }, msTimeout);\r\n }\r\n\r\n let response: Response;\r\n try {\r\n response = await this.fetchType(request.url!, {\r\n body: request.content!,\r\n cache: \"no-cache\",\r\n credentials: request.withCredentials === true ? \"include\" : \"same-origin\",\r\n headers: {\r\n \"Content-Type\": \"text/plain;charset=UTF-8\",\r\n \"X-Requested-With\": \"XMLHttpRequest\",\r\n ...request.headers,\r\n },\r\n method: request.method!,\r\n mode: \"cors\",\r\n redirect: \"manual\",\r\n signal: abortController.signal,\r\n });\r\n } catch (e) {\r\n if (error) {\r\n throw error;\r\n }\r\n this.logger.log(\r\n LogLevel.Warning,\r\n `Error from HTTP request. ${e}.`,\r\n );\r\n throw e;\r\n } finally {\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n if (request.abortSignal) {\r\n request.abortSignal.onabort = null;\r\n }\r\n }\r\n\r\n if (!response.ok) {\r\n throw new HttpError(response.statusText, response.status);\r\n }\r\n\r\n const content = deserializeContent(response, request.responseType);\r\n const payload = await content;\r\n\r\n return new HttpResponse(\r\n response.status,\r\n response.statusText,\r\n payload,\r\n );\r\n }\r\n\r\n public getCookieString(url: string): string {\r\n let cookies: string = \"\";\r\n if (Platform.isNode && this.jar) {\r\n // @ts-ignore: unused variable\r\n this.jar.getCookies(url, (e, c) => cookies = c.join(\"; \"));\r\n }\r\n return cookies;\r\n }\r\n}\r\n\r\nfunction deserializeContent(response: Response, responseType?: XMLHttpRequestResponseType): Promise {\r\n let content;\r\n switch (responseType) {\r\n case \"arraybuffer\":\r\n content = response.arrayBuffer();\r\n break;\r\n case \"text\":\r\n content = response.text();\r\n break;\r\n case \"blob\":\r\n case \"document\":\r\n case \"json\":\r\n throw new Error(`${responseType} is not supported.`);\r\n default:\r\n content = response.text();\r\n break;\r\n }\r\n\r\n return content;\r\n}\r\n"]}