//I wanted to change AutoRedirect per request using the same HttpClient.
//But this is not possible because it throws an exception: This instance has already started one or more requests. Properties can only be modified before sending the first request.
//Here is my solution, Please learn it so if anyone else asks about it you should answer.

//Usage:
var handler = new RedirectHandler(new HttpClientHandler());
var client = new HttpClient(handler);

//redirects to HTTPS
var url = "http://stackoverflow.com/";

//AutoRedirect is true
var response = await HttpClientHelper.SendAsync(client, url, autoRedirect: true).ConfigureAwait(false);
//AutoRedirect is false
response = await HttpClientHelper.SendAsync(client, url, autoRedirect: false).ConfigureAwait(false);

public static class HttpClientHelper
{
    private const string AutoRedirectPropertyKey = "RequestAutoRedirect";
    private static readonly HttpRequestOptionsKey<bool?> AutoRedirectOptionsKey = new(AutoRedirectPropertyKey);

    public static Task<HttpResponseMessage> SendAsync(HttpClient client, string url, bool autoRedirect = true)
    {
        var uri = new Uri(url);
        var request = new HttpRequestMessage
        {
            RequestUri = uri,
            Method = HttpMethod.Get
        };
        
        request.SetAutoRedirect(autoRedirect);

        return client.SendAsync(request);
    }

    public static void SetAutoRedirect(this HttpRequestMessage request, bool autoRedirect)
    {
        request.Options.Set(AutoRedirectOptionsKey, autoRedirect);
    }
    public static bool? GetAutoRedirect(this HttpRequestMessage request)
    {
        request.Options.TryGetValue(AutoRedirectOptionsKey, out var value);
        return value;
    }

    public static HttpMessageHandler? GetMostInnerHandler(this HttpMessageHandler? self)
    {
        while (self is DelegatingHandler handler)
        {
            self = handler.InnerHandler;
        }

        return self;
    }
}

public class RedirectHandler : DelegatingHandler
{
    private int MaxAutomaticRedirections { get; set; }
    private bool InitialAutoRedirect { get; set; }

    public RedirectHandler(HttpMessageHandler innerHandler) : base(innerHandler)
    {
        var mostInnerHandler = innerHandler.GetMostInnerHandler();
        SetupCustomAutoRedirect(mostInnerHandler);
    }

    private void SetupCustomAutoRedirect(HttpMessageHandler? mostInnerHandler)
    {
        //Store the initial auto-redirect & max-auto-redirect values.
        //Disabling auto-redirect and handle redirects manually.
        try
        {
            switch (mostInnerHandler)
            {
                case HttpClientHandler hch:
                    InitialAutoRedirect = hch.AllowAutoRedirect;
                    MaxAutomaticRedirections = hch.MaxAutomaticRedirections;
                    hch.AllowAutoRedirect = false;
                    break;
                case SocketsHttpHandler shh:
                    InitialAutoRedirect = shh.AllowAutoRedirect;
                    MaxAutomaticRedirections = shh.MaxAutomaticRedirections;
                    shh.AllowAutoRedirect = false;
                    break;
                default:
                    Debug.WriteLine("[SetupCustomAutoRedirect] Unknown handler type: {0}", mostInnerHandler?.GetType().FullName);
                    InitialAutoRedirect = true;
                    MaxAutomaticRedirections = 17;
                    break;
            }
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.Message);
            InitialAutoRedirect = true;
            MaxAutomaticRedirections = 17;
        }
    }

    private bool IsRedirectAllowed(HttpRequestMessage request)
    {
        var value = request.GetAutoRedirect();
        if (value == null)
            return InitialAutoRedirect;
        
        return value == true;
    }
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var redirectCount = 0;
        var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);

        //Manual Redirect
        //https://github.com/dotnet/runtime/blob/ccfe21882e4a2206ce49cd5b32d3eb3cab3e530f/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs
        Uri? redirectUri;
        while (IsRedirect(response) && IsRedirectAllowed(request) && (redirectUri = GetUriForRedirect(request.RequestUri!, response)) != null)
        {
            redirectCount++;
            if (redirectCount > MaxAutomaticRedirections)
                break;

            response.Dispose();

            // Clear the authorization header.
            request.Headers.Authorization = null;
            // Set up for the redirect
            request.RequestUri = redirectUri;

            if (RequestRequiresForceGet(response.StatusCode, request.Method))
            {
                request.Method = HttpMethod.Get;
                request.Content = null;
                if (request.Headers.TransferEncodingChunked == true)
                    request.Headers.TransferEncodingChunked = false;
            }

            // Issue the redirected request.
            response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
        }

        return response;
    }
    private bool IsRedirect(HttpResponseMessage response)
    {
        switch (response.StatusCode)
        {
            case HttpStatusCode.MultipleChoices:
            case HttpStatusCode.Moved:
            case HttpStatusCode.Found:
            case HttpStatusCode.SeeOther:
            case HttpStatusCode.TemporaryRedirect:
            case HttpStatusCode.PermanentRedirect:
                return true;

            default:
                return false;
        }
    }
    private static Uri? GetUriForRedirect(Uri requestUri, HttpResponseMessage response)
    {
        var location = response.Headers.Location;
        if (location == null)
        {
            return null;
        }

        // Ensure the redirect location is an absolute URI.
        if (!location.IsAbsoluteUri)
        {
            location = new Uri(requestUri, location);
        }

        // Per https://tools.ietf.org/html/rfc7231#section-7.1.2, a redirect location without a
        // fragment should inherit the fragment from the original URI.
        var requestFragment = requestUri.Fragment;
        if (!string.IsNullOrEmpty(requestFragment))
        {
            var redirectFragment = location.Fragment;
            if (string.IsNullOrEmpty(redirectFragment))
            {
                location = new UriBuilder(location) { Fragment = requestFragment }.Uri;
            }
        }

        return location;
    }
    private static bool RequestRequiresForceGet(HttpStatusCode statusCode, HttpMethod requestMethod)
    {
        switch (statusCode)
        {
            case HttpStatusCode.Moved:
            case HttpStatusCode.Found:
            case HttpStatusCode.MultipleChoices:
                return requestMethod == HttpMethod.Post;
            case HttpStatusCode.SeeOther:
                return requestMethod != HttpMethod.Get && requestMethod != HttpMethod.Head;
            default:
                return false;
        }
    }
}

The main idea is to disable automatic redirects and handle them manually using a custom **RedirectHandler**.

 1. Before sending a request, we utilize the extension method **SetAutoRedirect** to store the redirect rule in the request's options dictionary.
 2. Upon receiving a response, we check if it is a redirect. If it is, we then examine the request's options dictionary for a redirect rule using the extension method **GetAutoRedirect**.
 3. Repeat #2 until **MaxAutomaticRedirections** is reached or there are no further redirects.