// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { logger } from "../log.js";
/**
 * The programmatic identifier of the redirectPolicy.
 */
export const redirectPolicyName = "redirectPolicy";
/**
 * Methods that are allowed to follow redirects 301 and 302
 */
const allowedRedirect = ["GET", "HEAD"];
/**
 * A policy to follow Location headers from the server in order
 * to support server-side redirection.
 * In the browser, this policy is not used.
 * @param options - Options to control policy behavior.
 */
export function redirectPolicy(options = {}) {
    const { maxRetries = 20, allowCrossOriginRedirects = false } = options;
    return {
        name: redirectPolicyName,
        async sendRequest(request, next) {
            const response = await next(request);
            return handleRedirect(next, response, maxRetries, allowCrossOriginRedirects);
        },
    };
}
async function handleRedirect(next, response, maxRetries, allowCrossOriginRedirects, currentRetries = 0) {
    const { request, status, headers } = response;
    const locationHeader = headers.get("location");
    if (locationHeader &&
        (status === 300 ||
            (status === 301 && allowedRedirect.includes(request.method)) ||
            (status === 302 && allowedRedirect.includes(request.method)) ||
            (status === 303 && request.method === "POST") ||
            status === 307) &&
        currentRetries < maxRetries) {
        const url = new URL(locationHeader, request.url);
        // Only follow redirects to the same origin by default.
        if (!allowCrossOriginRedirects) {
            const originalUrl = new URL(request.url);
            if (url.origin !== originalUrl.origin) {
                logger.verbose(`Skipping cross-origin redirect from ${originalUrl.origin} to ${url.origin}.`);
                return response;
            }
        }
        request.url = url.toString();
        // POST request with Status code 303 should be converted into a
        // redirected GET request if the redirect url is present in the location header
        if (status === 303) {
            request.method = "GET";
            request.headers.delete("Content-Length");
            delete request.body;
        }
        request.headers.delete("Authorization");
        const res = await next(request);
        return handleRedirect(next, res, maxRetries, allowCrossOriginRedirects, currentRetries + 1);
    }
    return response;
}
//# sourceMappingURL=redirectPolicy.js.map