diff --git a/sdk/core/core-rest-pipeline/CHANGELOG.md b/sdk/core/core-rest-pipeline/CHANGELOG.md index d1b5e4f640b6..924c3554d170 100644 --- a/sdk/core/core-rest-pipeline/CHANGELOG.md +++ b/sdk/core/core-rest-pipeline/CHANGELOG.md @@ -1,15 +1,11 @@ # Release History -## 1.3.2 (Unreleased) - -### Features Added - -### Breaking Changes - -### Bugs Fixed +## 1.3.2 (2021-11-4) ### Other Changes +- Allow specifying any status response to get a raw stream as response content. [#18492](https://github.com/Azure/azure-sdk-for-js/pull/18492) + ## 1.3.1 (2021-09-30) ### Bugs Fixed diff --git a/sdk/core/core-rest-pipeline/src/interfaces.ts b/sdk/core/core-rest-pipeline/src/interfaces.ts index 93e8a469a5df..ab27c078c687 100644 --- a/sdk/core/core-rest-pipeline/src/interfaces.ts +++ b/sdk/core/core-rest-pipeline/src/interfaces.ts @@ -138,6 +138,7 @@ export interface PipelineRequest { /** * A list of response status codes whose corresponding PipelineResponse body should be treated as a stream. + * When streamResponseStatusCodes contains the value Number.POSITIVE_INFINITY any status would be treated as a stream. */ streamResponseStatusCodes?: Set; diff --git a/sdk/core/core-rest-pipeline/src/nodeHttpClient.ts b/sdk/core/core-rest-pipeline/src/nodeHttpClient.ts index 60f22ffc3252..4e2346fa65ee 100644 --- a/sdk/core/core-rest-pipeline/src/nodeHttpClient.ts +++ b/sdk/core/core-rest-pipeline/src/nodeHttpClient.ts @@ -151,7 +151,11 @@ class NodeHttpClient implements HttpClient { responseStream = downloadReportStream; } - if (request.streamResponseStatusCodes?.has(response.status)) { + if ( + // Value of POSITIVE_INFINITY in streamResponseStatusCodes is considered as any status code + request.streamResponseStatusCodes?.has(Number.POSITIVE_INFINITY) || + request.streamResponseStatusCodes?.has(response.status) + ) { response.readableStreamBody = responseStream; } else { response.bodyAsText = await streamToText(responseStream); diff --git a/sdk/core/core-rest-pipeline/src/pipelineRequest.ts b/sdk/core/core-rest-pipeline/src/pipelineRequest.ts index e3364325c404..1828818f5f96 100644 --- a/sdk/core/core-rest-pipeline/src/pipelineRequest.ts +++ b/sdk/core/core-rest-pipeline/src/pipelineRequest.ts @@ -109,6 +109,7 @@ class PipelineRequestImpl implements PipelineRequest { public body?: RequestBodyType; public formData?: FormDataMap; public streamResponseStatusCodes?: Set; + public proxySettings?: ProxySettings; public disableKeepAlive: boolean; public abortSignal?: AbortSignalLike; diff --git a/sdk/core/core-rest-pipeline/src/xhrHttpClient.ts b/sdk/core/core-rest-pipeline/src/xhrHttpClient.ts index 7fdaee72c57e..090e948afa9b 100644 --- a/sdk/core/core-rest-pipeline/src/xhrHttpClient.ts +++ b/sdk/core/core-rest-pipeline/src/xhrHttpClient.ts @@ -67,6 +67,7 @@ class XhrHttpClient implements HttpClient { for (const [name, value] of request.headers) { xhr.setRequestHeader(name, value); } + xhr.responseType = request.streamResponseStatusCodes?.size ? "blob" : "text"; if (isReadableStream(request.body)) { @@ -105,7 +106,11 @@ function handleBlobResponse( xhr.addEventListener("readystatechange", () => { // Resolve as soon as headers are loaded if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) { - if (request.streamResponseStatusCodes?.has(xhr.status)) { + if ( + // Value of POSITIVE_INFINITY in streamResponseStatusCodes is considered as any status code + request.streamResponseStatusCodes?.has(Number.POSITIVE_INFINITY) || + request.streamResponseStatusCodes?.has(xhr.status) + ) { const blobBody = new Promise((resolve, reject) => { xhr.addEventListener("load", () => { resolve(xhr.response); diff --git a/sdk/core/core-rest-pipeline/test/browser/xhrHttpClient.spec.ts b/sdk/core/core-rest-pipeline/test/browser/xhrHttpClient.spec.ts index d57d8cc8aad7..6aa5f9be526a 100644 --- a/sdk/core/core-rest-pipeline/test/browser/xhrHttpClient.spec.ts +++ b/sdk/core/core-rest-pipeline/test/browser/xhrHttpClient.spec.ts @@ -153,6 +153,21 @@ describe("XhrHttpClient", function() { assert.ok(response.blobBody, "Expect streaming body"); }); + it("should stream response body on any status code", async function() { + const client = createDefaultHttpClient(); + const request = createPipelineRequest({ + url: "https://example.com", + streamResponseStatusCodes: new Set([Number.POSITIVE_INFINITY]) + }); + const promise = client.sendRequest(request); + assert.equal(requests.length, 1); + requests[0].respond(201, {}, "body"); + const response = await promise; + assert.strictEqual(response.status, 201); + assert.equal(response.bodyAsText, undefined); + assert.ok(response.blobBody, "Expect streaming body"); + }); + it("should not stream response body on non-matching status code", async function() { const client = createDefaultHttpClient(); const request = createPipelineRequest({ 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 7fcd4eb343b9..e44933a125d6 100644 --- a/sdk/core/core-rest-pipeline/test/node/nodeHttpClient.spec.ts +++ b/sdk/core/core-rest-pipeline/test/node/nodeHttpClient.spec.ts @@ -194,6 +194,21 @@ describe("NodeHttpClient", function() { assert.ok(response.readableStreamBody); }); + it("should stream response body on any status code", async function() { + const client = createDefaultHttpClient(); + const clientRequest = createRequest(); + stubbedHttpsRequest.returns(clientRequest); + const request = createPipelineRequest({ + url: "https://example.com", + streamResponseStatusCodes: new Set([Number.POSITIVE_INFINITY]) + }); + const promise = client.sendRequest(request); + stubbedHttpsRequest.yield(createResponse(201, "body")); + const response = await promise; + assert.equal(response.bodyAsText, undefined); + assert.ok(response.readableStreamBody); + }); + it("should not stream response body on non-matching status code", async function() { const client = createDefaultHttpClient(); const clientRequest = createRequest();