diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index b40bee198199..905795ebfce5 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -14239,7 +14239,7 @@ packages: dev: false file:projects/core-rest-pipeline.tgz: - resolution: {integrity: sha512-yMZDpj7f7Wqn+tJ6Q6AUsd9ywFlTCn2lsuehnBCVFDXyV1LkgzK83XXX7W5tat7vLQIKGMHxmdIXKWBxME5ovw==, tarball: file:projects/core-rest-pipeline.tgz} + resolution: {integrity: sha512-huJBLY2W+bEheXWtuUHMoAr+0WW/dRCMhyHZPFeL5FnLL7iSqBscZZHVCMkdyFOnBr1qlavfGgx79kHgaBjAMg==, tarball: file:projects/core-rest-pipeline.tgz} name: '@rush-temp/core-rest-pipeline' version: 0.0.0 dependencies: @@ -14247,11 +14247,13 @@ packages: '@microsoft/api-extractor': 7.19.4 '@opentelemetry/api': 1.0.4 '@types/chai': 4.3.0 + '@types/chai-as-promised': 7.1.5 '@types/mocha': 7.0.2 '@types/node': 12.20.46 '@types/sinon': 9.0.11 '@types/uuid': 8.3.4 chai: 4.3.6 + chai-as-promised: 7.1.1_chai@4.3.6 cross-env: 7.0.3 downlevel-dts: 0.8.0 eslint: 7.32.0 @@ -14273,6 +14275,7 @@ packages: mocha: 7.2.0 mocha-junit-reporter: 2.0.2_mocha@7.2.0 prettier: 2.5.1 + puppeteer: 13.5.1 rimraf: 3.0.2 sinon: 9.2.4 source-map-support: 0.5.21 @@ -14283,6 +14286,7 @@ packages: transitivePeerDependencies: - bufferutil - debug + - encoding - supports-color - utf-8-validate dev: false diff --git a/sdk/core/core-rest-pipeline/CHANGELOG.md b/sdk/core/core-rest-pipeline/CHANGELOG.md index 6c2e727feabf..d5ac5efac327 100644 --- a/sdk/core/core-rest-pipeline/CHANGELOG.md +++ b/sdk/core/core-rest-pipeline/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bugs Fixed +- [Bug #20778](https://github.com/Azure/azure-sdk-for-js/pull/20778) Customers can provide abort signals in the options bags for the client libraries but they were not being checked when requests were being retried. The issue is fixed in [#20781](https://github.com/Azure/azure-sdk-for-js/pull/20781). + ### Other Changes - Changed the default number of retries from 10 to 3. diff --git a/sdk/core/core-rest-pipeline/package.json b/sdk/core/core-rest-pipeline/package.json index 28c12cacd1fd..48f4e43d8c2b 100644 --- a/sdk/core/core-rest-pipeline/package.json +++ b/sdk/core/core-rest-pipeline/package.json @@ -101,11 +101,13 @@ "@microsoft/api-extractor": "^7.18.11", "@opentelemetry/api": "^1.0.1", "@types/chai": "^4.1.6", + "@types/chai-as-promised": "^7.1.0", "@types/mocha": "^7.0.2", "@types/node": "^12.0.0", "@types/sinon": "^9.0.4", "@types/uuid": "^8.0.0", "chai": "^4.2.0", + "chai-as-promised": "^7.1.1", "downlevel-dts": "^0.8.0", "cross-env": "^7.0.2", "eslint": "^7.15.0", @@ -124,6 +126,7 @@ "mocha-junit-reporter": "^2.0.0", "mocha": "^7.1.1", "prettier": "^2.5.1", + "puppeteer": "^13.5.1", "rimraf": "^3.0.0", "sinon": "^9.0.2", "source-map-support": "^0.5.9", diff --git a/sdk/core/core-rest-pipeline/src/createPipelineFromOptions.ts b/sdk/core/core-rest-pipeline/src/createPipelineFromOptions.ts index fe7c52942757..8ab67fd8dd14 100644 --- a/sdk/core/core-rest-pipeline/src/createPipelineFromOptions.ts +++ b/sdk/core/core-rest-pipeline/src/createPipelineFromOptions.ts @@ -6,12 +6,12 @@ import { PipelineRetryOptions } from "./interfaces"; import { Pipeline, createEmptyPipeline } from "./pipeline"; import { decompressResponsePolicy } from "./policies/decompressResponsePolicy"; import { formDataPolicy } from "./policies/formDataPolicy"; -import { logPolicy, LogPolicyOptions } from "./policies/logPolicy"; +import { LogPolicyOptions, logPolicy } from "./policies/logPolicy"; import { proxyPolicy } from "./policies/proxyPolicy"; -import { redirectPolicy, RedirectPolicyOptions } from "./policies/redirectPolicy"; +import { RedirectPolicyOptions, redirectPolicy } from "./policies/redirectPolicy"; import { setClientRequestIdPolicy } from "./policies/setClientRequestIdPolicy"; import { tracingPolicy } from "./policies/tracingPolicy"; -import { userAgentPolicy, UserAgentPolicyOptions } from "./policies/userAgentPolicy"; +import { UserAgentPolicyOptions, userAgentPolicy } from "./policies/userAgentPolicy"; import { defaultRetryPolicy } from "./policies/defaultRetryPolicy"; import { isNode } from "./util/helpers"; diff --git a/sdk/core/core-rest-pipeline/src/nodeHttpClient.ts b/sdk/core/core-rest-pipeline/src/nodeHttpClient.ts index c923a0b3abfb..36cb32b860a4 100644 --- a/sdk/core/core-rest-pipeline/src/nodeHttpClient.ts +++ b/sdk/core/core-rest-pipeline/src/nodeHttpClient.ts @@ -8,11 +8,11 @@ import { Transform } from "stream"; import { AbortController, AbortError } from "@azure/abort-controller"; import { HttpClient, + HttpHeaders, PipelineRequest, PipelineResponse, - TransferProgressEvent, - HttpHeaders, RequestBodyType, + TransferProgressEvent, } from "./interfaces"; import { createHttpHeaders } from "./httpHeaders"; import { RestError } from "./restError"; diff --git a/sdk/core/core-rest-pipeline/src/pipeline.ts b/sdk/core/core-rest-pipeline/src/pipeline.ts index 8789c7a3ea6b..717d13b7aa92 100644 --- a/sdk/core/core-rest-pipeline/src/pipeline.ts +++ b/sdk/core/core-rest-pipeline/src/pipeline.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineRequest, PipelineResponse, HttpClient, SendRequest } from "./interfaces"; +import { HttpClient, PipelineRequest, PipelineResponse, SendRequest } from "./interfaces"; /** * Policies are executed in phases. diff --git a/sdk/core/core-rest-pipeline/src/pipelineRequest.ts b/sdk/core/core-rest-pipeline/src/pipelineRequest.ts index 8af9fa0fc43b..9cdd6062eeb4 100644 --- a/sdk/core/core-rest-pipeline/src/pipelineRequest.ts +++ b/sdk/core/core-rest-pipeline/src/pipelineRequest.ts @@ -2,13 +2,13 @@ // Licensed under the MIT license. import { - PipelineRequest, - TransferProgressEvent, - RequestBodyType, - HttpMethods, - HttpHeaders, FormDataMap, + HttpHeaders, + HttpMethods, + PipelineRequest, ProxySettings, + RequestBodyType, + TransferProgressEvent, } from "./interfaces"; import { createHttpHeaders } from "./httpHeaders"; import { AbortSignalLike } from "@azure/abort-controller"; diff --git a/sdk/core/core-rest-pipeline/src/policies/bearerTokenAuthenticationPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/bearerTokenAuthenticationPolicy.ts index 4e92a244a1d3..d519af1059ca 100644 --- a/sdk/core/core-rest-pipeline/src/policies/bearerTokenAuthenticationPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/bearerTokenAuthenticationPolicy.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { TokenCredential, GetTokenOptions, AccessToken } from "@azure/core-auth"; +import { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; import { AzureLogger } from "@azure/logger"; -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; import { createTokenCycler } from "../util/tokenCycler"; diff --git a/sdk/core/core-rest-pipeline/src/policies/decompressResponsePolicy.ts b/sdk/core/core-rest-pipeline/src/policies/decompressResponsePolicy.ts index de8b6b1827dc..f52a2d2fdcb2 100644 --- a/sdk/core/core-rest-pipeline/src/policies/decompressResponsePolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/decompressResponsePolicy.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; /** diff --git a/sdk/core/core-rest-pipeline/src/policies/formDataPolicy.browser.ts b/sdk/core/core-rest-pipeline/src/policies/formDataPolicy.browser.ts index 6b4035daa4a4..b8920bf9cbf5 100644 --- a/sdk/core/core-rest-pipeline/src/policies/formDataPolicy.browser.ts +++ b/sdk/core/core-rest-pipeline/src/policies/formDataPolicy.browser.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; /** diff --git a/sdk/core/core-rest-pipeline/src/policies/formDataPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/formDataPolicy.ts index d31ec842a44a..208bdecc28f2 100644 --- a/sdk/core/core-rest-pipeline/src/policies/formDataPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/formDataPolicy.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import FormData from "form-data"; -import { PipelineResponse, PipelineRequest, SendRequest, FormDataMap } from "../interfaces"; +import { FormDataMap, PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; /** diff --git a/sdk/core/core-rest-pipeline/src/policies/logPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/logPolicy.ts index 8c6a52e591b3..2dacedf0aac5 100644 --- a/sdk/core/core-rest-pipeline/src/policies/logPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/logPolicy.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import { Debugger } from "@azure/logger"; -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; import { logger as coreLogger } from "../log"; import { Sanitizer } from "../util/sanitizer"; diff --git a/sdk/core/core-rest-pipeline/src/policies/ndJsonPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/ndJsonPolicy.ts index d165259fbf7d..04d035c93189 100644 --- a/sdk/core/core-rest-pipeline/src/policies/ndJsonPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/ndJsonPolicy.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; /** diff --git a/sdk/core/core-rest-pipeline/src/policies/proxyPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/proxyPolicy.ts index 4c9b6f3ebda5..c57da1dde1da 100644 --- a/sdk/core/core-rest-pipeline/src/policies/proxyPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/proxyPolicy.ts @@ -6,11 +6,11 @@ import * as https from "https"; import { HttpsProxyAgent, HttpsProxyAgentOptions } from "https-proxy-agent"; import { HttpProxyAgent, HttpProxyAgentOptions } from "http-proxy-agent"; import { - PipelineResponse, + HttpHeaders, PipelineRequest, - SendRequest, + PipelineResponse, ProxySettings, - HttpHeaders, + SendRequest, } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; import { URL } from "../util/url"; diff --git a/sdk/core/core-rest-pipeline/src/policies/redirectPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/redirectPolicy.ts index 6528f5e924a8..eda9ff5c5a0f 100644 --- a/sdk/core/core-rest-pipeline/src/policies/redirectPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/redirectPolicy.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; import { URL } from "../util/url"; diff --git a/sdk/core/core-rest-pipeline/src/policies/retryPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/retryPolicy.ts index bfef18d00007..58bbb3b84422 100644 --- a/sdk/core/core-rest-pipeline/src/policies/retryPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/retryPolicy.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; import { delay } from "../util/helpers"; import { createClientLogger } from "@azure/logger"; @@ -113,7 +113,7 @@ export function retryPolicy( strategyLogger.info( `Retry ${retryCount}: Retry strategy ${strategy.name} retries after ${retryAfterInMs}` ); - await delay(retryAfterInMs); + await delay(retryAfterInMs, undefined, { abortSignal: request.abortSignal }); continue retryRequest; } diff --git a/sdk/core/core-rest-pipeline/src/policies/setClientRequestIdPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/setClientRequestIdPolicy.ts index d7a085ca96dc..564634d77e6c 100644 --- a/sdk/core/core-rest-pipeline/src/policies/setClientRequestIdPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/setClientRequestIdPolicy.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; /** diff --git a/sdk/core/core-rest-pipeline/src/policies/tracingPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/tracingPolicy.ts index d4735097b9e2..947bf1baec6d 100644 --- a/sdk/core/core-rest-pipeline/src/policies/tracingPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/tracingPolicy.ts @@ -2,15 +2,15 @@ // Licensed under the MIT license. import { - getTraceParentHeader, - createSpanFunction, - SpanStatusCode, - isSpanContextValid, Span, SpanOptions, + SpanStatusCode, + createSpanFunction, + getTraceParentHeader, + isSpanContextValid, } from "@azure/core-tracing"; import { SpanKind } from "@azure/core-tracing"; -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; import { getUserAgentValue } from "../util/userAgent"; import { logger } from "../log"; diff --git a/sdk/core/core-rest-pipeline/src/policies/userAgentPolicy.ts b/sdk/core/core-rest-pipeline/src/policies/userAgentPolicy.ts index 6ba172130edb..0ab8d10e1c55 100644 --- a/sdk/core/core-rest-pipeline/src/policies/userAgentPolicy.ts +++ b/sdk/core/core-rest-pipeline/src/policies/userAgentPolicy.ts @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineResponse, PipelineRequest, SendRequest } from "../interfaces"; +import { PipelineRequest, PipelineResponse, SendRequest } from "../interfaces"; import { PipelinePolicy } from "../pipeline"; -import { getUserAgentValue, getUserAgentHeaderName } from "../util/userAgent"; +import { getUserAgentHeaderName, getUserAgentValue } from "../util/userAgent"; const UserAgentHeaderName = getUserAgentHeaderName(); diff --git a/sdk/core/core-rest-pipeline/src/restError.ts b/sdk/core/core-rest-pipeline/src/restError.ts index a73ff39099a2..dcf8dc7159c8 100644 --- a/sdk/core/core-rest-pipeline/src/restError.ts +++ b/sdk/core/core-rest-pipeline/src/restError.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { PipelineResponse, PipelineRequest } from "./interfaces"; +import { PipelineRequest, PipelineResponse } from "./interfaces"; import { custom } from "./util/inspect"; import { Sanitizer } from "./util/sanitizer"; diff --git a/sdk/core/core-rest-pipeline/src/util/helpers.ts b/sdk/core/core-rest-pipeline/src/util/helpers.ts index adf8dff61422..e90247f1554c 100644 --- a/sdk/core/core-rest-pipeline/src/util/helpers.ts +++ b/sdk/core/core-rest-pipeline/src/util/helpers.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +import { AbortError, AbortSignalLike } from "@azure/abort-controller"; + /** * A constant that indicates whether the environment the code is running is Node.JS. * @internal @@ -8,15 +10,62 @@ export const isNode = typeof process !== "undefined" && Boolean(process.version) && Boolean(process.versions?.node); +const StandardAbortMessage = "The operation was aborted."; + /** - * A wrapper for setTimeout that resolves a promise after t milliseconds. - * @internal - * @param t - The number of milliseconds to be delayed. + * A wrapper for setTimeout that resolves a promise after delayInMs milliseconds. + * @param delayInMs - The number of milliseconds to be delayed. * @param value - The value to be resolved with after a timeout of t milliseconds. + * @param options - The options for delay - currently abort options + * - abortSignal - The abortSignal associated with containing operation. + * - abortErrorMsg - The abort error message associated with containing operation. * @returns Resolved promise */ -export function delay(t: number, value?: T): Promise { - return new Promise((resolve) => setTimeout(() => resolve(value), t)); +export function delay( + delayInMs: number, + value?: T, + options?: { + abortSignal?: AbortSignalLike; + abortErrorMsg?: string; + } +): Promise { + return new Promise((resolve, reject) => { + let timer: ReturnType | undefined = undefined; + let onAborted: (() => void) | undefined = undefined; + + const rejectOnAbort = (): void => { + return reject( + new AbortError(options?.abortErrorMsg ? options?.abortErrorMsg : StandardAbortMessage) + ); + }; + + const removeListeners = (): void => { + if (options?.abortSignal && onAborted) { + options.abortSignal.removeEventListener("abort", onAborted); + } + }; + + onAborted = (): void => { + if (timer) { + clearTimeout(timer); + } + removeListeners(); + return rejectOnAbort(); + }; + + if (options?.abortSignal && options.abortSignal.aborted) { + return rejectOnAbort(); + } + + timer = setTimeout(() => { + removeListeners(); + resolve(value); + }, delayInMs); + + if (options?.abortSignal) { + options.abortSignal.addEventListener("abort", onAborted); + } + }); } /** diff --git a/sdk/core/core-rest-pipeline/src/util/sanitizer.ts b/sdk/core/core-rest-pipeline/src/util/sanitizer.ts index 8a19c9368b81..ef8ae936f314 100644 --- a/sdk/core/core-rest-pipeline/src/util/sanitizer.ts +++ b/sdk/core/core-rest-pipeline/src/util/sanitizer.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { isObject, UnknownObject } from "./helpers"; +import { UnknownObject, isObject } from "./helpers"; import { URL } from "./url"; /** diff --git a/sdk/core/core-rest-pipeline/src/util/userAgent.ts b/sdk/core/core-rest-pipeline/src/util/userAgent.ts index 040819453a60..cffde1885d94 100644 --- a/sdk/core/core-rest-pipeline/src/util/userAgent.ts +++ b/sdk/core/core-rest-pipeline/src/util/userAgent.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { setPlatformSpecificData, getHeaderName } from "./userAgentPlatform"; +import { getHeaderName, setPlatformSpecificData } from "./userAgentPlatform"; import { SDK_VERSION } from "../constants"; function getUserAgentString(telemetryInfo: Map): string { diff --git a/sdk/core/core-rest-pipeline/test/bearerTokenAuthenticationPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/bearerTokenAuthenticationPolicy.spec.ts index a56bd3d75abf..daf7cc96191a 100644 --- a/sdk/core/core-rest-pipeline/test/bearerTokenAuthenticationPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/bearerTokenAuthenticationPolicy.spec.ts @@ -3,14 +3,14 @@ import { assert } from "chai"; import * as sinon from "sinon"; -import { TokenCredential, AccessToken } from "@azure/core-auth"; +import { AccessToken, TokenCredential } from "@azure/core-auth"; import { PipelinePolicy, - createPipelineRequest, - createHttpHeaders, PipelineResponse, - bearerTokenAuthenticationPolicy, SendRequest, + bearerTokenAuthenticationPolicy, + createHttpHeaders, + createPipelineRequest, } from "../src"; import { DEFAULT_CYCLER_OPTIONS } from "../src/util/tokenCycler"; diff --git a/sdk/core/core-rest-pipeline/test/browser/formDataPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/browser/formDataPolicy.spec.ts index 6cf4d68374bb..7cea8007f46e 100644 --- a/sdk/core/core-rest-pipeline/test/browser/formDataPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/browser/formDataPolicy.spec.ts @@ -4,10 +4,10 @@ import { assert } from "chai"; import * as sinon from "sinon"; import { - createPipelineRequest, - SendRequest, PipelineResponse, + SendRequest, createHttpHeaders, + createPipelineRequest, formDataPolicy, } from "../../src"; diff --git a/sdk/core/core-rest-pipeline/test/defaultRetryPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/defaultRetryPolicy.spec.ts index 78513bd3e6e9..b502120bf47d 100644 --- a/sdk/core/core-rest-pipeline/test/defaultRetryPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/defaultRetryPolicy.spec.ts @@ -3,7 +3,7 @@ import { assert } from "chai"; import * as sinon from "sinon"; -import { createPipelineRequest, SendRequest, RestError, defaultRetryPolicy } from "../src"; +import { RestError, SendRequest, createPipelineRequest, defaultRetryPolicy } from "../src"; import { DEFAULT_RETRY_POLICY_COUNT } from "../src/constants"; describe("defaultRetryPolicy", function () { diff --git a/sdk/core/core-rest-pipeline/test/ndJsonPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/ndJsonPolicy.spec.ts index 5ddf4d53a913..de5059561630 100644 --- a/sdk/core/core-rest-pipeline/test/ndJsonPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/ndJsonPolicy.spec.ts @@ -4,10 +4,10 @@ import { assert } from "chai"; import * as sinon from "sinon"; import { - createPipelineRequest, - SendRequest, PipelineResponse, + SendRequest, createHttpHeaders, + createPipelineRequest, ndJsonPolicy, } from "../src"; diff --git a/sdk/core/core-rest-pipeline/test/node/bearerTokenAuthenticationPolicyChallenge.spec.ts b/sdk/core/core-rest-pipeline/test/node/bearerTokenAuthenticationPolicyChallenge.spec.ts index 31478e69e7e3..6f37c0bfb7f4 100644 --- a/sdk/core/core-rest-pipeline/test/node/bearerTokenAuthenticationPolicyChallenge.spec.ts +++ b/sdk/core/core-rest-pipeline/test/node/bearerTokenAuthenticationPolicyChallenge.spec.ts @@ -5,13 +5,13 @@ import { assert } from "chai"; import * as sinon from "sinon"; import { AccessToken, GetTokenOptions, TokenCredential } from "@azure/core-auth"; import { - bearerTokenAuthenticationPolicy, AuthorizeRequestOnChallengeOptions, + HttpClient, + PipelineResponse, + bearerTokenAuthenticationPolicy, createEmptyPipeline, createHttpHeaders, createPipelineRequest, - HttpClient, - PipelineResponse, } from "../../src"; import { TextDecoder } from "util"; diff --git a/sdk/core/core-rest-pipeline/test/node/decompressResponsePolicy.ts b/sdk/core/core-rest-pipeline/test/node/decompressResponsePolicy.ts index 46f4ce8ba5f7..587bb3203278 100644 --- a/sdk/core/core-rest-pipeline/test/node/decompressResponsePolicy.ts +++ b/sdk/core/core-rest-pipeline/test/node/decompressResponsePolicy.ts @@ -3,7 +3,7 @@ import { assert } from "chai"; import * as sinon from "sinon"; -import { decompressResponsePolicy, createPipelineRequest, SendRequest } from "../../src"; +import { SendRequest, createPipelineRequest, decompressResponsePolicy } from "../../src"; describe("decompressResponsePolicy (node)", function () { it("Sets the expected flag on the request", function () { diff --git a/sdk/core/core-rest-pipeline/test/node/formDataPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/node/formDataPolicy.spec.ts index 55862e1545e4..197fc066a81b 100644 --- a/sdk/core/core-rest-pipeline/test/node/formDataPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/node/formDataPolicy.spec.ts @@ -4,10 +4,10 @@ import { assert } from "chai"; import * as sinon from "sinon"; import { - createPipelineRequest, - SendRequest, PipelineResponse, + SendRequest, createHttpHeaders, + createPipelineRequest, formDataPolicy, } from "../../src"; diff --git a/sdk/core/core-rest-pipeline/test/node/nodeHttpClient.spec.ts b/sdk/core/core-rest-pipeline/test/node/nodeHttpClient.spec.ts index f475cf0a36b6..3085d15b08f0 100644 --- a/sdk/core/core-rest-pipeline/test/node/nodeHttpClient.spec.ts +++ b/sdk/core/core-rest-pipeline/test/node/nodeHttpClient.spec.ts @@ -4,7 +4,7 @@ import { assert } from "chai"; import * as sinon from "sinon"; import { PassThrough } from "stream"; -import { IncomingMessage, ClientRequest, IncomingHttpHeaders } from "http"; +import { ClientRequest, IncomingHttpHeaders, IncomingMessage } from "http"; import * as https from "https"; import * as http from "http"; import { AbortController } from "@azure/abort-controller"; diff --git a/sdk/core/core-rest-pipeline/test/node/proxyPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/node/proxyPolicy.spec.ts index 8b80d61a60ff..71390e1b9da6 100644 --- a/sdk/core/core-rest-pipeline/test/node/proxyPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/node/proxyPolicy.spec.ts @@ -4,17 +4,17 @@ import { assert } from "chai"; import * as sinon from "sinon"; import { - proxyPolicy, - createPipelineRequest, - SendRequest, ProxySettings, - getDefaultProxySettings, + SendRequest, createHttpHeaders, + createPipelineRequest, + getDefaultProxySettings, + proxyPolicy, } from "../../src"; import { + getProxyAgentOptions, globalNoProxyList, loadNoProxy, - getProxyAgentOptions, } from "../../src/policies/proxyPolicy"; describe("proxyPolicy (node)", function () { diff --git a/sdk/core/core-rest-pipeline/test/pipeline.spec.ts b/sdk/core/core-rest-pipeline/test/pipeline.spec.ts index 3bd003b076f8..bcf5976836d6 100644 --- a/sdk/core/core-rest-pipeline/test/pipeline.spec.ts +++ b/sdk/core/core-rest-pipeline/test/pipeline.spec.ts @@ -3,12 +3,12 @@ import { assert } from "chai"; import { - createEmptyPipeline, - PipelinePolicy, HttpClient, - createPipelineRequest, + PipelinePolicy, + createEmptyPipeline, createHttpHeaders, createPipelineFromOptions, + createPipelineRequest, } from "../src"; describe("HttpsPipeline", function () { diff --git a/sdk/core/core-rest-pipeline/test/redirectPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/redirectPolicy.spec.ts index 53526c5f17e8..7372f8a4c076 100644 --- a/sdk/core/core-rest-pipeline/test/redirectPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/redirectPolicy.spec.ts @@ -4,7 +4,7 @@ import { assert } from "chai"; import { redirectPolicy } from "../src/policies/redirectPolicy"; import * as sinon from "sinon"; -import { createHttpHeaders, createPipelineRequest, PipelineResponse, SendRequest } from "../src"; +import { PipelineResponse, SendRequest, createHttpHeaders, createPipelineRequest } from "../src"; describe("RedirectPolicy", () => { it("should not follow redirect if no location header", async () => { diff --git a/sdk/core/core-rest-pipeline/test/retryPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/retryPolicy.spec.ts index 66e6f5368785..2d7850c1db8f 100644 --- a/sdk/core/core-rest-pipeline/test/retryPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/retryPolicy.spec.ts @@ -6,11 +6,11 @@ import { AbortController } from "@azure/abort-controller"; import { assert } from "chai"; import * as sinon from "sinon"; import { - createPipelineRequest, - SendRequest, PipelineResponse, - createHttpHeaders, RestError, + SendRequest, + createHttpHeaders, + createPipelineRequest, retryPolicy, } from "../src"; import { DEFAULT_RETRY_POLICY_COUNT } from "../src/constants"; diff --git a/sdk/core/core-rest-pipeline/test/systemErrorRetryPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/systemErrorRetryPolicy.spec.ts index 0110e8600c69..f577f26b9ad8 100644 --- a/sdk/core/core-rest-pipeline/test/systemErrorRetryPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/systemErrorRetryPolicy.spec.ts @@ -4,12 +4,12 @@ import { assert } from "chai"; import * as sinon from "sinon"; import { - createPipelineRequest, - SendRequest, PipelineResponse, + RestError, + SendRequest, createHttpHeaders, + createPipelineRequest, systemErrorRetryPolicy, - RestError, } from "../src"; import { DEFAULT_RETRY_POLICY_COUNT } from "../src/constants"; diff --git a/sdk/core/core-rest-pipeline/test/throttlingRetryPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/throttlingRetryPolicy.spec.ts index ec05ab62c4df..e3d8aa537504 100644 --- a/sdk/core/core-rest-pipeline/test/throttlingRetryPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/throttlingRetryPolicy.spec.ts @@ -1,16 +1,19 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { assert } from "chai"; +import { assert, use as chaiUse } from "chai"; +import chaiPromises from "chai-as-promised"; +chaiUse(chaiPromises); import { Context } from "mocha"; import * as sinon from "sinon"; import { - createPipelineRequest, - SendRequest, PipelineResponse, + SendRequest, createHttpHeaders, + createPipelineRequest, throttlingRetryPolicy, } from "../src"; +import { AbortController } from "@azure/abort-controller"; import { DEFAULT_RETRY_POLICY_COUNT } from "../src/constants"; describe("throttlingRetryPolicy", function () { @@ -216,4 +219,37 @@ describe("throttlingRetryPolicy", function () { clock.restore(); }); + + it("throttlingRetryPolicy should honor abort signal", async () => { + const request = createPipelineRequest({ + url: "https://bing.com", + abortSignal: AbortController.timeout(100), // test should end at 100ms + }); + const retryResponse: PipelineResponse = { + headers: createHttpHeaders({ + "Retry-After": "10000", // 10000 seconds - a large duration + }), + request, + status: 429, + }; + const successResponse: PipelineResponse = { + headers: createHttpHeaders(), + request, + status: 200, + }; + + const policy = throttlingRetryPolicy(); + const next = sinon.stub, ReturnType>(); + next.onFirstCall().resolves(retryResponse); + next.onSecondCall().resolves(successResponse); + + await assert.isRejected( + policy.sendRequest(request, next), + "The operation was aborted.", + "Unexpected error thrown" + ); + + assert.isTrue(next.calledOnce); + assert.isFalse(next.calledTwice); + }); }); diff --git a/sdk/core/core-rest-pipeline/test/tracingPolicy.spec.ts b/sdk/core/core-rest-pipeline/test/tracingPolicy.spec.ts index 8ecd7a7e3651..ca27794c59e2 100644 --- a/sdk/core/core-rest-pipeline/test/tracingPolicy.spec.ts +++ b/sdk/core/core-rest-pipeline/test/tracingPolicy.spec.ts @@ -4,26 +4,26 @@ import { assert } from "chai"; import * as sinon from "sinon"; import { - tracingPolicy, - createPipelineRequest, - SendRequest, PipelineResponse, - createHttpHeaders, RestError, + SendRequest, + createHttpHeaders, + createPipelineRequest, + tracingPolicy, } from "../src"; import { + SpanAttributeValue, + SpanAttributes, SpanContext, + SpanOptions, + SpanStatus, + SpanStatusCode, TraceFlags, TraceState, context, setSpan, - SpanStatus, - SpanStatusCode, - SpanAttributes, - SpanAttributeValue, - SpanOptions, } from "@azure/core-tracing"; -import { TracerProvider, Tracer, Span, trace } from "@opentelemetry/api"; +import { Span, Tracer, TracerProvider, trace } from "@opentelemetry/api"; export class MockSpan implements Span { private _endCalled = false;