Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core-rest-pipeline] Allow specifying any status response to get stream #18492

Merged
merged 4 commits into from
Nov 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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