Merge branch 'release/2.2'
This commit is contained in:
commit
c612eb8730
|
|
@ -26,4 +26,5 @@ scripts/tmp/
|
|||
.tools/
|
||||
src/**/global.json
|
||||
launchSettings.json
|
||||
BenchmarkDotNet.Artifacts/
|
||||
BenchmarkDotNet.Artifacts/
|
||||
korebuild-lock.txt
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@
|
|||
Exclude="
|
||||
@(ProjectToExclude);
|
||||
$(RepositoryRoot)**\bin\**\*;
|
||||
$(RepositoryRoot)**\obj\**\*;
|
||||
$(RepositoryRoot)**\AutobahnTestApp\**\*;" />
|
||||
$(RepositoryRoot)**\obj\**\*;" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Properties for publishing -->
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@ content/*.js;Microsoft.DotNet.Web.Spa.ProjectTemplates.*.nupkg; Exclude JavaScri
|
|||
content/*.js;Microsoft.DotNet.Web.ProjectTemplates.*.nupkg; Exclude JavaScript files from codesigning in project templates
|
||||
Templates/*.js;Microsoft.VisualStudio.Web.CodeGenerators.Mvc.*.nupkg; Exclude JavaScript files from codesigning in code generators
|
||||
*.js;signalr-*-javadoc.jar; Exclude JavaScript files in the generated javadocs
|
||||
*.binlog; Exclude msbuild log files
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
{
|
||||
"adx-nonshipping": {
|
||||
"rules": [],
|
||||
"packages": {
|
||||
"Microsoft.AspNetCore.HttpSys.Sources": {}
|
||||
}
|
||||
},
|
||||
"Default": {
|
||||
"rules": [
|
||||
"DefaultCompositeRule"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
<Project>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<DeveloperBuildTestTfms>netcoreapp2.2</DeveloperBuildTestTfms>
|
||||
<StandardTestTfms>$(DeveloperBuildTestTfms)</StandardTestTfms>
|
||||
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' ">$(StandardTestTfms)</StandardTestTfms>
|
||||
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestTfms);net472</StandardTestTfms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -19,14 +19,6 @@ namespace Microsoft.AspNetCore.Server.HttpSys.Listener
|
|||
private static object PortLock = new object();
|
||||
|
||||
internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15);
|
||||
// Minimum support for Windows 7 is assumed.
|
||||
internal static readonly bool IsWin8orLater;
|
||||
|
||||
static Utilities()
|
||||
{
|
||||
var win8Version = new Version(6, 2);
|
||||
IsWin8orLater = (Environment.OSVersion.Version >= win8Version);
|
||||
}
|
||||
|
||||
internal static HttpSysListener CreateHttpServer(out string baseAddress)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,9 +2,13 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -12,6 +16,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys.FunctionalTests
|
|||
{
|
||||
public class ResponseCachingTests
|
||||
{
|
||||
private readonly string _absoluteFilePath;
|
||||
private readonly long _fileLength;
|
||||
|
||||
public ResponseCachingTests()
|
||||
{
|
||||
_absoluteFilePath = Directory.GetFiles(Directory.GetCurrentDirectory()).First();
|
||||
_fileLength = new FileInfo(_absoluteFilePath).Length;
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_NoCacheControl_NotCached()
|
||||
{
|
||||
|
|
@ -51,6 +64,50 @@ namespace Microsoft.AspNetCore.Server.HttpSys.FunctionalTests
|
|||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win2008R2, WindowsVersions.Win7, SkipReason = "Content type not required for caching on Win7 and Win2008R2.")]
|
||||
public async Task Caching_WithoutContentType_NotCached()
|
||||
{
|
||||
var requestCount = 1;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
// httpContext.Response.ContentType = "some/thing"; // Http.Sys requires content-type for caching
|
||||
httpContext.Response.Headers["x-request-count"] = (requestCount++).ToString();
|
||||
httpContext.Response.Headers["Cache-Control"] = "public, max-age=10";
|
||||
httpContext.Response.ContentLength = 10;
|
||||
return httpContext.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
Assert.Equal("1", await SendRequestAsync(address));
|
||||
Assert.Equal("2", await SendRequestAsync(address));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_WithoutContentType_Cached_OnWin7AndWin2008R2()
|
||||
{
|
||||
if (Utilities.IsWin8orLater)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var requestCount = 1;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
// httpContext.Response.ContentType = "some/thing"; // Http.Sys requires content-type for caching
|
||||
httpContext.Response.Headers["x-request-count"] = (requestCount++).ToString();
|
||||
httpContext.Response.Headers["Cache-Control"] = "public, max-age=10";
|
||||
httpContext.Response.ContentLength = 10;
|
||||
return httpContext.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
Assert.Equal("1", await SendRequestAsync(address));
|
||||
Assert.Equal("1", await SendRequestAsync(address));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_MaxAge_Cached()
|
||||
{
|
||||
|
|
@ -71,6 +128,25 @@ namespace Microsoft.AspNetCore.Server.HttpSys.FunctionalTests
|
|||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_MaxAgeHuge_Cached()
|
||||
{
|
||||
var requestCount = 1;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
httpContext.Response.ContentType = "some/thing"; // Http.Sys requires content-type for caching
|
||||
httpContext.Response.Headers["x-request-count"] = (requestCount++).ToString();
|
||||
httpContext.Response.Headers["Cache-Control"] = "public, max-age=" + int.MaxValue.ToString(CultureInfo.InvariantCulture);
|
||||
httpContext.Response.ContentLength = 10;
|
||||
return httpContext.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
Assert.Equal("1", await SendRequestAsync(address));
|
||||
Assert.Equal("1", await SendRequestAsync(address));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_SMaxAge_Cached()
|
||||
{
|
||||
|
|
@ -220,14 +296,152 @@ namespace Microsoft.AspNetCore.Server.HttpSys.FunctionalTests
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<string> SendRequestAsync(string uri)
|
||||
[ConditionalFact]
|
||||
public async Task Caching_Flush_NotCached()
|
||||
{
|
||||
var requestCount = 1;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
httpContext.Response.ContentType = "some/thing"; // Http.Sys requires content-type for caching
|
||||
httpContext.Response.Headers["x-request-count"] = (requestCount++).ToString();
|
||||
httpContext.Response.Headers["Cache-Control"] = "public, max-age=10";
|
||||
httpContext.Response.ContentLength = 10;
|
||||
httpContext.Response.Body.Flush();
|
||||
return httpContext.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
Assert.Equal("1", await SendRequestAsync(address));
|
||||
Assert.Equal("2", await SendRequestAsync(address));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_WriteFullContentLength_Cached()
|
||||
{
|
||||
var requestCount = 1;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, async httpContext =>
|
||||
{
|
||||
httpContext.Response.ContentType = "some/thing"; // Http.Sys requires content-type for caching
|
||||
httpContext.Response.Headers["x-request-count"] = (requestCount++).ToString();
|
||||
httpContext.Response.Headers["Cache-Control"] = "public, max-age=10";
|
||||
httpContext.Response.ContentLength = 10;
|
||||
await httpContext.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
// Http.Sys will add this for us
|
||||
Assert.Null(httpContext.Response.ContentLength);
|
||||
}))
|
||||
{
|
||||
Assert.Equal("1", await SendRequestAsync(address));
|
||||
Assert.Equal("1", await SendRequestAsync(address));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_SendFileNoContentLength_NotCached()
|
||||
{
|
||||
var requestCount = 1;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, async httpContext =>
|
||||
{
|
||||
httpContext.Response.ContentType = "some/thing"; // Http.Sys requires content-type for caching
|
||||
httpContext.Response.Headers["x-request-count"] = (requestCount++).ToString();
|
||||
httpContext.Response.Headers["Cache-Control"] = "public, max-age=10";
|
||||
await httpContext.Response.SendFileAsync(_absoluteFilePath, 0, null, CancellationToken.None);
|
||||
}))
|
||||
{
|
||||
Assert.Equal("1", await GetFileAsync(address));
|
||||
Assert.Equal("2", await GetFileAsync(address));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_SendFileWithFullContentLength_Cached()
|
||||
{
|
||||
var requestCount = 1;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, async httpContext =>
|
||||
{
|
||||
httpContext.Response.ContentType = "some/thing"; // Http.Sys requires content-type for caching
|
||||
httpContext.Response.Headers["x-request-count"] = (requestCount++).ToString();
|
||||
httpContext.Response.Headers["Cache-Control"] = "public, max-age=10";
|
||||
httpContext.Response.ContentLength = _fileLength;
|
||||
await httpContext.Response.SendFileAsync(_absoluteFilePath, 0, null, CancellationToken.None);
|
||||
}))
|
||||
{
|
||||
Assert.Equal("1", await GetFileAsync(address));
|
||||
Assert.Equal("1", await GetFileAsync(address));
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
public async Task Caching_VariousStatusCodes_Cached()
|
||||
{
|
||||
var requestCount = 1;
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, httpContext =>
|
||||
{
|
||||
httpContext.Response.ContentType = "some/thing"; // Http.Sys requires content-type for caching
|
||||
httpContext.Response.Headers["x-request-count"] = (requestCount++).ToString();
|
||||
httpContext.Response.Headers["Cache-Control"] = "public, max-age=10";
|
||||
var status = int.Parse(httpContext.Request.Path.Value.Substring(1));
|
||||
httpContext.Response.StatusCode = status;
|
||||
httpContext.Response.ContentLength = 10;
|
||||
return httpContext.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
// Http.Sys will cache almost any status code.
|
||||
for (int status = 200; status < 600; status++)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case 206: // 206 (Partial Content) is not cached
|
||||
case 407: // 407 (Proxy Authentication Required) makes CoreCLR's HttpClient throw
|
||||
continue;
|
||||
}
|
||||
requestCount = 1;
|
||||
try
|
||||
{
|
||||
Assert.Equal("1", await SendRequestAsync(address + status, status));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to get first response for {status}", ex);
|
||||
}
|
||||
try
|
||||
{
|
||||
Assert.Equal("1", await SendRequestAsync(address + status, status));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to get second response for {status}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> SendRequestAsync(string uri, int status = 200)
|
||||
{
|
||||
using (var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10) })
|
||||
{
|
||||
var response = await client.GetAsync(uri);
|
||||
Assert.Equal(status, (int)response.StatusCode);
|
||||
if (status != 204 && status != 304)
|
||||
{
|
||||
Assert.Equal(10, response.Content.Headers.ContentLength);
|
||||
Assert.Equal(new byte[10], await response.Content.ReadAsByteArrayAsync());
|
||||
}
|
||||
return response.Headers.GetValues("x-request-count").FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> GetFileAsync(string uri)
|
||||
{
|
||||
using (var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10) })
|
||||
{
|
||||
var response = await client.GetAsync(uri);
|
||||
Assert.Equal(200, (int)response.StatusCode);
|
||||
Assert.Equal(10, response.Content.Headers.ContentLength);
|
||||
Assert.Equal(new byte[10], await response.Content.ReadAsByteArrayAsync());
|
||||
Assert.Equal(_fileLength, response.Content.Headers.ContentLength);
|
||||
return response.Headers.GetValues("x-request-count").FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15);
|
||||
internal static readonly int WriteRetryLimit = 1000;
|
||||
|
||||
// Minimum support for Windows 7 is assumed.
|
||||
internal static readonly bool IsWin8orLater;
|
||||
|
||||
static Utilities()
|
||||
{
|
||||
var win8Version = new Version(6, 2);
|
||||
IsWin8orLater = (Environment.OSVersion.Version >= win8Version);
|
||||
}
|
||||
|
||||
internal static IServer CreateHttpServer(out string baseAddress, RequestDelegate app)
|
||||
{
|
||||
string root;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(SharedSourceRoot)NullScope.cs" />
|
||||
<Compile Include="$(SharedSourceRoot)Buffers.Testing\*.cs" />
|
||||
<Compile Include="$(KestrelSharedSourceRoot)test\*.cs" LinkBase="shared" />
|
||||
<Compile Include="$(RepositoryRoot)\src\Shared\Buffers.Testing\*.cs" />
|
||||
<Content Include="$(KestrelSharedSourceRoot)test\TestCertificates\*.pfx" LinkBase="shared\TestCertificates" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue