Move remote server redirect and decompression tests to HttpClientHandlerTest.RemoteSe...
authorGeoff Kizer <geoffrek@microsoft.com>
Sat, 26 Jun 2021 04:10:32 +0000 (21:10 -0700)
committerGitHub <noreply@github.com>
Sat, 26 Jun 2021 04:10:32 +0000 (21:10 -0700)
* move remote redirect and decompression tests to HttpClientHandler_RemoteServerTest

Co-authored-by: Geoffrey Kizer <geoffrek@windows.microsoft.com>
src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.AutoRedirect.cs
src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs
src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs

index 7521484..c9bbdbc 100644 (file)
@@ -2,7 +2,6 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Generic;
-using System.Net.Http.Headers;
 using System.Net.Sockets;
 using System.Net.Test.Common;
 using System.Threading.Tasks;
@@ -12,32 +11,13 @@ using Xunit.Abstractions;
 
 namespace System.Net.Http.Functional.Tests
 {
-    using Configuration = System.Net.Test.Common.Configuration;
-
 #if WINHTTPHANDLER_TEST
     using HttpClientHandler = System.Net.Http.WinHttpClientHandler;
 #endif
 
     public abstract class HttpClientHandlerTest_AutoRedirect : HttpClientHandlerTestBase
     {
-        private const string ExpectedContent = "Test content";
-        private const string Username = "testuser";
-        private const string Password = "password";
-
-        private readonly NetworkCredential _credential = new NetworkCredential(Username, Password);
-
-        public static IEnumerable<object[]> RemoteServersAndRedirectStatusCodes()
-        {
-            foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers)
-            {
-                yield return new object[] { remoteServer, 300 };
-                yield return new object[] { remoteServer, 301 };
-                yield return new object[] { remoteServer, 302 };
-                yield return new object[] { remoteServer, 303 };
-                yield return new object[] { remoteServer, 307 };
-                yield return new object[] { remoteServer, 308 };
-            }
-        }
+        public HttpClientHandlerTest_AutoRedirect(ITestOutputHelper output) : base(output) { }
 
         public static IEnumerable<object[]> RedirectStatusCodesOldMethodsNewMethods()
         {
@@ -55,34 +35,6 @@ namespace System.Net.Http.Functional.Tests
                 yield return new object[] { statusCode, "MYCUSTOMMETHOD", statusCode == 303 ? "GET" : "MYCUSTOMMETHOD" };
             }
         }
-        public HttpClientHandlerTest_AutoRedirect(ITestOutputHelper output) : base(output) { }
-
-        [OuterLoop("Uses external servers")]
-        [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))]
-        public async Task GetAsync_AllowAutoRedirectFalse_RedirectFromHttpToHttp_StatusCodeRedirect(Configuration.Http.RemoteServer remoteServer, int statusCode)
-        {
-            if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10))
-            {
-                // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework.
-                return;
-            }
-
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AllowAutoRedirect = false;
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                Uri uri = remoteServer.RedirectUriForDestinationUri(
-                    statusCode: statusCode,
-                    destinationUri: remoteServer.EchoUri,
-                    hops: 1);
-                _output.WriteLine("Uri: {0}", uri);
-                using (HttpResponseMessage response = await client.GetAsync(uri))
-                {
-                    Assert.Equal(statusCode, (int)response.StatusCode);
-                    Assert.Equal(uri, response.RequestMessage.RequestUri);
-                }
-            }
-        }
 
         [Theory, MemberData(nameof(RedirectStatusCodesOldMethodsNewMethods))]
         public async Task AllowAutoRedirect_True_ValidateNewMethodUsedOnRedirection(
@@ -143,7 +95,7 @@ namespace System.Net.Http.Functional.Tests
                 await LoopbackServer.CreateServerAsync(async (origServer, origUrl) =>
                 {
                     var request = new HttpRequestMessage(HttpMethod.Post, origUrl) { Version = UseVersion };
-                    request.Content = new StringContent(ExpectedContent);
+                    request.Content = new StringContent("hello world");
                     request.Headers.TransferEncodingChunked = true;
 
                     Task<HttpResponseMessage> getResponseTask = client.SendAsync(TestAsync, request);
@@ -192,76 +144,6 @@ namespace System.Net.Http.Functional.Tests
             }
         }
 
-        [OuterLoop("Uses external servers")]
-        [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))]
-        public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpToHttp_StatusCodeOK(Configuration.Http.RemoteServer remoteServer, int statusCode)
-        {
-            if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10))
-            {
-                // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework.
-                return;
-            }
-
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AllowAutoRedirect = true;
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                Uri uri = remoteServer.RedirectUriForDestinationUri(
-                    statusCode: statusCode,
-                    destinationUri: remoteServer.EchoUri,
-                    hops: 1);
-                _output.WriteLine("Uri: {0}", uri);
-                using (HttpResponseMessage response = await client.GetAsync(uri))
-                {
-                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-                    Assert.Equal(remoteServer.EchoUri, response.RequestMessage.RequestUri);
-                }
-            }
-        }
-
-        [OuterLoop("Uses external servers")]
-        [Fact]
-        public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpToHttps_StatusCodeOK()
-        {
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AllowAutoRedirect = true;
-            using (HttpClient client = CreateHttpClient(handler))
-            {
-                Uri uri = Configuration.Http.RemoteHttp11Server.RedirectUriForDestinationUri(
-                    statusCode: 302,
-                    destinationUri: Configuration.Http.RemoteSecureHttp11Server.EchoUri,
-                    hops: 1);
-                _output.WriteLine("Uri: {0}", uri);
-                using (HttpResponseMessage response = await client.GetAsync(uri))
-                {
-                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-                    Assert.Equal(Configuration.Http.SecureRemoteEchoServer, response.RequestMessage.RequestUri);
-                }
-            }
-        }
-
-        [OuterLoop("Uses external servers")]
-        [Fact]
-        public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpsToHttp_StatusCodeRedirect()
-        {
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AllowAutoRedirect = true;
-            using (HttpClient client = CreateHttpClient(handler))
-            {
-                Uri uri = Configuration.Http.RemoteSecureHttp11Server.RedirectUriForDestinationUri(
-                    statusCode: 302,
-                    destinationUri: Configuration.Http.RemoteHttp11Server.EchoUri,
-                    hops: 1);
-                _output.WriteLine("Uri: {0}", uri);
-
-                using (HttpResponseMessage response = await client.GetAsync(uri))
-                {
-                    Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
-                    Assert.Equal(uri, response.RequestMessage.RequestUri);
-                }
-            }
-        }
-
         [Fact]
         public async Task GetAsync_AllowAutoRedirectTrue_RedirectWithoutLocation_ReturnsOriginalResponse()
         {
@@ -288,99 +170,6 @@ namespace System.Net.Http.Functional.Tests
             }
         }
 
-        [OuterLoop("Uses external servers")]
-        [Theory, MemberData(nameof(RemoteServersMemberData))]
-        public async Task GetAsync_AllowAutoRedirectTrue_RedirectToUriWithParams_RequestMsgUriSet(Configuration.Http.RemoteServer remoteServer)
-        {
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AllowAutoRedirect = true;
-            Uri targetUri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password);
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                Uri uri = remoteServer.RedirectUriForDestinationUri(
-                    statusCode: 302,
-                    destinationUri: targetUri,
-                    hops: 1);
-                _output.WriteLine("Uri: {0}", uri);
-                using (HttpResponseMessage response = await client.GetAsync(uri))
-                {
-                    Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
-                    Assert.Equal(targetUri, response.RequestMessage.RequestUri);
-                }
-            }
-        }
-
-        [OuterLoop("Uses external servers")]
-        [Theory]
-        [InlineData(3, 2)]
-        [InlineData(3, 3)]
-        [InlineData(3, 4)]
-        public async Task GetAsync_MaxAutomaticRedirectionsNServerHops_ThrowsIfTooMany(int maxHops, int hops)
-        {
-            if (IsWinHttpHandler && !PlatformDetection.IsWindows10Version1703OrGreater)
-            {
-                // Skip this test if using WinHttpHandler but on a release prior to Windows 10 Creators Update.
-                _output.WriteLine("Skipping test due to Windows 10 version prior to Version 1703.");
-                return;
-            }
-
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.MaxAutomaticRedirections = maxHops;
-            using (HttpClient client = CreateHttpClient(handler))
-            {
-                Task<HttpResponseMessage> t = client.GetAsync(Configuration.Http.RemoteHttp11Server.RedirectUriForDestinationUri(
-                    statusCode: 302,
-                    destinationUri: Configuration.Http.RemoteHttp11Server.EchoUri,
-                    hops: hops));
-
-                if (hops <= maxHops)
-                {
-                    using (HttpResponseMessage response = await t)
-                    {
-                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-                        Assert.Equal(Configuration.Http.RemoteEchoServer, response.RequestMessage.RequestUri);
-                    }
-                }
-                else
-                {
-                    if (!IsWinHttpHandler)
-                    {
-                        using (HttpResponseMessage response = await t)
-                        {
-                            Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
-                        }
-                    }
-                    else
-                    {
-                        await Assert.ThrowsAsync<HttpRequestException>(() => t);
-                    }
-                }
-            }
-        }
-
-        [OuterLoop("Uses external servers")]
-        [Theory, MemberData(nameof(RemoteServersMemberData))]
-        public async Task GetAsync_AllowAutoRedirectTrue_RedirectWithRelativeLocation(Configuration.Http.RemoteServer remoteServer)
-        {
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AllowAutoRedirect = true;
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                Uri uri = remoteServer.RedirectUriForDestinationUri(
-                    statusCode: 302,
-                    destinationUri: remoteServer.EchoUri,
-                    hops: 1,
-                    relative: true);
-                _output.WriteLine("Uri: {0}", uri);
-
-                using (HttpResponseMessage response = await client.GetAsync(uri))
-                {
-                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-                    Assert.Equal(remoteServer.EchoUri, response.RequestMessage.RequestUri);
-                }
-            }
-        }
-
         [Theory]
         [InlineData(200)]
         [InlineData(201)]
@@ -476,111 +265,5 @@ namespace System.Net.Http.Functional.Tests
                 });
             }
         }
-
-        [Theory, MemberData(nameof(RemoteServersMemberData))]
-        [OuterLoop("Uses external servers")]
-        public async Task GetAsync_CredentialIsNetworkCredentialUriRedirect_StatusCodeUnauthorized(Configuration.Http.RemoteServer remoteServer)
-        {
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.Credentials = _credential;
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                Uri redirectUri = remoteServer.RedirectUriForCreds(
-                    statusCode: 302,
-                    userName: Username,
-                    password: Password);
-                using (HttpResponseMessage unAuthResponse = await client.GetAsync(redirectUri))
-                {
-                    Assert.Equal(HttpStatusCode.Unauthorized, unAuthResponse.StatusCode);
-                }
-            }
-        }
-
-        [Theory, MemberData(nameof(RemoteServersMemberData))]
-        [OuterLoop("Uses external servers")]
-        public async Task HttpClientHandler_CredentialIsNotCredentialCacheAfterRedirect_StatusCodeOK(Configuration.Http.RemoteServer remoteServer)
-        {
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.Credentials = _credential;
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                Uri redirectUri = remoteServer.RedirectUriForCreds(
-                    statusCode: 302,
-                    userName: Username,
-                    password: Password);
-                using (HttpResponseMessage unAuthResponse = await client.GetAsync(redirectUri))
-                {
-                    Assert.Equal(HttpStatusCode.Unauthorized, unAuthResponse.StatusCode);
-                }
-
-                // Use the same handler to perform get request, authentication should succeed after redirect.
-                Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password);
-                using (HttpResponseMessage authResponse = await client.GetAsync(uri))
-                {
-                    Assert.Equal(HttpStatusCode.OK, authResponse.StatusCode);
-                }
-            }
-        }
-
-        [OuterLoop("Uses external servers")]
-        [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))]
-        public async Task GetAsync_CredentialIsCredentialCacheUriRedirect_StatusCodeOK(Configuration.Http.RemoteServer remoteServer, int statusCode)
-        {
-            if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10))
-            {
-                // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework.
-                return;
-            }
-
-            Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password);
-            Uri redirectUri = remoteServer.RedirectUriForCreds(
-                statusCode: statusCode,
-                userName: Username,
-                password: Password);
-            _output.WriteLine(uri.AbsoluteUri);
-            _output.WriteLine(redirectUri.AbsoluteUri);
-            var credentialCache = new CredentialCache();
-            credentialCache.Add(uri, "Basic", _credential);
-
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.Credentials = credentialCache;
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                using (HttpResponseMessage response = await client.GetAsync(redirectUri))
-                {
-                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-                    Assert.Equal(uri, response.RequestMessage.RequestUri);
-                }
-            }
-        }
-
-        [OuterLoop("Uses external servers")]
-        [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))]
-        public async Task DefaultHeaders_SetCredentials_ClearedOnRedirect(Configuration.Http.RemoteServer remoteServer, int statusCode)
-        {
-            if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10))
-            {
-                // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework.
-                return;
-            }
-
-            HttpClientHandler handler = CreateHttpClientHandler();
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                string credentialString = _credential.UserName + ":" + _credential.Password;
-                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentialString);
-                Uri uri = remoteServer.RedirectUriForDestinationUri(
-                    statusCode: statusCode,
-                    destinationUri: remoteServer.EchoUri,
-                    hops: 1);
-                _output.WriteLine("Uri: {0}", uri);
-                using (HttpResponseMessage response = await client.GetAsync(uri))
-                {
-                    string responseText = await response.Content.ReadAsStringAsync();
-                    _output.WriteLine(responseText);
-                    Assert.False(TestHelper.JsonMessageContainsKey(responseText, "Authorization"));
-                }
-            }
-        }
     }
 }
index f53b6fc..88ac334 100644 (file)
@@ -13,8 +13,6 @@ using Xunit.Abstractions;
 
 namespace System.Net.Http.Functional.Tests
 {
-    using Configuration = System.Net.Test.Common.Configuration;
-
 #if WINHTTPHANDLER_TEST
     using HttpClientHandler = System.Net.Http.WinHttpClientHandler;
 #endif
@@ -28,17 +26,6 @@ namespace System.Net.Http.Functional.Tests
 #endif
         public HttpClientHandler_Decompression_Test(ITestOutputHelper output) : base(output) { }
 
-        public static IEnumerable<object[]> RemoteServersAndCompressionUris()
-        {
-            foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers)
-            {
-                yield return new object[] { remoteServer, remoteServer.GZipUri };
-
-                // Remote deflate endpoint isn't correctly following the deflate protocol.
-                //yield return new object[] { remoteServer, remoteServer.DeflateUri };
-            }
-        }
-
         [Theory]
         [InlineData("gzip", false)]
         [InlineData("gzip", true)]
@@ -169,83 +156,6 @@ namespace System.Net.Http.Functional.Tests
             });
         }
 
-        [OuterLoop("Uses external servers")]
-        [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")]
-        [Theory, MemberData(nameof(RemoteServersAndCompressionUris))]
-        public async Task GetAsync_SetAutomaticDecompression_ContentDecompressed_GZip(Configuration.Http.RemoteServer remoteServer, Uri uri)
-        {
-            // Sync API supported only up to HTTP/1.1
-            if (!TestAsync && remoteServer.HttpVersion.Major >= 2)
-            {
-                return;
-            }
-
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            {
-                using (HttpResponseMessage response = await client.SendAsync(TestAsync, CreateRequest(HttpMethod.Get, uri, remoteServer.HttpVersion)))
-                {
-                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-                    string responseContent = await response.Content.ReadAsStringAsync();
-                    _output.WriteLine(responseContent);
-                    TestHelper.VerifyResponseBody(
-                        responseContent,
-                        response.Content.Headers.ContentMD5,
-                        false,
-                        null);
-                }
-            }
-        }
-
-        // The remote server endpoint was written to use DeflateStream, which isn't actually a correct
-        // implementation of the deflate protocol (the deflate protocol requires the zlib wrapper around
-        // deflate).  Until we can get that updated (and deal with previous releases still testing it
-        // via a DeflateStream-based implementation), we utilize httpbin.org to help validate behavior.
-        [OuterLoop("Uses external servers")]
-        [Theory]
-        [InlineData("http://httpbin.org/deflate", "\"deflated\": true")]
-        [InlineData("https://httpbin.org/deflate", "\"deflated\": true")]
-        [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")]
-        public async Task GetAsync_SetAutomaticDecompression_ContentDecompressed_Deflate(string uri, string expectedContent)
-        {
-            if (IsWinHttpHandler)
-            {
-                // WinHttpHandler targets netstandard2.0 and still erroneously uses DeflateStream rather than ZlibStream for deflate.
-                return;
-            }
-
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
-            using (HttpClient client = CreateHttpClient(handler))
-            {
-                Assert.Contains(expectedContent, await client.GetStringAsync(uri));
-            }
-        }
-
-        [OuterLoop("Uses external servers")]
-        [Theory, MemberData(nameof(RemoteServersAndCompressionUris))]
-        [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")]
-        public async Task GetAsync_SetAutomaticDecompression_HeadersRemoved(Configuration.Http.RemoteServer remoteServer, Uri uri)
-        {
-            // Sync API supported only up to HTTP/1.1
-            if (!TestAsync && remoteServer.HttpVersion.Major >= 2)
-            {
-                return;
-            }
-
-            HttpClientHandler handler = CreateHttpClientHandler();
-            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
-            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
-            using (HttpResponseMessage response = await client.SendAsync(TestAsync, CreateRequest(HttpMethod.Get, uri, remoteServer.HttpVersion), HttpCompletionOption.ResponseHeadersRead))
-            {
-                Assert.Equal(HttpStatusCode.OK, response.StatusCode);
-
-                Assert.False(response.Content.Headers.Contains("Content-Encoding"), "Content-Encoding unexpectedly found");
-                Assert.False(response.Content.Headers.Contains("Content-Length"), "Content-Length unexpectedly found");
-            }
-        }
-
         [Theory]
 #if NETCOREAPP
         [InlineData(DecompressionMethods.Brotli, "br", "")]
index 732384e..36d732d 100644 (file)
@@ -4,6 +4,7 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using System.Net.Http.Headers;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
@@ -912,6 +913,403 @@ namespace System.Net.Http.Functional.Tests
             }
         }
 
+        public static IEnumerable<object[]> RemoteServersAndRedirectStatusCodes()
+        {
+            foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers)
+            {
+                yield return new object[] { remoteServer, 300 };
+                yield return new object[] { remoteServer, 301 };
+                yield return new object[] { remoteServer, 302 };
+                yield return new object[] { remoteServer, 303 };
+                yield return new object[] { remoteServer, 307 };
+                yield return new object[] { remoteServer, 308 };
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))]
+        public async Task GetAsync_AllowAutoRedirectFalse_RedirectFromHttpToHttp_StatusCodeRedirect(Configuration.Http.RemoteServer remoteServer, int statusCode)
+        {
+            if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10))
+            {
+                // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework.
+                return;
+            }
+
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AllowAutoRedirect = false;
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                Uri uri = remoteServer.RedirectUriForDestinationUri(
+                    statusCode: statusCode,
+                    destinationUri: remoteServer.EchoUri,
+                    hops: 1);
+                _output.WriteLine("Uri: {0}", uri);
+                using (HttpResponseMessage response = await client.GetAsync(uri))
+                {
+                    Assert.Equal(statusCode, (int)response.StatusCode);
+                    Assert.Equal(uri, response.RequestMessage.RequestUri);
+                }
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))]
+        public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpToHttp_StatusCodeOK(Configuration.Http.RemoteServer remoteServer, int statusCode)
+        {
+            if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10))
+            {
+                // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework.
+                return;
+            }
+
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AllowAutoRedirect = true;
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                Uri uri = remoteServer.RedirectUriForDestinationUri(
+                    statusCode: statusCode,
+                    destinationUri: remoteServer.EchoUri,
+                    hops: 1);
+                _output.WriteLine("Uri: {0}", uri);
+                using (HttpResponseMessage response = await client.GetAsync(uri))
+                {
+                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+                    Assert.Equal(remoteServer.EchoUri, response.RequestMessage.RequestUri);
+                }
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Fact]
+        public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpToHttps_StatusCodeOK()
+        {
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AllowAutoRedirect = true;
+            using (HttpClient client = CreateHttpClient(handler))
+            {
+                Uri uri = Configuration.Http.RemoteHttp11Server.RedirectUriForDestinationUri(
+                    statusCode: 302,
+                    destinationUri: Configuration.Http.RemoteSecureHttp11Server.EchoUri,
+                    hops: 1);
+                _output.WriteLine("Uri: {0}", uri);
+                using (HttpResponseMessage response = await client.GetAsync(uri))
+                {
+                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+                    Assert.Equal(Configuration.Http.SecureRemoteEchoServer, response.RequestMessage.RequestUri);
+                }
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Fact]
+        public async Task GetAsync_AllowAutoRedirectTrue_RedirectFromHttpsToHttp_StatusCodeRedirect()
+        {
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AllowAutoRedirect = true;
+            using (HttpClient client = CreateHttpClient(handler))
+            {
+                Uri uri = Configuration.Http.RemoteSecureHttp11Server.RedirectUriForDestinationUri(
+                    statusCode: 302,
+                    destinationUri: Configuration.Http.RemoteHttp11Server.EchoUri,
+                    hops: 1);
+                _output.WriteLine("Uri: {0}", uri);
+
+                using (HttpResponseMessage response = await client.GetAsync(uri))
+                {
+                    Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
+                    Assert.Equal(uri, response.RequestMessage.RequestUri);
+                }
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Theory, MemberData(nameof(RemoteServersMemberData))]
+        public async Task GetAsync_AllowAutoRedirectTrue_RedirectToUriWithParams_RequestMsgUriSet(Configuration.Http.RemoteServer remoteServer)
+        {
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AllowAutoRedirect = true;
+            Uri targetUri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password);
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                Uri uri = remoteServer.RedirectUriForDestinationUri(
+                    statusCode: 302,
+                    destinationUri: targetUri,
+                    hops: 1);
+                _output.WriteLine("Uri: {0}", uri);
+                using (HttpResponseMessage response = await client.GetAsync(uri))
+                {
+                    Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
+                    Assert.Equal(targetUri, response.RequestMessage.RequestUri);
+                }
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Theory]
+        [InlineData(3, 2)]
+        [InlineData(3, 3)]
+        [InlineData(3, 4)]
+        public async Task GetAsync_MaxAutomaticRedirectionsNServerHops_ThrowsIfTooMany(int maxHops, int hops)
+        {
+            if (IsWinHttpHandler && !PlatformDetection.IsWindows10Version1703OrGreater)
+            {
+                // Skip this test if using WinHttpHandler but on a release prior to Windows 10 Creators Update.
+                _output.WriteLine("Skipping test due to Windows 10 version prior to Version 1703.");
+                return;
+            }
+
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.MaxAutomaticRedirections = maxHops;
+            using (HttpClient client = CreateHttpClient(handler))
+            {
+                Task<HttpResponseMessage> t = client.GetAsync(Configuration.Http.RemoteHttp11Server.RedirectUriForDestinationUri(
+                    statusCode: 302,
+                    destinationUri: Configuration.Http.RemoteHttp11Server.EchoUri,
+                    hops: hops));
+
+                if (hops <= maxHops)
+                {
+                    using (HttpResponseMessage response = await t)
+                    {
+                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+                        Assert.Equal(Configuration.Http.RemoteEchoServer, response.RequestMessage.RequestUri);
+                    }
+                }
+                else
+                {
+                    if (!IsWinHttpHandler)
+                    {
+                        using (HttpResponseMessage response = await t)
+                        {
+                            Assert.Equal(HttpStatusCode.Redirect, response.StatusCode);
+                        }
+                    }
+                    else
+                    {
+                        await Assert.ThrowsAsync<HttpRequestException>(() => t);
+                    }
+                }
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Theory, MemberData(nameof(RemoteServersMemberData))]
+        public async Task GetAsync_AllowAutoRedirectTrue_RedirectWithRelativeLocation(Configuration.Http.RemoteServer remoteServer)
+        {
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AllowAutoRedirect = true;
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                Uri uri = remoteServer.RedirectUriForDestinationUri(
+                    statusCode: 302,
+                    destinationUri: remoteServer.EchoUri,
+                    hops: 1,
+                    relative: true);
+                _output.WriteLine("Uri: {0}", uri);
+
+                using (HttpResponseMessage response = await client.GetAsync(uri))
+                {
+                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+                    Assert.Equal(remoteServer.EchoUri, response.RequestMessage.RequestUri);
+                }
+            }
+        }
+
+        [Theory, MemberData(nameof(RemoteServersMemberData))]
+        [OuterLoop("Uses external servers")]
+        public async Task GetAsync_CredentialIsNetworkCredentialUriRedirect_StatusCodeUnauthorized(Configuration.Http.RemoteServer remoteServer)
+        {
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.Credentials = _credential;
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                Uri redirectUri = remoteServer.RedirectUriForCreds(
+                    statusCode: 302,
+                    userName: Username,
+                    password: Password);
+                using (HttpResponseMessage unAuthResponse = await client.GetAsync(redirectUri))
+                {
+                    Assert.Equal(HttpStatusCode.Unauthorized, unAuthResponse.StatusCode);
+                }
+            }
+        }
+
+        [Theory, MemberData(nameof(RemoteServersMemberData))]
+        [OuterLoop("Uses external servers")]
+        public async Task HttpClientHandler_CredentialIsNotCredentialCacheAfterRedirect_StatusCodeOK(Configuration.Http.RemoteServer remoteServer)
+        {
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.Credentials = _credential;
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                Uri redirectUri = remoteServer.RedirectUriForCreds(
+                    statusCode: 302,
+                    userName: Username,
+                    password: Password);
+                using (HttpResponseMessage unAuthResponse = await client.GetAsync(redirectUri))
+                {
+                    Assert.Equal(HttpStatusCode.Unauthorized, unAuthResponse.StatusCode);
+                }
+
+                // Use the same handler to perform get request, authentication should succeed after redirect.
+                Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password);
+                using (HttpResponseMessage authResponse = await client.GetAsync(uri))
+                {
+                    Assert.Equal(HttpStatusCode.OK, authResponse.StatusCode);
+                }
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))]
+        public async Task GetAsync_CredentialIsCredentialCacheUriRedirect_StatusCodeOK(Configuration.Http.RemoteServer remoteServer, int statusCode)
+        {
+            if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10))
+            {
+                // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework.
+                return;
+            }
+
+            Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password);
+            Uri redirectUri = remoteServer.RedirectUriForCreds(
+                statusCode: statusCode,
+                userName: Username,
+                password: Password);
+            _output.WriteLine(uri.AbsoluteUri);
+            _output.WriteLine(redirectUri.AbsoluteUri);
+            var credentialCache = new CredentialCache();
+            credentialCache.Add(uri, "Basic", _credential);
+
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.Credentials = credentialCache;
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                using (HttpResponseMessage response = await client.GetAsync(redirectUri))
+                {
+                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+                    Assert.Equal(uri, response.RequestMessage.RequestUri);
+                }
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Theory, MemberData(nameof(RemoteServersAndRedirectStatusCodes))]
+        public async Task DefaultHeaders_SetCredentials_ClearedOnRedirect(Configuration.Http.RemoteServer remoteServer, int statusCode)
+        {
+            if (statusCode == 308 && (IsWinHttpHandler && PlatformDetection.WindowsVersion < 10))
+            {
+                // 308 redirects are not supported on old versions of WinHttp, or on .NET Framework.
+                return;
+            }
+
+            HttpClientHandler handler = CreateHttpClientHandler();
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                string credentialString = _credential.UserName + ":" + _credential.Password;
+                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentialString);
+                Uri uri = remoteServer.RedirectUriForDestinationUri(
+                    statusCode: statusCode,
+                    destinationUri: remoteServer.EchoUri,
+                    hops: 1);
+                _output.WriteLine("Uri: {0}", uri);
+                using (HttpResponseMessage response = await client.GetAsync(uri))
+                {
+                    string responseText = await response.Content.ReadAsStringAsync();
+                    _output.WriteLine(responseText);
+                    Assert.False(TestHelper.JsonMessageContainsKey(responseText, "Authorization"));
+                }
+            }
+        }
+
+        public static IEnumerable<object[]> RemoteServersAndCompressionUris()
+        {
+            foreach (Configuration.Http.RemoteServer remoteServer in Configuration.Http.RemoteServers)
+            {
+                yield return new object[] { remoteServer, remoteServer.GZipUri };
+
+                // Remote deflate endpoint isn't correctly following the deflate protocol.
+                //yield return new object[] { remoteServer, remoteServer.DeflateUri };
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")]
+        [Theory, MemberData(nameof(RemoteServersAndCompressionUris))]
+        public async Task GetAsync_SetAutomaticDecompression_ContentDecompressed_GZip(Configuration.Http.RemoteServer remoteServer, Uri uri)
+        {
+            // Sync API supported only up to HTTP/1.1
+            if (!TestAsync && remoteServer.HttpVersion.Major >= 2)
+            {
+                return;
+            }
+
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            {
+                using (HttpResponseMessage response = await client.SendAsync(TestAsync, CreateRequest(HttpMethod.Get, uri, remoteServer.HttpVersion)))
+                {
+                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+                    string responseContent = await response.Content.ReadAsStringAsync();
+                    _output.WriteLine(responseContent);
+                    TestHelper.VerifyResponseBody(
+                        responseContent,
+                        response.Content.Headers.ContentMD5,
+                        false,
+                        null);
+                }
+            }
+        }
+
+        // The remote server endpoint was written to use DeflateStream, which isn't actually a correct
+        // implementation of the deflate protocol (the deflate protocol requires the zlib wrapper around
+        // deflate).  Until we can get that updated (and deal with previous releases still testing it
+        // via a DeflateStream-based implementation), we utilize httpbin.org to help validate behavior.
+        [OuterLoop("Uses external servers")]
+        [Theory]
+        [InlineData("http://httpbin.org/deflate", "\"deflated\": true")]
+        [InlineData("https://httpbin.org/deflate", "\"deflated\": true")]
+        [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")]
+        public async Task GetAsync_SetAutomaticDecompression_ContentDecompressed_Deflate(string uri, string expectedContent)
+        {
+            if (IsWinHttpHandler)
+            {
+                // WinHttpHandler targets netstandard2.0 and still erroneously uses DeflateStream rather than ZlibStream for deflate.
+                return;
+            }
+
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
+            using (HttpClient client = CreateHttpClient(handler))
+            {
+                Assert.Contains(expectedContent, await client.GetStringAsync(uri));
+            }
+        }
+
+        [OuterLoop("Uses external servers")]
+        [Theory, MemberData(nameof(RemoteServersAndCompressionUris))]
+        [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")]
+        public async Task GetAsync_SetAutomaticDecompression_HeadersRemoved(Configuration.Http.RemoteServer remoteServer, Uri uri)
+        {
+            // Sync API supported only up to HTTP/1.1
+            if (!TestAsync && remoteServer.HttpVersion.Major >= 2)
+            {
+                return;
+            }
+
+            HttpClientHandler handler = CreateHttpClientHandler();
+            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
+            using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler))
+            using (HttpResponseMessage response = await client.SendAsync(TestAsync, CreateRequest(HttpMethod.Get, uri, remoteServer.HttpVersion), HttpCompletionOption.ResponseHeadersRead))
+            {
+                Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+
+                Assert.False(response.Content.Headers.Contains("Content-Encoding"), "Content-Encoding unexpectedly found");
+                Assert.False(response.Content.Headers.Contains("Content-Length"), "Content-Length unexpectedly found");
+            }
+        }
+
         [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))]
         [Theory]
         [MemberData(nameof(Http2Servers))]