зеркало из https://github.com/Azure/ms-rest-js.git
Port redirect policy changes from azure-sdk-for-js
This commit is contained in:
Родитель
6281ac6a12
Коммит
c47191b425
|
@ -1,6 +1,8 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
## 2.3.1 - UNRELEASED
|
## 2.5.0 - UNRELEASED
|
||||||
|
|
||||||
- Add WebResource.redirectLimit: Limit the number of redirects followed for this request. If set to 0, redirects will not be followed.
|
- Add WebResource.redirectLimit: Limit the number of redirects followed for this request. If set to 0, redirects will not be followed.
|
||||||
|
- Port changes to redirect policy from [azure-sdk-for-js](https://github.com/Azure/azure-sdk-for-js/pull/11863/files]
|
||||||
|
|
||||||
## 2.4.0 - 2021-04-19
|
## 2.4.0 - 2021-04-19
|
||||||
|
|
||||||
|
|
|
@ -130,11 +130,6 @@ export abstract class FetchHttpClient implements HttpClient {
|
||||||
body = uploadReportStream;
|
body = uploadReportStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
const redirectInit: Partial<RequestInit> = {};
|
|
||||||
if (httpRequest.redirectLimit !== undefined) {
|
|
||||||
redirectInit.redirect = "manual";
|
|
||||||
}
|
|
||||||
|
|
||||||
const platformSpecificRequestInit: Partial<RequestInit> = await this.prepareRequest(
|
const platformSpecificRequestInit: Partial<RequestInit> = await this.prepareRequest(
|
||||||
httpRequest
|
httpRequest
|
||||||
);
|
);
|
||||||
|
@ -144,7 +139,7 @@ export abstract class FetchHttpClient implements HttpClient {
|
||||||
headers: httpRequest.headers.rawHeaders(),
|
headers: httpRequest.headers.rawHeaders(),
|
||||||
method: httpRequest.method,
|
method: httpRequest.method,
|
||||||
signal: abortController.signal,
|
signal: abortController.signal,
|
||||||
...redirectInit,
|
redirect: "manual",
|
||||||
...platformSpecificRequestInit,
|
...platformSpecificRequestInit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,27 @@ import {
|
||||||
RequestPolicyOptionsLike,
|
RequestPolicyOptionsLike,
|
||||||
} from "./requestPolicy";
|
} from "./requestPolicy";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for how redirect responses are handled.
|
||||||
|
*/
|
||||||
|
export interface RedirectOptions {
|
||||||
|
/*
|
||||||
|
* When true, redirect responses are followed. Defaults to true.
|
||||||
|
*/
|
||||||
|
handleRedirects: boolean;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of times the redirect URL will be tried before
|
||||||
|
* failing. Defaults to 20.
|
||||||
|
*/
|
||||||
|
maxRetries?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DefaultRedirectOptions: RedirectOptions = {
|
||||||
|
handleRedirects: true,
|
||||||
|
maxRetries: 20,
|
||||||
|
};
|
||||||
|
|
||||||
export function redirectPolicy(maximumRetries = 20): RequestPolicyFactory {
|
export function redirectPolicy(maximumRetries = 20): RequestPolicyFactory {
|
||||||
return {
|
return {
|
||||||
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
create: (nextPolicy: RequestPolicy, options: RequestPolicyOptionsLike) => {
|
||||||
|
@ -44,12 +65,14 @@ function handleRedirect(
|
||||||
const locationHeader = response.headers.get("location");
|
const locationHeader = response.headers.get("location");
|
||||||
if (
|
if (
|
||||||
locationHeader &&
|
locationHeader &&
|
||||||
(status === 300 || status === 302 || status === 307 || (status === 303 && request.method === "POST")) &&
|
(status === 300 ||
|
||||||
(
|
(status === 301 && ["GET", "HEAD"].includes(request.method)) ||
|
||||||
(request.redirectLimit !== undefined && currentRetries < request.redirectLimit)
|
(status === 302 && ["GET", "POST", "HEAD"].includes(request.method)) ||
|
||||||
||
|
(status === 303 && "POST" === request.method) ||
|
||||||
(request.redirectLimit === undefined && currentRetries < policy.maxRetries)
|
status === 307) &&
|
||||||
)) {
|
((request.redirectLimit !== undefined && currentRetries < request.redirectLimit) ||
|
||||||
|
(request.redirectLimit === undefined && currentRetries < policy.maxRetries))
|
||||||
|
) {
|
||||||
const builder = URLBuilder.parse(request.url);
|
const builder = URLBuilder.parse(request.url);
|
||||||
builder.setPath(locationHeader);
|
builder.setPath(locationHeader);
|
||||||
request.url = builder.toString();
|
request.url = builder.toString();
|
||||||
|
@ -57,8 +80,9 @@ function handleRedirect(
|
||||||
// POST request with Status code 302 and 303 should be converted into a
|
// POST request with Status code 302 and 303 should be converted into a
|
||||||
// redirected GET request if the redirect url is present in the location header
|
// redirected GET request if the redirect url is present in the location header
|
||||||
// reference: https://tools.ietf.org/html/rfc7231#page-57 && https://fetch.spec.whatwg.org/#http-redirect-fetch
|
// reference: https://tools.ietf.org/html/rfc7231#page-57 && https://fetch.spec.whatwg.org/#http-redirect-fetch
|
||||||
if (status === 302 || status === 303) {
|
if ((status === 302 || status === 303) && request.method === "POST") {
|
||||||
request.method = "GET";
|
request.method = "GET";
|
||||||
|
delete request.body;
|
||||||
}
|
}
|
||||||
|
|
||||||
return policy._nextPolicy
|
return policy._nextPolicy
|
||||||
|
@ -78,4 +102,3 @@ function recordRedirect(response: HttpOperationResponse, redirect: string): Http
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import {
|
||||||
getDefaultUserAgentHeaderName,
|
getDefaultUserAgentHeaderName,
|
||||||
getDefaultUserAgentValue,
|
getDefaultUserAgentValue,
|
||||||
} from "./policies/userAgentPolicy";
|
} from "./policies/userAgentPolicy";
|
||||||
import { redirectPolicy } from "./policies/redirectPolicy";
|
import { DefaultRedirectOptions, RedirectOptions, redirectPolicy } from "./policies/redirectPolicy";
|
||||||
import {
|
import {
|
||||||
RequestPolicy,
|
RequestPolicy,
|
||||||
RequestPolicyFactory,
|
RequestPolicyFactory,
|
||||||
|
@ -135,6 +135,10 @@ export interface ServiceClientOptions {
|
||||||
* Proxy settings which will be used for every HTTP request (Node.js only).
|
* Proxy settings which will be used for every HTTP request (Node.js only).
|
||||||
*/
|
*/
|
||||||
proxySettings?: ProxySettings;
|
proxySettings?: ProxySettings;
|
||||||
|
/**
|
||||||
|
* Options for how redirect responses are handled.
|
||||||
|
*/
|
||||||
|
redirectOptions?: RedirectOptions;
|
||||||
/**
|
/**
|
||||||
* HTTP and HTTPS agents which will be used for every HTTP request (Node.js only).
|
* HTTP and HTTPS agents which will be used for every HTTP request (Node.js only).
|
||||||
*/
|
*/
|
||||||
|
@ -581,7 +585,15 @@ function createDefaultRequestPolicyFactories(
|
||||||
if (userAgentHeaderName && userAgentHeaderValue) {
|
if (userAgentHeaderName && userAgentHeaderValue) {
|
||||||
factories.push(userAgentPolicy({ key: userAgentHeaderName, value: userAgentHeaderValue }));
|
factories.push(userAgentPolicy({ key: userAgentHeaderName, value: userAgentHeaderValue }));
|
||||||
}
|
}
|
||||||
factories.push(redirectPolicy());
|
|
||||||
|
const redirectOptions = {
|
||||||
|
...DefaultRedirectOptions,
|
||||||
|
...options.redirectOptions,
|
||||||
|
};
|
||||||
|
if (redirectOptions.handleRedirects) {
|
||||||
|
factories.push(redirectPolicy(redirectOptions.maxRetries));
|
||||||
|
}
|
||||||
|
|
||||||
factories.push(rpRegistrationPolicy(options.rpRegistrationRetryTimeout));
|
factories.push(rpRegistrationPolicy(options.rpRegistrationRetryTimeout));
|
||||||
|
|
||||||
if (!options.noRetryPolicy) {
|
if (!options.noRetryPolicy) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ export const Constants = {
|
||||||
* @const
|
* @const
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
msRestVersion: "2.4.0",
|
msRestVersion: "2.5.0",
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies HTTP.
|
* Specifies HTTP.
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"email": "azsdkteam@microsoft.com",
|
"email": "azsdkteam@microsoft.com",
|
||||||
"url": "https://github.com/Azure/ms-rest-js"
|
"url": "https://github.com/Azure/ms-rest-js"
|
||||||
},
|
},
|
||||||
"version": "2.4.0",
|
"version": "2.5.0",
|
||||||
"description": "Isomorphic client Runtime for Typescript/node.js/browser javascript client libraries generated using AutoRest",
|
"description": "Isomorphic client Runtime for Typescript/node.js/browser javascript client libraries generated using AutoRest",
|
||||||
"tags": [
|
"tags": [
|
||||||
"isomorphic",
|
"isomorphic",
|
||||||
|
|
|
@ -0,0 +1,274 @@
|
||||||
|
// Copyright (c) Microsoft Corporation.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
import { assert } from "chai";
|
||||||
|
import { RedirectPolicy } from "../../lib/policies/redirectPolicy";
|
||||||
|
import { WebResource } from "../../lib/webResource";
|
||||||
|
import { HttpOperationResponse } from "../../lib/httpOperationResponse";
|
||||||
|
import { HttpHeaders } from "../../lib/httpHeaders";
|
||||||
|
import { RequestPolicyOptions } from "../../lib/policies/requestPolicy";
|
||||||
|
|
||||||
|
describe("RedirectPolicy", () => {
|
||||||
|
it("should not follow redirect if no location header", async () => {
|
||||||
|
const responseCodes = [301];
|
||||||
|
const request = new WebResource("https://example.com", "GET");
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, 301);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not follow POST 301 redirect", async function () {
|
||||||
|
const expectedStatusCode = 301;
|
||||||
|
const responseCodes = [301];
|
||||||
|
const request = new WebResource("https://example.com", "POST");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should follow GET 301 redirect", async function () {
|
||||||
|
const expectedStatusCode = 200;
|
||||||
|
const responseCodes = [301];
|
||||||
|
const request = new WebResource("https://example.com", "GET");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should follow HEAD 301 redirect", async function () {
|
||||||
|
const expectedStatusCode = 200;
|
||||||
|
const responseCodes = [301];
|
||||||
|
const request = new WebResource("https://example.com", "HEAD");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should follow POST 302 redirect", async function () {
|
||||||
|
const expectedStatusCode = 200;
|
||||||
|
const responseCodes = [302];
|
||||||
|
const request = new WebResource("https://example.com", "POST");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should follow GET 302 redirect", async function () {
|
||||||
|
const expectedStatusCode = 200;
|
||||||
|
const responseCodes = [302];
|
||||||
|
const request = new WebResource("https://example.com", "GET");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should follow HEAD 302 redirect", async function () {
|
||||||
|
const expectedStatusCode = 200;
|
||||||
|
const responseCodes = [302];
|
||||||
|
const request = new WebResource("https://example.com", "HEAD");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should follow POST 303 redirect", async function () {
|
||||||
|
const expectedStatusCode = 200;
|
||||||
|
const responseCodes = [303];
|
||||||
|
const request = new WebResource("https://example.com", "POST");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
if (!responseCodes.length) {
|
||||||
|
assert.strictEqual(_requestToSend.method, "GET", "Expected second request to be GET");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not follow GET 303 redirect", async function () {
|
||||||
|
const expectedStatusCode = 303;
|
||||||
|
const responseCodes = [303];
|
||||||
|
const request = new WebResource("https://example.com", "GET");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should follow GET 307 redirect", async function () {
|
||||||
|
const expectedStatusCode = 200;
|
||||||
|
const responseCodes = [307];
|
||||||
|
const request = new WebResource("https://example.com", "GET");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should follow GET 300 redirect", async function () {
|
||||||
|
const expectedStatusCode = 200;
|
||||||
|
const responseCodes = [300];
|
||||||
|
const request = new WebResource("https://example.com", "GET");
|
||||||
|
const headers = [{ location: "https://example.com/new" }];
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders(headers.shift() || {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should only try maxretries", async function () {
|
||||||
|
const expectedStatusCode = 300;
|
||||||
|
const maxretries = 1;
|
||||||
|
const responseCodes = [300, 300, 200];
|
||||||
|
const request = new WebResource("https://example.com", "GET");
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
return Promise.resolve({
|
||||||
|
status: responseCodes.shift() || 200,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders({ location: "https://example.com/new" }),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions(), maxretries);
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should try to redirect 3 times by default", async function () {
|
||||||
|
const expectedStatusCode = 300;
|
||||||
|
let callCount = 0;
|
||||||
|
const request = new WebResource("https://example.com", "GET");
|
||||||
|
const nextPolicy = {
|
||||||
|
sendRequest: (_requestToSend: WebResource): Promise<HttpOperationResponse> => {
|
||||||
|
callCount++;
|
||||||
|
return Promise.resolve({
|
||||||
|
status: 300,
|
||||||
|
request: _requestToSend,
|
||||||
|
headers: new HttpHeaders({ location: "https://example.com/new" }),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const policy = new RedirectPolicy(nextPolicy, new RequestPolicyOptions());
|
||||||
|
const result = await policy.sendRequest(request);
|
||||||
|
|
||||||
|
assert.strictEqual(result.status, expectedStatusCode);
|
||||||
|
assert.strictEqual(callCount, 21);
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,7 +5,6 @@ import { expect } from "chai";
|
||||||
import sinon from "sinon";
|
import sinon from "sinon";
|
||||||
|
|
||||||
import { DefaultHttpClient } from "../lib/defaultHttpClient";
|
import { DefaultHttpClient } from "../lib/defaultHttpClient";
|
||||||
import { WebResource } from "../lib/webResource";
|
|
||||||
import { getHttpMock, HttpMockFacade } from "./mockHttp";
|
import { getHttpMock, HttpMockFacade } from "./mockHttp";
|
||||||
import { CommonResponse } from "../lib/fetchHttpClient";
|
import { CommonResponse } from "../lib/fetchHttpClient";
|
||||||
import { ServiceClient } from "../lib/serviceClient";
|
import { ServiceClient } from "../lib/serviceClient";
|
||||||
|
@ -16,13 +15,10 @@ import { redirectPolicy } from "../lib/policies/redirectPolicy";
|
||||||
const nodeIt = (isNode ? it : it.skip) as TestFunction;
|
const nodeIt = (isNode ? it : it.skip) as TestFunction;
|
||||||
|
|
||||||
describe("redirectLimit", function () {
|
describe("redirectLimit", function () {
|
||||||
|
|
||||||
let httpMock: HttpMockFacade;
|
let httpMock: HttpMockFacade;
|
||||||
let capturedRedirectInit: string | undefined;
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
httpMock = getHttpMock();
|
httpMock = getHttpMock();
|
||||||
httpMock.setup();
|
httpMock.setup();
|
||||||
capturedRedirectInit = undefined;
|
|
||||||
});
|
});
|
||||||
afterEach(() => httpMock.teardown());
|
afterEach(() => httpMock.teardown());
|
||||||
|
|
||||||
|
@ -31,7 +27,6 @@ describe("redirectLimit", function () {
|
||||||
const fetchMock = httpMock.getFetch();
|
const fetchMock = httpMock.getFetch();
|
||||||
if (fetchMock) {
|
if (fetchMock) {
|
||||||
sinon.stub(httpClient, "fetch").callsFake(async (input, init) => {
|
sinon.stub(httpClient, "fetch").callsFake(async (input, init) => {
|
||||||
capturedRedirectInit = init?.redirect;
|
|
||||||
const response = await fetchMock(input, init);
|
const response = await fetchMock(input, init);
|
||||||
return (response as unknown) as CommonResponse;
|
return (response as unknown) as CommonResponse;
|
||||||
});
|
});
|
||||||
|
@ -39,130 +34,125 @@ describe("redirectLimit", function () {
|
||||||
return httpClient;
|
return httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function executeRequestWithRedirectLimit(redirectLimit?: number) {
|
|
||||||
const resourceUrl = "/resource";
|
|
||||||
|
|
||||||
httpMock.get(resourceUrl, async () => {
|
|
||||||
return { status: 200 };
|
|
||||||
});
|
|
||||||
|
|
||||||
const httpClient = getMockedHttpClient();
|
|
||||||
const request = new WebResource().prepare({ url: resourceUrl, method: "GET", redirectLimit});
|
|
||||||
|
|
||||||
// Act
|
|
||||||
await httpClient.sendRequest(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeIt("should initiate fetch without overriding redirect when redirectLimit is undefined", async function () {
|
|
||||||
await executeRequestWithRedirectLimit(undefined);
|
|
||||||
|
|
||||||
expect(capturedRedirectInit).to.be.undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeIt("should initiate fetch with manual redirect when redirectLimit is 0", async function () {
|
|
||||||
await executeRequestWithRedirectLimit(0);
|
|
||||||
|
|
||||||
expect(capturedRedirectInit).to.equal("manual");
|
|
||||||
});
|
|
||||||
|
|
||||||
nodeIt("should initiate fetch with manual redirect when redirectLimit is greater than 0", async function () {
|
|
||||||
await executeRequestWithRedirectLimit(3);
|
|
||||||
|
|
||||||
expect(capturedRedirectInit).to.equal("manual");
|
|
||||||
});
|
|
||||||
|
|
||||||
const resourceUrl = "/resource";
|
const resourceUrl = "/resource";
|
||||||
const redirectedUrl_1 = "/redirected_1";
|
const redirectedUrl_1 = "/redirected_1";
|
||||||
const redirectedUrl_2 = "/redirected_2";
|
const redirectedUrl_2 = "/redirected_2";
|
||||||
|
|
||||||
function configureMockRedirectResponses() {
|
function configureMockRedirectResponses() {
|
||||||
httpMock.get(resourceUrl, async () => {
|
httpMock.get(resourceUrl, async () => {
|
||||||
return { status: 300, headers : {"location": redirectedUrl_1} };
|
return { status: 300, headers: { location: redirectedUrl_1 } };
|
||||||
});
|
});
|
||||||
httpMock.get(redirectedUrl_1, async () => {
|
httpMock.get(redirectedUrl_1, async () => {
|
||||||
return { status: 300, headers : {"location": redirectedUrl_2} };
|
return { status: 300, headers: { location: redirectedUrl_2 } };
|
||||||
});
|
});
|
||||||
httpMock.get(redirectedUrl_2, async () => {
|
httpMock.get(redirectedUrl_2, async () => {
|
||||||
return { status: 200 };
|
return { status: 200 };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeIt("of 20 should follow redirects and return last visited url in response.url", async function () {
|
nodeIt(
|
||||||
configureMockRedirectResponses();
|
"of 20 should follow redirects and return last visited url in response.url",
|
||||||
|
async function () {
|
||||||
|
configureMockRedirectResponses();
|
||||||
|
|
||||||
const client = new ServiceClient(undefined, {
|
const client = new ServiceClient(undefined, {
|
||||||
httpClient: getMockedHttpClient()
|
httpClient: getMockedHttpClient(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const response = await client.sendRequest({ url: resourceUrl, method: "GET", redirectLimit: 20});
|
const response = await client.sendRequest({
|
||||||
|
url: resourceUrl,
|
||||||
|
method: "GET",
|
||||||
|
redirectLimit: 20,
|
||||||
|
});
|
||||||
|
|
||||||
expect(response.status).to.equal(200);
|
expect(response.status).to.equal(200);
|
||||||
expect(response.redirected).to.be.true;
|
expect(response.redirected).to.be.true;
|
||||||
expect(response.url).to.equal(redirectedUrl_2);
|
expect(response.url).to.equal(redirectedUrl_2);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
nodeIt("of 0 should not follow redirects and should return last visited url in response.url", async function () {
|
nodeIt(
|
||||||
configureMockRedirectResponses();
|
"of 0 should not follow redirects and should return last visited url in response.url",
|
||||||
|
async function () {
|
||||||
|
configureMockRedirectResponses();
|
||||||
|
|
||||||
const client = new ServiceClient(undefined, {
|
const client = new ServiceClient(undefined, {
|
||||||
httpClient: getMockedHttpClient()
|
httpClient: getMockedHttpClient(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const response = await client.sendRequest({ url: resourceUrl, method: "GET", redirectLimit: 0});
|
const response = await client.sendRequest({
|
||||||
|
url: resourceUrl,
|
||||||
|
method: "GET",
|
||||||
|
redirectLimit: 0,
|
||||||
|
});
|
||||||
|
|
||||||
expect(response.status).to.equal(300);
|
expect(response.status).to.equal(300);
|
||||||
expect(response.headers.get("location")).to.equal(redirectedUrl_1);
|
expect(response.headers.get("location")).to.equal(redirectedUrl_1);
|
||||||
expect(response.redirected).to.be.false;
|
expect(response.redirected).to.be.false;
|
||||||
expect(response.url).to.equal(resourceUrl);
|
expect(response.url).to.equal(resourceUrl);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
nodeIt("of 1 should follow 1 redirect and return last visited url in response.url", async function () {
|
nodeIt(
|
||||||
configureMockRedirectResponses();
|
"of 1 should follow 1 redirect and return last visited url in response.url",
|
||||||
|
async function () {
|
||||||
|
configureMockRedirectResponses();
|
||||||
|
|
||||||
const client = new ServiceClient(undefined, {
|
const client = new ServiceClient(undefined, {
|
||||||
httpClient: getMockedHttpClient()
|
httpClient: getMockedHttpClient(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const response = await client.sendRequest({ url: resourceUrl, method: "GET", redirectLimit: 1});
|
const response = await client.sendRequest({
|
||||||
|
url: resourceUrl,
|
||||||
|
method: "GET",
|
||||||
|
redirectLimit: 1,
|
||||||
|
});
|
||||||
|
|
||||||
expect(response.status).to.equal(300);
|
expect(response.status).to.equal(300);
|
||||||
expect(response.headers.get("location")).to.equal(redirectedUrl_2);
|
expect(response.headers.get("location")).to.equal(redirectedUrl_2);
|
||||||
expect(response.redirected).to.be.true;
|
expect(response.redirected).to.be.true;
|
||||||
expect(response.url).to.equal(redirectedUrl_1);
|
expect(response.url).to.equal(redirectedUrl_1);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
nodeIt("of undefined should follow redirects and return last visited url in response.url", async function () {
|
nodeIt(
|
||||||
configureMockRedirectResponses();
|
"of undefined should follow redirects and return last visited url in response.url",
|
||||||
|
async function () {
|
||||||
|
configureMockRedirectResponses();
|
||||||
|
|
||||||
const client = new ServiceClient(undefined, {
|
const client = new ServiceClient(undefined, {
|
||||||
httpClient: getMockedHttpClient()
|
httpClient: getMockedHttpClient(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const response = await client.sendRequest({ url: resourceUrl, method: "GET" });
|
const response = await client.sendRequest({ url: resourceUrl, method: "GET" });
|
||||||
|
|
||||||
expect(response.status).to.equal(200);
|
expect(response.status).to.equal(200);
|
||||||
expect(response.redirected).to.be.true;
|
expect(response.redirected).to.be.true;
|
||||||
expect(response.url).to.equal(redirectedUrl_2);
|
expect(response.url).to.equal(redirectedUrl_2);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
nodeIt("of undefinded with policy limit of 1 should follow 1 redirect and return last visited url in response.url", async function () {
|
nodeIt(
|
||||||
configureMockRedirectResponses();
|
"of undefinded with policy limit of 1 should follow 1 redirect and return last visited url in response.url",
|
||||||
|
async function () {
|
||||||
|
configureMockRedirectResponses();
|
||||||
|
|
||||||
const client = new ServiceClient(undefined, {
|
const client = new ServiceClient(undefined, {
|
||||||
httpClient: getMockedHttpClient(),
|
httpClient: getMockedHttpClient(),
|
||||||
requestPolicyFactories: [redirectPolicy(1)],
|
requestPolicyFactories: [redirectPolicy(1)],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const response = await client.sendRequest({ url: resourceUrl, method: "GET" });
|
const response = await client.sendRequest({ url: resourceUrl, method: "GET" });
|
||||||
|
|
||||||
expect(response.status).to.equal(300);
|
expect(response.status).to.equal(300);
|
||||||
expect(response.headers.get("location")).to.equal(redirectedUrl_2);
|
expect(response.headers.get("location")).to.equal(redirectedUrl_2);
|
||||||
expect(response.redirected).to.be.true;
|
expect(response.redirected).to.be.true;
|
||||||
expect(response.url).to.equal(redirectedUrl_1);
|
expect(response.url).to.equal(redirectedUrl_1);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче