Skip to content

Commit

Permalink
[core-rest-pipeline] Allow specifying any status response to get stre…
Browse files Browse the repository at this point in the history
…am (#18492)

* Add responseAsStream to PipelineRequest

* Use Number.POSITIVE_INFINITY to indicate that any status code should get raw response

* Remove unneeded property in client request and address comments

* Update changelog
  • Loading branch information
joheredi authored Nov 3, 2021
1 parent 416b79b commit d85d19a
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 9 deletions.
10 changes: 3 additions & 7 deletions sdk/core/core-rest-pipeline/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions sdk/core/core-rest-pipeline/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<number>;

Expand Down
6 changes: 5 additions & 1 deletion sdk/core/core-rest-pipeline/src/nodeHttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions sdk/core/core-rest-pipeline/src/pipelineRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class PipelineRequestImpl implements PipelineRequest {
public body?: RequestBodyType;
public formData?: FormDataMap;
public streamResponseStatusCodes?: Set<number>;

public proxySettings?: ProxySettings;
public disableKeepAlive: boolean;
public abortSignal?: AbortSignalLike;
Expand Down
7 changes: 6 additions & 1 deletion sdk/core/core-rest-pipeline/src/xhrHttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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<Blob>((resolve, reject) => {
xhr.addEventListener("load", () => {
resolve(xhr.response);
Expand Down
15 changes: 15 additions & 0 deletions sdk/core/core-rest-pipeline/test/browser/xhrHttpClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
15 changes: 15 additions & 0 deletions sdk/core/core-rest-pipeline/test/node/nodeHttpClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit d85d19a

Please sign in to comment.