Merge aspnet/HttpAbstractions release/2.2
This commit is contained in:
commit
0f64aa5c01
|
|
@ -4,6 +4,24 @@
|
|||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<AspNetCoreBaselineVersion>2.2.0</AspNetCoreBaselineVersion>
|
||||
</PropertyGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Authentication.Abstractions-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Abstractions' ">
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.2.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Authentication.Core-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Core' ">
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Core' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.2.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Connections.Abstractions-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Connections.Abstractions' ">
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
|
|
@ -98,48 +116,48 @@
|
|||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Hosting.Abstractions-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.Abstractions' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.2.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Hosting.Server.Abstractions-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.Server.Abstractions' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.Server.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="[2.2.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Hosting.WindowsServices-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.WindowsServices' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.WindowsServices' AND '$(TargetFramework)' == 'net461' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting" Version="[2.2.0, )" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.WindowsServices' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="System.ServiceProcess.ServiceController" Version="[4.5.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Hosting-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="System.Diagnostics.DiagnosticSource" Version="[4.5.0, )" />
|
||||
<BaselinePackageReference Include="System.Reflection.Metadata" Version="[1.6.0, )" />
|
||||
</ItemGroup>
|
||||
|
|
@ -152,39 +170,39 @@
|
|||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Http.Abstractions-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Abstractions' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="System.Text.Encodings.Web" Version="[4.5.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Http.Extensions-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Extensions' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Extensions' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Net.Http.Headers" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Net.Http.Headers" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="System.Buffers" Version="[4.5.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Http.Features-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Features' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Features' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Primitives" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Primitives" Version="[2.2.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Http-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Net.Http.Headers" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.ObjectPool" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Net.Http.Headers" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.ObjectPool" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[2.2.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.JsonPatch-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.JsonPatch' ">
|
||||
|
|
@ -196,10 +214,10 @@
|
|||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Owin-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Owin' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Owin' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Http" Version="[2.2.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.Server.Kestrel.Core-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Server.Kestrel.Core' ">
|
||||
|
|
@ -291,11 +309,11 @@
|
|||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.TestHost-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.TestHost' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.TestHost' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.5.0, )" />
|
||||
<BaselinePackageReference Include="Microsoft.AspNetCore.Hosting" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.5.2, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.WebSockets-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.WebSockets' ">
|
||||
|
|
@ -309,18 +327,18 @@
|
|||
</ItemGroup>
|
||||
<!-- Package: Microsoft.AspNetCore.WebUtilities-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.WebUtilities' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.WebUtilities' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.Net.Http.Headers" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Net.Http.Headers" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="System.Text.Encodings.Web" Version="[4.5.0, )" />
|
||||
</ItemGroup>
|
||||
<!-- Package: Microsoft.Net.Http.Headers-->
|
||||
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.Net.Http.Headers' ">
|
||||
<BaselinePackageVersion>2.1.1</BaselinePackageVersion>
|
||||
<BaselinePackageVersion>2.2.0</BaselinePackageVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.Net.Http.Headers' AND '$(TargetFramework)' == 'netstandard2.0' ">
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Primitives" Version="[2.1.1, )" />
|
||||
<BaselinePackageReference Include="Microsoft.Extensions.Primitives" Version="[2.2.0, )" />
|
||||
<BaselinePackageReference Include="System.Buffers" Version="[4.5.0, )" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// Returns all of the AuthenticationTokens contained in the properties.
|
||||
/// </summary>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/> properties.</param>
|
||||
/// <returns>The authentication toekns.</returns>
|
||||
/// <returns>The authentication tokens.</returns>
|
||||
public static IEnumerable<AuthenticationToken> GetTokens(this AuthenticationProperties properties)
|
||||
{
|
||||
if (properties == null)
|
||||
|
|
@ -132,7 +132,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <param name="context">The <see cref="HttpContext"/> context.</param>
|
||||
/// <param name="tokenName">The name of the token.</param>
|
||||
/// <returns>The value of the token.</returns>
|
||||
public static Task<string> GetTokenAsync(this IAuthenticationService auth, HttpContext context, string tokenName)
|
||||
public static Task<string> GetTokenAsync(this IAuthenticationService auth, HttpContext context, string tokenName)
|
||||
=> auth.GetTokenAsync(context, scheme: null, tokenName: tokenName);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -49,6 +50,9 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
|
||||
private readonly IDictionary<string, AuthenticationScheme> _schemes;
|
||||
private readonly List<AuthenticationScheme> _requestHandlers;
|
||||
// Used as a safe return value for enumeration apis
|
||||
private IEnumerable<AuthenticationScheme> _schemesCopy = Array.Empty<AuthenticationScheme>();
|
||||
private IEnumerable<AuthenticationScheme> _requestHandlersCopy = Array.Empty<AuthenticationScheme>();
|
||||
|
||||
private Task<AuthenticationScheme> GetDefaultSchemeAsync()
|
||||
=> _options.DefaultScheme != null
|
||||
|
|
@ -102,7 +106,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <summary>
|
||||
/// Returns the scheme that will be used by default for <see cref="IAuthenticationService.SignOutAsync(HttpContext, string, AuthenticationProperties)"/>.
|
||||
/// This is typically specified via <see cref="AuthenticationOptions.DefaultSignOutScheme"/>.
|
||||
/// Otherwise this will fallback to <see cref="GetDefaultSignInSchemeAsync"/> if that supoorts sign out.
|
||||
/// Otherwise this will fallback to <see cref="GetDefaultSignInSchemeAsync"/> if that supports sign out.
|
||||
/// </summary>
|
||||
/// <returns>The scheme that will be used by default for <see cref="IAuthenticationService.SignOutAsync(HttpContext, string, AuthenticationProperties)"/>.</returns>
|
||||
public virtual Task<AuthenticationScheme> GetDefaultSignOutSchemeAsync()
|
||||
|
|
@ -123,7 +127,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// </summary>
|
||||
/// <returns>The schemes in priority order for request handling</returns>
|
||||
public virtual Task<IEnumerable<AuthenticationScheme>> GetRequestHandlerSchemesAsync()
|
||||
=> Task.FromResult<IEnumerable<AuthenticationScheme>>(_requestHandlers);
|
||||
=> Task.FromResult(_requestHandlersCopy);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a scheme for use by <see cref="IAuthenticationService"/>.
|
||||
|
|
@ -144,8 +148,10 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
if (typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType))
|
||||
{
|
||||
_requestHandlers.Add(scheme);
|
||||
_requestHandlersCopy = _requestHandlers.ToArray();
|
||||
}
|
||||
_schemes[scheme.Name] = scheme;
|
||||
_schemesCopy = _schemes.Values.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,13 +170,17 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
if (_schemes.ContainsKey(name))
|
||||
{
|
||||
var scheme = _schemes[name];
|
||||
_requestHandlers.Remove(scheme);
|
||||
if (_requestHandlers.Remove(scheme))
|
||||
{
|
||||
_requestHandlersCopy = _requestHandlers.ToArray();
|
||||
}
|
||||
_schemes.Remove(name);
|
||||
_schemesCopy = _schemes.Values.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Task<IEnumerable<AuthenticationScheme>> GetAllSchemesAsync()
|
||||
=> Task.FromResult<IEnumerable<AuthenticationScheme>>(_schemes.Values);
|
||||
=> Task.FromResult(_schemesCopy);
|
||||
}
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
{
|
||||
if (!StringSegment.IsNullOrEmpty(fileName))
|
||||
{
|
||||
FileName = Sanatize(fileName);
|
||||
FileName = Sanitize(fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -166,7 +166,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
|
||||
/// <summary>
|
||||
/// Sets the FileName parameter using encodings appropriate for MIME headers.
|
||||
/// The FileNameStar paraemter is removed.
|
||||
/// The FileNameStar parameter is removed.
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
public void SetMimeFileName(StringSegment fileName)
|
||||
|
|
@ -434,7 +434,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
// Replaces characters not suitable for HTTP headers with '_' rather than MIME encoding them.
|
||||
private StringSegment Sanatize(StringSegment input)
|
||||
private StringSegment Sanitize(StringSegment input)
|
||||
{
|
||||
var result = input;
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
}
|
||||
|
||||
// Since we never re-use a "found" value in 'y', we expecte 'alreadyFound' to have all fields set to 'true'.
|
||||
// Since we never re-use a "found" value in 'y', we expected 'alreadyFound' to have all fields set to 'true'.
|
||||
// Otherwise the two collections can't be equal and we should not get here.
|
||||
Contract.Assert(Contract.ForAll(alreadyFound, value => { return value; }),
|
||||
"Expected all values in 'alreadyFound' to be true since collections are considered equal.");
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
return HttpParseResult.NotParsed;
|
||||
}
|
||||
|
||||
// Quoted-char has 2 characters. Check wheter there are 2 chars left ('\' + char)
|
||||
// Quoted-char has 2 characters. Check whether there are 2 chars left ('\' + char)
|
||||
// If so, check whether the character is in the range 0-127. If not, it's an invalid value.
|
||||
if ((startIndex + 2 > input.Length) || (input[startIndex + 1] > 127))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -650,6 +650,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (set.Suffix.HasValue)
|
||||
{
|
||||
if (Suffix.HasValue)
|
||||
|
|
@ -663,7 +664,10 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
else
|
||||
{
|
||||
return set.SubType.Equals(SubType, StringComparison.OrdinalIgnoreCase);
|
||||
// If this subtype or suffix matches the subtype of the set,
|
||||
// it is considered a subtype.
|
||||
// Ex: application/json > application/val+json
|
||||
return MatchesEitherSubtypeOrSuffix(set);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -673,6 +677,12 @@ namespace Microsoft.Net.Http.Headers
|
|||
set.SubTypeWithoutSuffix.Equals(SubTypeWithoutSuffix, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private bool MatchesEitherSubtypeOrSuffix(MediaTypeHeaderValue set)
|
||||
{
|
||||
return set.SubType.Equals(SubType, StringComparison.OrdinalIgnoreCase) ||
|
||||
set.SubType.Equals(Suffix, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private bool MatchesParameters(MediaTypeHeaderValue set)
|
||||
{
|
||||
if (set._parameters != null && set._parameters.Count != 0)
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
current = current + fromLength;
|
||||
current = current + HttpRuleParser.GetWhitespaceLength(input, current);
|
||||
|
||||
// Afer the first value, the '-' character must follow.
|
||||
// After the first value, the '-' character must follow.
|
||||
if ((current == input.Length) || (input[current] != '-'))
|
||||
{
|
||||
// We need a '-' character otherwise this can't be a valid range.
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
{
|
||||
{ "inline", new ContentDispositionHeaderValue("inline") }, // @"This should be equivalent to not including the header at all."
|
||||
{ "inline;", new ContentDispositionHeaderValue("inline") },
|
||||
{ "inline;name=", new ContentDispositionHeaderValue("inline") { Parameters = { new NameValueHeaderValue("name", "") } } }, // TODO: passing in a null value causes a strange assert on CoreCLR before the test even starts. Not reproducable in the body of a test.
|
||||
{ "inline;name=", new ContentDispositionHeaderValue("inline") { Parameters = { new NameValueHeaderValue("name", "") } } }, // TODO: passing in a null value causes a strange assert on CoreCLR before the test even starts. Not reproducible in the body of a test.
|
||||
{ "inline;name=value", new ContentDispositionHeaderValue("inline") { Name = "value" } },
|
||||
{ "inline;name=value;", new ContentDispositionHeaderValue("inline") { Name = "value" } },
|
||||
{ "inline;name=value;", new ContentDispositionHeaderValue("inline") { Name = "value" } },
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
public void CookieHeaderValue_ParseList_ExcludesInvalidValues(IList<CookieHeaderValue> cookies, string[] input)
|
||||
{
|
||||
var results = CookieHeaderValue.ParseList(input);
|
||||
// ParseList aways returns a list, even if empty. TryParseList may return null (via out).
|
||||
// ParseList always returns a list, even if empty. TryParseList may return null (via out).
|
||||
Assert.Equal(cookies ?? new List<CookieHeaderValue>(), results);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseList_WithSomeInvlaidValues_ExcludesInvalidValues()
|
||||
public void ParseList_WithSomeInvalidValues_ExcludesInvalidValues()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -433,7 +433,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseStrictList_WithSomeInvlaidValues_Throws()
|
||||
public void ParseStrictList_WithSomeInvalidValues_Throws()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -451,7 +451,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseList_WithSomeInvlaidValues_ExcludesInvalidValues()
|
||||
public void TryParseList_WithSomeInvalidValues_ExcludesInvalidValues()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -482,7 +482,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseStrictList_WithSomeInvlaidValues_ReturnsFalse()
|
||||
public void TryParseStrictList_WithSomeInvalidValues_ReturnsFalse()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -617,7 +617,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseList_WithSomeInvlaidValues_IgnoresInvalidValues()
|
||||
public void ParseList_WithSomeInvalidValues_IgnoresInvalidValues()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -640,7 +640,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseStrictList_WithSomeInvlaidValues_Throws()
|
||||
public void ParseStrictList_WithSomeInvalidValues_Throws()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -651,7 +651,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseList_WithSomeInvlaidValues_IgnoresInvalidValues()
|
||||
public void TryParseList_WithSomeInvalidValues_IgnoresInvalidValues()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -676,7 +676,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseStrictList_WithSomeInvlaidValues_ReturnsFalse()
|
||||
public void TryParseStrictList_WithSomeInvalidValues_ReturnsFalse()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -750,6 +750,8 @@ namespace Microsoft.Net.Http.Headers
|
|||
[InlineData("application/entity+json", "application/entity+json")]
|
||||
[InlineData("application/*+json", "application/entity+json")]
|
||||
[InlineData("application/*+json", "application/*+json")]
|
||||
[InlineData("application/json", "application/problem+json")]
|
||||
[InlineData("application/json", "application/vnd.restful+json")]
|
||||
[InlineData("application/*", "application/*+JSON")]
|
||||
[InlineData("application/vnd.github+json", "application/vnd.github+json")]
|
||||
[InlineData("application/*", "application/entity+JSON")]
|
||||
|
|
@ -774,6 +776,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
[InlineData("application/*+*", "application/json")]
|
||||
[InlineData("application/entity+*", "application/entity+json")] // We don't allow suffixes to be wildcards
|
||||
[InlineData("application/*+*", "application/entity+json")] // We don't allow suffixes to be wildcards
|
||||
[InlineData("application/entity+json", "application/entity")]
|
||||
public void IsSubSetOfWithSuffixes_NegativeCases(string set, string subset)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Copy_NameOnly_SuccesfullyCopied()
|
||||
public void Copy_NameOnly_SuccessfullyCopied()
|
||||
{
|
||||
var pair0 = new NameValueHeaderValue("name");
|
||||
var pair1 = pair0.Copy();
|
||||
|
|
@ -95,7 +95,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Copy_NameAndValue_SuccesfullyCopied()
|
||||
public void Copy_NameAndValue_SuccessfullyCopied()
|
||||
{
|
||||
var pair0 = new NameValueHeaderValue("name", "value");
|
||||
var pair1 = pair0.Copy();
|
||||
|
|
@ -466,7 +466,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseList_WithSomeInvlaidValues_ExcludesInvalidValues()
|
||||
public void ParseList_WithSomeInvalidValues_ExcludesInvalidValues()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -502,7 +502,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseStrictList_WithSomeInvlaidValues_Throws()
|
||||
public void ParseStrictList_WithSomeInvalidValues_Throws()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -520,7 +520,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseList_WithSomeInvlaidValues_ExcludesInvalidValues()
|
||||
public void TryParseList_WithSomeInvalidValues_ExcludesInvalidValues()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -557,7 +557,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseStrictList_WithSomeInvlaidValues_ReturnsFalse()
|
||||
public void TryParseStrictList_WithSomeInvalidValues_ReturnsFalse()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ToString_UseDifferentrangeConditions_AllSerializedCorrectly()
|
||||
public void ToString_UseDifferentRangeConditions_AllSerializedCorrectly()
|
||||
{
|
||||
var rangeCondition = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"x\""));
|
||||
Assert.Equal("\"x\"", rangeCondition.ToString());
|
||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetHashCode_UseSameAndDifferentrangeConditions_SameOrDifferentHashCodes()
|
||||
public void GetHashCode_UseSameAndDifferentRangeConditions_SameOrDifferentHashCodes()
|
||||
{
|
||||
var rangeCondition1 = new RangeConditionHeaderValue("\"x\"");
|
||||
var rangeCondition2 = new RangeConditionHeaderValue(new EntityTagHeaderValue("\"x\""));
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
public void SetCookieHeaderValue_ParseList_ExcludesInvalidValues(IList<SetCookieHeaderValue> cookies, string[] input)
|
||||
{
|
||||
var results = SetCookieHeaderValue.ParseList(input);
|
||||
// ParseList aways returns a list, even if empty. TryParseList may return null (via out).
|
||||
// ParseList always returns a list, even if empty. TryParseList may return null (via out).
|
||||
Assert.Equal(cookies ?? new List<SetCookieHeaderValue>(), results);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -354,7 +354,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseList_WithSomeInvlaidValues_IgnoresInvalidValues()
|
||||
public void ParseList_WithSomeInvalidValues_IgnoresInvalidValues()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -392,7 +392,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ParseStrictList_WithSomeInvlaidValues_Throws()
|
||||
public void ParseStrictList_WithSomeInvalidValues_Throws()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -412,7 +412,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseList_WithSomeInvlaidValues_IgnoresInvalidValues()
|
||||
public void TryParseList_WithSomeInvalidValues_IgnoresInvalidValues()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
@ -451,7 +451,7 @@ namespace Microsoft.Net.Http.Headers
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseStrictList_WithSomeInvlaidValues_ReturnsFalse()
|
||||
public void TryParseStrictList_WithSomeInvalidValues_ReturnsFalse()
|
||||
{
|
||||
var inputs = new[]
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Http;
|
|||
namespace Microsoft.AspNetCore.Builder.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Respresents a middleware that maps a request path to a sub-request pipeline.
|
||||
/// Represents a middleware that maps a request path to a sub-request pipeline.
|
||||
/// </summary>
|
||||
public class MapMiddleware
|
||||
{
|
||||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Builder.Extensions
|
|||
private readonly MapOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instace of <see cref="MapMiddleware"/>.
|
||||
/// Creates a new instance of <see cref="MapMiddleware"/>.
|
||||
/// </summary>
|
||||
/// <param name="next">The delegate representing the next middleware in the request pipeline.</param>
|
||||
/// <param name="options">The middleware options.</param>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Http;
|
|||
namespace Microsoft.AspNetCore.Builder.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Respresents a middleware that runs a sub-request pipeline when a given predicate is matched.
|
||||
/// Represents a middleware that runs a sub-request pipeline when a given predicate is matched.
|
||||
/// </summary>
|
||||
public class MapWhenMiddleware
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Http
|
||||
{
|
||||
public static class ResponseTrailerExtensions
|
||||
{
|
||||
private const string Trailer = "Trailer";
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given trailer name to the 'Trailer' response header. This must happen before the response headers are sent.
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="trailerName"></param>
|
||||
public static void DeclareTrailer(this HttpResponse response, string trailerName)
|
||||
{
|
||||
response.Headers.AppendCommaSeparatedValues(Trailer, trailerName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the server supports sending trailer headers for this response.
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SupportsTrailers(this HttpResponse response)
|
||||
{
|
||||
var feature = response.HttpContext.Features.Get<IHttpResponseTrailersFeature>();
|
||||
return feature?.Trailers != null && !feature.Trailers.IsReadOnly;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given trailer header to the trailers collection to be sent at the end of the response body.
|
||||
/// Check <see cref="SupportsTrailers" /> or an InvalidOperationException may be thrown.
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <param name="trailerName"></param>
|
||||
/// <param name="trailerValues"></param>
|
||||
public static void AppendTrailer(this HttpResponse response, string trailerName, StringValues trailerValues)
|
||||
{
|
||||
var feature = response.HttpContext.Features.Get<IHttpResponseTrailersFeature>();
|
||||
if (feature?.Trailers == null || feature.Trailers.IsReadOnly)
|
||||
{
|
||||
throw new InvalidOperationException("Trailers are not supported for this response.");
|
||||
}
|
||||
|
||||
feature.Trailers.Append(trailerName, trailerValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,13 +74,13 @@ namespace Microsoft.AspNetCore.Builder
|
|||
throw new InvalidOperationException(Resources.FormatException_UseMiddlewareNoInvokeMethod(InvokeMethodName, InvokeAsyncMethodName, middleware));
|
||||
}
|
||||
|
||||
var methodinfo = invokeMethods[0];
|
||||
if (!typeof(Task).IsAssignableFrom(methodinfo.ReturnType))
|
||||
var methodInfo = invokeMethods[0];
|
||||
if (!typeof(Task).IsAssignableFrom(methodInfo.ReturnType))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatException_UseMiddlewareNonTaskReturnType(InvokeMethodName, InvokeAsyncMethodName, nameof(Task)));
|
||||
}
|
||||
|
||||
var parameters = methodinfo.GetParameters();
|
||||
var parameters = methodInfo.GetParameters();
|
||||
if (parameters.Length == 0 || parameters[0].ParameterType != typeof(HttpContext))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatException_UseMiddlewareNoParameters(InvokeMethodName, InvokeAsyncMethodName, nameof(HttpContext)));
|
||||
|
|
@ -92,10 +92,10 @@ namespace Microsoft.AspNetCore.Builder
|
|||
var instance = ActivatorUtilities.CreateInstance(app.ApplicationServices, middleware, ctorArgs);
|
||||
if (parameters.Length == 1)
|
||||
{
|
||||
return (RequestDelegate)methodinfo.CreateDelegate(typeof(RequestDelegate), instance);
|
||||
return (RequestDelegate)methodInfo.CreateDelegate(typeof(RequestDelegate), instance);
|
||||
}
|
||||
|
||||
var factory = Compile<object>(methodinfo, parameters);
|
||||
var factory = Compile<object>(methodInfo, parameters);
|
||||
|
||||
return context =>
|
||||
{
|
||||
|
|
@ -142,13 +142,13 @@ namespace Microsoft.AspNetCore.Builder
|
|||
});
|
||||
}
|
||||
|
||||
private static Func<T, HttpContext, IServiceProvider, Task> Compile<T>(MethodInfo methodinfo, ParameterInfo[] parameters)
|
||||
private static Func<T, HttpContext, IServiceProvider, Task> Compile<T>(MethodInfo methodInfo, ParameterInfo[] parameters)
|
||||
{
|
||||
// If we call something like
|
||||
//
|
||||
// public class Middleware
|
||||
// {
|
||||
// public Task Invoke(HttpContext context, ILoggerFactory loggeryFactory)
|
||||
// public Task Invoke(HttpContext context, ILoggerFactory loggerFactory)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
|
|
@ -158,14 +158,14 @@ namespace Microsoft.AspNetCore.Builder
|
|||
// We'll end up with something like this:
|
||||
// Generic version:
|
||||
//
|
||||
// Task Invoke(Middleware instance, HttpContext httpContext, IServiceprovider provider)
|
||||
// Task Invoke(Middleware instance, HttpContext httpContext, IServiceProvider provider)
|
||||
// {
|
||||
// return instance.Invoke(httpContext, (ILoggerFactory)UseMiddlewareExtensions.GetService(provider, typeof(ILoggerFactory));
|
||||
// }
|
||||
|
||||
// Non generic version:
|
||||
//
|
||||
// Task Invoke(object instance, HttpContext httpContext, IServiceprovider provider)
|
||||
// Task Invoke(object instance, HttpContext httpContext, IServiceProvider provider)
|
||||
// {
|
||||
// return ((Middleware)instance).Invoke(httpContext, (ILoggerFactory)UseMiddlewareExtensions.GetService(provider, typeof(ILoggerFactory));
|
||||
// }
|
||||
|
|
@ -190,7 +190,7 @@ namespace Microsoft.AspNetCore.Builder
|
|||
{
|
||||
providerArg,
|
||||
Expression.Constant(parameterType, typeof(Type)),
|
||||
Expression.Constant(methodinfo.DeclaringType, typeof(Type))
|
||||
Expression.Constant(methodInfo.DeclaringType, typeof(Type))
|
||||
};
|
||||
|
||||
var getServiceCall = Expression.Call(GetServiceInfo, parameterTypeExpression);
|
||||
|
|
@ -198,12 +198,12 @@ namespace Microsoft.AspNetCore.Builder
|
|||
}
|
||||
|
||||
Expression middlewareInstanceArg = instanceArg;
|
||||
if (methodinfo.DeclaringType != typeof(T))
|
||||
if (methodInfo.DeclaringType != typeof(T))
|
||||
{
|
||||
middlewareInstanceArg = Expression.Convert(middlewareInstanceArg, methodinfo.DeclaringType);
|
||||
middlewareInstanceArg = Expression.Convert(middlewareInstanceArg, methodInfo.DeclaringType);
|
||||
}
|
||||
|
||||
var body = Expression.Call(middlewareInstanceArg, methodinfo, methodArguments);
|
||||
var body = Expression.Call(middlewareInstanceArg, methodInfo, methodArguments);
|
||||
|
||||
var lambda = Expression.Lambda<Func<T, HttpContext, IServiceProvider, Task>>(body, instanceArg, httpContextArg, providerArg);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Builder.Extensions
|
|||
private readonly PathString _pathBase;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instace of <see cref="UsePathBaseMiddleware"/>.
|
||||
/// Creates a new instance of <see cref="UsePathBaseMiddleware"/>.
|
||||
/// </summary>
|
||||
/// <param name="next">The delegate representing the next middleware in the request pipeline.</param>
|
||||
/// <param name="pathBase">The path base to extract.</param>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,12 @@ namespace Microsoft.AspNetCore.Http
|
|||
/// <param name="port">A positive, greater than 0 value representing the port in the host string.</param>
|
||||
public HostString(string host, int port)
|
||||
{
|
||||
if(port <= 0)
|
||||
if (host == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(host));
|
||||
}
|
||||
|
||||
if (port <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(port), Resources.Exception_PortMustBeGreaterThanZero);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
private readonly string _value;
|
||||
|
||||
/// <summary>
|
||||
/// Initalize the path string with a given value. This value must be in unescaped format. Use
|
||||
/// Initialize the path string with a given value. This value must be in unescaped format. Use
|
||||
/// PathString.FromUriComponent(value) if you have a path value which is in an escaped format.
|
||||
/// </summary>
|
||||
/// <param name="value">The unescaped path to be assigned to the Value property.</param>
|
||||
|
|
@ -117,7 +117,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
{
|
||||
if (!requiresEscaping)
|
||||
{
|
||||
// the current segument doesn't require escape
|
||||
// the current segment doesn't require escape
|
||||
if (buffer == null)
|
||||
{
|
||||
buffer = new StringBuilder(_value.Length * 3);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Builder.Extensions
|
|||
|
||||
public class MapPredicateMiddlewareTests
|
||||
{
|
||||
private static readonly Predicate NotImplementedPredicate = new Predicate(envionment => { throw new NotImplementedException(); });
|
||||
private static readonly Predicate NotImplementedPredicate = new Predicate(environment => { throw new NotImplementedException(); });
|
||||
|
||||
private static Task Success(HttpContext context)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,10 +59,10 @@ namespace Microsoft.AspNetCore.Http.Abstractions
|
|||
[InlineData("", "value", "?=value")]
|
||||
[InlineData("", "", "?=")]
|
||||
[InlineData("", null, "?=")]
|
||||
public void CreateNameValue_Success(string name, string value, string exepcted)
|
||||
public void CreateNameValue_Success(string name, string value, string expected)
|
||||
{
|
||||
var query = QueryString.Create(name, value);
|
||||
Assert.Equal(exepcted, query.Value);
|
||||
Assert.Equal(expected, query.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void UseMiddleware_MutlipleInvokeMethods_ThrowsException()
|
||||
public void UseMiddleware_MultipleInvokeMethods_ThrowsException()
|
||||
{
|
||||
var builder = new ApplicationBuilder(new DummyServiceProvider());
|
||||
builder.UseMiddleware(typeof(MiddlewareMultipleInvokesStub));
|
||||
|
|
@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void UseMiddleware_MutlipleInvokeAsyncMethods_ThrowsException()
|
||||
public void UseMiddleware_MultipleInvokeAsyncMethods_ThrowsException()
|
||||
{
|
||||
var builder = new ApplicationBuilder(new DummyServiceProvider());
|
||||
builder.UseMiddleware(typeof(MiddlewareMultipleInvokeAsyncStub));
|
||||
|
|
@ -116,7 +116,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void UseMiddleware_MutlipleInvokeAndInvokeAsyncMethods_ThrowsException()
|
||||
public void UseMiddleware_MultipleInvokeAndInvokeAsyncMethods_ThrowsException()
|
||||
{
|
||||
var builder = new ApplicationBuilder(new DummyServiceProvider());
|
||||
builder.UseMiddleware(typeof(MiddlewareMultipleInvokeAndInvokeAsyncStub));
|
||||
|
|
@ -153,7 +153,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void UseMiddlewareWithIvokeWithOutAndRefThrows()
|
||||
public void UseMiddlewareWithInvokeWithOutAndRefThrows()
|
||||
{
|
||||
var mockServiceProvider = new DummyServiceProvider();
|
||||
var builder = new ApplicationBuilder(mockServiceProvider);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Http.Features
|
|||
}
|
||||
else if (flush)
|
||||
{
|
||||
// Cache was cleared, but item retrived from current Collection for version
|
||||
// Cache was cleared, but item retrieved from current Collection for version
|
||||
// so use passed in revision rather than making another virtual call
|
||||
Revision = revision;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Http.Features
|
||||
{
|
||||
public interface IHttpResponseTrailersFeature
|
||||
{
|
||||
IHeaderDictionary Trailers { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -131,6 +131,11 @@ namespace Microsoft.AspNetCore.Http.Features
|
|||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (_request.ContentLength == 0)
|
||||
{
|
||||
return FormCollection.Empty;
|
||||
}
|
||||
|
||||
if (_options.BufferBody)
|
||||
{
|
||||
_request.EnableRewind(_options.MemoryBufferThreshold, _options.BufferBodyLengthLimit);
|
||||
|
|
@ -221,7 +226,7 @@ namespace Microsoft.AspNetCore.Http.Features
|
|||
//
|
||||
// value
|
||||
|
||||
// Do not limit the key name length here because the mulipart headers length limit is already in effect.
|
||||
// Do not limit the key name length here because the multipart headers length limit is already in effect.
|
||||
var key = formDataSection.Name;
|
||||
var value = await formDataSection.GetValueAsync();
|
||||
|
||||
|
|
|
|||
|
|
@ -7,17 +7,20 @@ namespace Microsoft.AspNetCore.Http
|
|||
{
|
||||
public class HttpContextAccessor : IHttpContextAccessor
|
||||
{
|
||||
private static AsyncLocal<HttpContext> _httpContextCurrent = new AsyncLocal<HttpContext>();
|
||||
private static AsyncLocal<(string traceIdentifier, HttpContext context)> _httpContextCurrent = new AsyncLocal<(string traceIdentifier, HttpContext context)>();
|
||||
|
||||
public HttpContext HttpContext
|
||||
{
|
||||
get
|
||||
{
|
||||
return _httpContextCurrent.Value;
|
||||
var value = _httpContextCurrent.Value;
|
||||
// Only return the context if the stored request id matches the stored trace identifier
|
||||
// context.TraceIdentifier is cleared by HttpContextFactory.Dispose.
|
||||
return value.traceIdentifier == value.context?.TraceIdentifier ? value.context : null;
|
||||
}
|
||||
set
|
||||
{
|
||||
_httpContextCurrent.Value = value;
|
||||
_httpContextCurrent.Value = (value?.TraceIdentifier, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ namespace Microsoft.AspNetCore.Http
|
|||
{
|
||||
_httpContextAccessor.HttpContext = null;
|
||||
}
|
||||
|
||||
// Null out the TraceIdentifier here as a sign that this request is done,
|
||||
// the HttpContextAccessor implementation relies on this to detect that the request is over
|
||||
httpContext.TraceIdentifier = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -157,7 +157,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
features.Set<IHttpResponseFeature>(new HttpResponseFeature());
|
||||
features.Set<IHttpWebSocketFeature>(new TestHttpWebSocketFeature());
|
||||
|
||||
// featurecollection is set. all cached interfaces are null.
|
||||
// FeatureCollection is set. all cached interfaces are null.
|
||||
var context = new DefaultHttpContext(features);
|
||||
TestAllCachedFeaturesAreNull(context, features);
|
||||
Assert.Equal(3, features.Count());
|
||||
|
|
@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
TestAllCachedFeaturesAreSet(context, features);
|
||||
Assert.NotEqual(3, features.Count());
|
||||
|
||||
// featurecollection is null. and all cached interfaces are null.
|
||||
// FeatureCollection is null. and all cached interfaces are null.
|
||||
// only top level is tested because child objects are inaccessible.
|
||||
context.Uninitialize();
|
||||
TestCachedFeaturesAreNull(context, null);
|
||||
|
|
@ -177,7 +177,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
newFeatures.Set<IHttpResponseFeature>(new HttpResponseFeature());
|
||||
newFeatures.Set<IHttpWebSocketFeature>(new TestHttpWebSocketFeature());
|
||||
|
||||
// featurecollection is set to newFeatures. all cached interfaces are null.
|
||||
// FeatureCollection is set to newFeatures. all cached interfaces are null.
|
||||
context.Initialize(newFeatures);
|
||||
TestAllCachedFeaturesAreNull(context, newFeatures);
|
||||
Assert.Equal(3, newFeatures.Count());
|
||||
|
|
|
|||
|
|
@ -12,6 +12,23 @@ namespace Microsoft.AspNetCore.Http.Features
|
|||
{
|
||||
public class FormFeatureTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ReadFormAsync_0ContentLength_ReturnsEmptyForm()
|
||||
{
|
||||
var context = new DefaultHttpContext();
|
||||
var responseFeature = new FakeResponseFeature();
|
||||
context.Features.Set<IHttpResponseFeature>(responseFeature);
|
||||
context.Request.ContentType = MultipartContentType;
|
||||
context.Request.ContentLength = 0;
|
||||
|
||||
var formFeature = new FormFeature(context.Request, new FormOptions());
|
||||
context.Features.Set<IFormFeature>(formFeature);
|
||||
|
||||
var formCollection = await context.Request.ReadFormAsync();
|
||||
|
||||
Assert.Same(FormCollection.Empty, formCollection);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void EmtpyQuotedHeaderSegmentsAreIgnored()
|
||||
public void EmptyQuotedHeaderSegmentsAreIgnored()
|
||||
{
|
||||
var headers = new HeaderDictionary(
|
||||
new Dictionary<string, StringValues>(StringComparer.OrdinalIgnoreCase)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
using System.Reflection;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Http
|
||||
{
|
||||
public class HttpContextAccessorTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task HttpContextAccessor_GettingHttpContextReturnsHttpContext()
|
||||
{
|
||||
var accessor = new HttpContextAccessor();
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
context.TraceIdentifier = "1";
|
||||
accessor.HttpContext = context;
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
Assert.Same(context, accessor.HttpContext);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HttpContextAccessor_GettingHttpContextWithOutSettingReturnsNull()
|
||||
{
|
||||
var accessor = new HttpContextAccessor();
|
||||
|
||||
Assert.Null(accessor.HttpContext);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HttpContextAccessor_GettingHttpContextReturnsNullHttpContextIfSetToNull()
|
||||
{
|
||||
var accessor = new HttpContextAccessor();
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
context.TraceIdentifier = "1";
|
||||
accessor.HttpContext = context;
|
||||
|
||||
var checkAsyncFlowTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var waitForNullTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var afterNullCheckTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
ThreadPool.QueueUserWorkItem(async _ =>
|
||||
{
|
||||
// The HttpContext flows with the execution context
|
||||
Assert.Same(context, accessor.HttpContext);
|
||||
|
||||
checkAsyncFlowTcs.SetResult(null);
|
||||
|
||||
await waitForNullTcs.Task;
|
||||
|
||||
try
|
||||
{
|
||||
Assert.Null(accessor.HttpContext);
|
||||
|
||||
afterNullCheckTcs.SetResult(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
afterNullCheckTcs.SetException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
await checkAsyncFlowTcs.Task;
|
||||
|
||||
// Null out the accessor
|
||||
accessor.HttpContext = null;
|
||||
context.TraceIdentifier = null;
|
||||
|
||||
waitForNullTcs.SetResult(null);
|
||||
|
||||
Assert.Null(accessor.HttpContext);
|
||||
|
||||
await afterNullCheckTcs.Task;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HttpContextAccessor_GettingHttpContextReturnsNullHttpContextIfDifferentTraceIdentifier()
|
||||
{
|
||||
var accessor = new HttpContextAccessor();
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
context.TraceIdentifier = "1";
|
||||
accessor.HttpContext = context;
|
||||
|
||||
var checkAsyncFlowTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var waitForNullTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var afterNullCheckTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
ThreadPool.QueueUserWorkItem(async _ =>
|
||||
{
|
||||
// The HttpContext flows with the execution context
|
||||
Assert.Same(context, accessor.HttpContext);
|
||||
|
||||
checkAsyncFlowTcs.SetResult(null);
|
||||
|
||||
await waitForNullTcs.Task;
|
||||
|
||||
try
|
||||
{
|
||||
Assert.Null(accessor.HttpContext);
|
||||
|
||||
afterNullCheckTcs.SetResult(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
afterNullCheckTcs.SetException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
await checkAsyncFlowTcs.Task;
|
||||
|
||||
// Reset the trace identifier on the first request
|
||||
context.TraceIdentifier = null;
|
||||
|
||||
// Set a new http context
|
||||
var context2 = new DefaultHttpContext();
|
||||
context2.TraceIdentifier = "2";
|
||||
accessor.HttpContext = context2;
|
||||
|
||||
waitForNullTcs.SetResult(null);
|
||||
|
||||
Assert.Same(context2, accessor.HttpContext);
|
||||
|
||||
await afterNullCheckTcs.Task;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HttpContextAccessor_GettingHttpContextDoesNotFlowIfAccessorSetToNull()
|
||||
{
|
||||
var accessor = new HttpContextAccessor();
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
context.TraceIdentifier = "1";
|
||||
accessor.HttpContext = context;
|
||||
|
||||
var checkAsyncFlowTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
accessor.HttpContext = null;
|
||||
|
||||
ThreadPool.QueueUserWorkItem(_ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// The HttpContext flows with the execution context
|
||||
Assert.Null(accessor.HttpContext);
|
||||
checkAsyncFlowTcs.SetResult(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
checkAsyncFlowTcs.SetException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
await checkAsyncFlowTcs.Task;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HttpContextAccessor_GettingHttpContextDoesNotFlowIfExecutionContextDoesNotFlow()
|
||||
{
|
||||
var accessor = new HttpContextAccessor();
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
context.TraceIdentifier = "1";
|
||||
accessor.HttpContext = context;
|
||||
|
||||
var checkAsyncFlowTcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
ThreadPool.UnsafeQueueUserWorkItem(_ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// The HttpContext flows with the execution context
|
||||
Assert.Null(accessor.HttpContext);
|
||||
checkAsyncFlowTcs.SetResult(null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
checkAsyncFlowTcs.SetException(ex);
|
||||
}
|
||||
}, null);
|
||||
|
||||
await checkAsyncFlowTcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,27 @@ namespace Microsoft.AspNetCore.Http
|
|||
var context = contextFactory.Create(new FeatureCollection());
|
||||
|
||||
// Assert
|
||||
Assert.True(ReferenceEquals(context, accessor.HttpContext));
|
||||
Assert.Same(context, accessor.HttpContext);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DisposeHttpContextSetsHttpContextAccessorToNull()
|
||||
{
|
||||
// Arrange
|
||||
var accessor = new HttpContextAccessor();
|
||||
var contextFactory = new HttpContextFactory(Options.Create(new FormOptions()), accessor);
|
||||
|
||||
// Act
|
||||
var context = contextFactory.Create(new FeatureCollection());
|
||||
var traceIdentifier = context.TraceIdentifier;
|
||||
|
||||
// Assert
|
||||
Assert.Same(context, accessor.HttpContext);
|
||||
|
||||
contextFactory.Dispose(context);
|
||||
|
||||
Assert.Null(accessor.HttpContext);
|
||||
Assert.NotEqual(traceIdentifier, context.TraceIdentifier);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@ namespace Microsoft.AspNetCore.Http.Tests
|
|||
{
|
||||
var headers = new HeaderDictionary();
|
||||
var cookies = new ResponseCookies(headers, null);
|
||||
var testcookie = "TestCookie";
|
||||
var testCookie = "TestCookie";
|
||||
|
||||
cookies.Delete(testcookie);
|
||||
cookies.Delete(testCookie);
|
||||
|
||||
var cookieHeaderValues = headers[HeaderNames.SetCookie];
|
||||
Assert.Single(cookieHeaderValues);
|
||||
Assert.StartsWith(testcookie, cookieHeaderValues[0]);
|
||||
Assert.StartsWith(testCookie, cookieHeaderValues[0]);
|
||||
Assert.Contains("path=/", cookieHeaderValues[0]);
|
||||
Assert.Contains("expires=Thu, 01 Jan 1970 00:00:00 GMT", cookieHeaderValues[0]);
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Http.Tests
|
|||
{
|
||||
var headers = new HeaderDictionary();
|
||||
var cookies = new ResponseCookies(headers, null);
|
||||
var testcookie = "TestCookie";
|
||||
var testCookie = "TestCookie";
|
||||
var time = new DateTimeOffset(2000, 1, 1, 1, 1, 1, 1, TimeSpan.Zero);
|
||||
var options = new CookieOptions
|
||||
{
|
||||
|
|
@ -43,11 +43,11 @@ namespace Microsoft.AspNetCore.Http.Tests
|
|||
SameSite = SameSiteMode.Lax
|
||||
};
|
||||
|
||||
cookies.Delete(testcookie, options);
|
||||
cookies.Delete(testCookie, options);
|
||||
|
||||
var cookieHeaderValues = headers[HeaderNames.SetCookie];
|
||||
Assert.Single(cookieHeaderValues);
|
||||
Assert.StartsWith(testcookie, cookieHeaderValues[0]);
|
||||
Assert.StartsWith(testCookie, cookieHeaderValues[0]);
|
||||
Assert.Contains("path=/", cookieHeaderValues[0]);
|
||||
Assert.Contains("expires=Thu, 01 Jan 1970 00:00:00 GMT", cookieHeaderValues[0]);
|
||||
Assert.Contains("secure", cookieHeaderValues[0]);
|
||||
|
|
@ -60,14 +60,14 @@ namespace Microsoft.AspNetCore.Http.Tests
|
|||
{
|
||||
var headers = new HeaderDictionary();
|
||||
var cookies = new ResponseCookies(headers, null);
|
||||
var testcookie = "TestCookie";
|
||||
var testCookie = "TestCookie";
|
||||
|
||||
cookies.Append(testcookie, testcookie);
|
||||
cookies.Delete(testcookie);
|
||||
cookies.Append(testCookie, testCookie);
|
||||
cookies.Delete(testCookie);
|
||||
|
||||
var cookieHeaderValues = headers[HeaderNames.SetCookie];
|
||||
Assert.Single(cookieHeaderValues);
|
||||
Assert.StartsWith(testcookie, cookieHeaderValues[0]);
|
||||
Assert.StartsWith(testCookie, cookieHeaderValues[0]);
|
||||
Assert.Contains("path=/", cookieHeaderValues[0]);
|
||||
Assert.Contains("expires=Thu, 01 Jan 1970 00:00:00 GMT", cookieHeaderValues[0]);
|
||||
}
|
||||
|
|
@ -80,9 +80,9 @@ namespace Microsoft.AspNetCore.Http.Tests
|
|||
var cookieOptions = new CookieOptions();
|
||||
var maxAgeTime = TimeSpan.FromHours(1);
|
||||
cookieOptions.MaxAge = TimeSpan.FromHours(1);
|
||||
var testcookie = "TestCookie";
|
||||
var testCookie = "TestCookie";
|
||||
|
||||
cookies.Append(testcookie, testcookie, cookieOptions);
|
||||
cookies.Append(testCookie, testCookie, cookieOptions);
|
||||
|
||||
var cookieHeaderValues = headers[HeaderNames.SetCookie];
|
||||
Assert.Single(cookieHeaderValues);
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ namespace Microsoft.AspNetCore.Builder
|
|||
{
|
||||
Func<RequestDelegate, RequestDelegate> middleware1 = next1 =>
|
||||
{
|
||||
AppFunc exitMiddlware = env =>
|
||||
AppFunc exitMiddleware = env =>
|
||||
{
|
||||
return next1((HttpContext)env[typeof(HttpContext).FullName]);
|
||||
};
|
||||
var app = middleware(exitMiddlware);
|
||||
var app = middleware(exitMiddleware);
|
||||
return httpContext =>
|
||||
{
|
||||
// Use the existing OWIN env if there is one.
|
||||
|
|
|
|||
|
|
@ -103,10 +103,10 @@ namespace Microsoft.AspNetCore.Owin
|
|||
// 2. The middleware inserts an alternate Accept signature into the OWIN environment.
|
||||
// 3. The middleware invokes Next and stores Next's Task locally. It then returns an alternate Task to the server.
|
||||
// 4. The OwinFeatureCollection adapts the alternate Accept signature to IHttpWebSocketFeature.AcceptAsync.
|
||||
// 5. A component later in the pipleline invokes IHttpWebSocketFeature.AcceptAsync (mapped to AcceptWebSocketAsync).
|
||||
// 5. A component later in the pipeline invokes IHttpWebSocketFeature.AcceptAsync (mapped to AcceptWebSocketAsync).
|
||||
// 6. The middleware calls the OWIN Accept, providing a local callback, and returns an incomplete Task.
|
||||
// 7. The middleware completes the alternate Task it returned from Invoke, telling the server that the request pipeline has completed.
|
||||
// 8. The server invokes the middleware's callback, which creats a WebSocket adapter complete's the orriginal Accept Task with it.
|
||||
// 8. The server invokes the middleware's callback, which creates a WebSocket adapter and completes the original Accept Task with it.
|
||||
// 9. The middleware waits while the application uses the WebSocket, where the end is signaled by the Next's Task completion.
|
||||
public static AppFunc AdaptWebSockets(AppFunc next)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ namespace Microsoft.AspNetCore.Owin
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void OwinEnvironmentImpelmentsGetEnumerator()
|
||||
public void OwinEnvironmentImplementsGetEnumerator()
|
||||
{
|
||||
var owinEnvironment = new OwinEnvironment(CreateContext());
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
public KeyValuePair<string, string>? ReadNextPair()
|
||||
{
|
||||
ReadNextPairImpl();
|
||||
if (ReadSucceded())
|
||||
if (ReadSucceeded())
|
||||
{
|
||||
return new KeyValuePair<string, string>(_currentKey, _currentValue);
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
public async Task<KeyValuePair<string, string>?> ReadNextPairAsync(CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
await ReadNextPairAsyncImpl(cancellationToken);
|
||||
if (ReadSucceded())
|
||||
if (ReadSucceeded())
|
||||
{
|
||||
return new KeyValuePair<string, string>(_currentKey, _currentValue);
|
||||
}
|
||||
|
|
@ -189,11 +189,11 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
return true;
|
||||
}
|
||||
|
||||
private bool TryReadWord(char seperator, int limit, out string value)
|
||||
private bool TryReadWord(char separator, int limit, out string value)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (ReadChar(seperator, limit, out value))
|
||||
if (ReadChar(separator, limit, out value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -201,7 +201,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
return false;
|
||||
}
|
||||
|
||||
private bool ReadChar(char seperator, int limit, out string word)
|
||||
private bool ReadChar(char separator, int limit, out string word)
|
||||
{
|
||||
// End
|
||||
if (_bufferCount == 0)
|
||||
|
|
@ -213,7 +213,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
var c = _buffer[_bufferOffset++];
|
||||
_bufferCount--;
|
||||
|
||||
if (c == seperator)
|
||||
if (c == separator)
|
||||
{
|
||||
word = BuildWord();
|
||||
return true;
|
||||
|
|
@ -283,14 +283,14 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
return accumulator.GetResults();
|
||||
}
|
||||
|
||||
private bool ReadSucceded()
|
||||
private bool ReadSucceeded()
|
||||
{
|
||||
return _currentKey != null && _currentValue != null;
|
||||
}
|
||||
|
||||
private void Append(ref KeyValueAccumulator accumulator)
|
||||
{
|
||||
if (ReadSucceded())
|
||||
if (ReadSucceeded())
|
||||
{
|
||||
accumulator.Append(_currentKey, _currentValue);
|
||||
if (accumulator.ValueCount > ValueCountLimit)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
@ -150,34 +152,66 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
}
|
||||
|
||||
public override async Task WriteAsync(char value)
|
||||
public override Task WriteAsync(char value)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter));
|
||||
return GetObjectDisposedTask();
|
||||
}
|
||||
|
||||
if (_charBufferCount == _charBufferSize)
|
||||
{
|
||||
await FlushInternalAsync(flushEncoder: false);
|
||||
return WriteAsyncAwaited(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enough room in buffer, no need to go async
|
||||
_charBuffer[_charBufferCount] = value;
|
||||
_charBufferCount++;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WriteAsyncAwaited(char value)
|
||||
{
|
||||
Debug.Assert(_charBufferCount == _charBufferSize);
|
||||
|
||||
await FlushInternalAsync(flushEncoder: false);
|
||||
|
||||
_charBuffer[_charBufferCount] = value;
|
||||
_charBufferCount++;
|
||||
}
|
||||
|
||||
public override async Task WriteAsync(char[] values, int index, int count)
|
||||
public override Task WriteAsync(char[] values, int index, int count)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter));
|
||||
return GetObjectDisposedTask();
|
||||
}
|
||||
|
||||
if (values == null)
|
||||
if (values == null || count == 0)
|
||||
{
|
||||
return;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var remaining = _charBufferSize - _charBufferCount;
|
||||
if (remaining >= count)
|
||||
{
|
||||
// Enough room in buffer, no need to go async
|
||||
CopyToCharBuffer(values, ref index, ref count);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
return WriteAsyncAwaited(values, index, count);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WriteAsyncAwaited(char[] values, int index, int count)
|
||||
{
|
||||
Debug.Assert(count > 0);
|
||||
Debug.Assert(_charBufferSize - _charBufferCount > count);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
if (_charBufferCount == _charBufferSize)
|
||||
|
|
@ -186,22 +220,43 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
CopyToCharBuffer(values, ref index, ref count);
|
||||
Debug.Assert(count == 0);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task WriteAsync(string value)
|
||||
public override Task WriteAsync(string value)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter));
|
||||
return GetObjectDisposedTask();
|
||||
}
|
||||
|
||||
if (value == null)
|
||||
var count = value?.Length ?? 0;
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var remaining = _charBufferSize - _charBufferCount;
|
||||
if (remaining >= count)
|
||||
{
|
||||
// Enough room in buffer, no need to go async
|
||||
CopyToCharBuffer(value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
return WriteAsyncAwaited(value);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WriteAsyncAwaited(string value)
|
||||
{
|
||||
var count = value.Length;
|
||||
|
||||
Debug.Assert(count > 0);
|
||||
Debug.Assert(_charBufferSize - _charBufferCount < count);
|
||||
|
||||
var index = 0;
|
||||
while (count > 0)
|
||||
{
|
||||
|
|
@ -231,7 +286,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter));
|
||||
return GetObjectDisposedTask();
|
||||
}
|
||||
|
||||
return FlushInternalAsync(flushEncoder: true);
|
||||
|
|
@ -306,6 +361,19 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
}
|
||||
|
||||
private void CopyToCharBuffer(string value)
|
||||
{
|
||||
Debug.Assert(_charBufferSize - _charBufferCount >= value.Length);
|
||||
|
||||
value.CopyTo(
|
||||
sourceIndex: 0,
|
||||
destination: _charBuffer,
|
||||
destinationIndex: _charBufferCount,
|
||||
count: value.Length);
|
||||
|
||||
_charBufferCount += value.Length;
|
||||
}
|
||||
|
||||
private void CopyToCharBuffer(string value, ref int index, ref int count)
|
||||
{
|
||||
var remaining = Math.Min(_charBufferSize - _charBufferCount, count);
|
||||
|
|
@ -336,5 +404,11 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
index += remaining;
|
||||
count -= remaining;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static Task GetObjectDisposedTask()
|
||||
{
|
||||
return Task.FromException(new ObjectDisposedException(nameof(HttpResponseStreamWriter)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
var anchorIndex = uri.IndexOf('#');
|
||||
var uriToBeAppended = uri;
|
||||
var anchorText = "";
|
||||
// If there is an anchor, then the query string must be inserted before its first occurance.
|
||||
// If there is an anchor, then the query string must be inserted before its first occurence.
|
||||
if (anchorIndex != -1)
|
||||
{
|
||||
anchorText = uri.Substring(anchorIndex);
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_ReadSinglePartBody_Success()
|
||||
public async Task MultipartReader_ReadSinglePartBody_Success()
|
||||
{
|
||||
var stream = MakeStream(OnePartBody);
|
||||
var reader = new MultipartReader(Boundary, stream);
|
||||
|
|
@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_HeaderCountExceeded_Throws()
|
||||
public async Task MultipartReader_HeaderCountExceeded_Throws()
|
||||
{
|
||||
var stream = MakeStream(OnePartBodyTwoHeaders);
|
||||
var reader = new MultipartReader(Boundary, stream)
|
||||
|
|
@ -136,7 +136,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_HeadersLengthExceeded_Throws()
|
||||
public async Task MultipartReader_HeadersLengthExceeded_Throws()
|
||||
{
|
||||
var stream = MakeStream(OnePartBodyTwoHeaders);
|
||||
var reader = new MultipartReader(Boundary, stream)
|
||||
|
|
@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_ReadSinglePartBodyWithTrailingWhitespace_Success()
|
||||
public async Task MultipartReader_ReadSinglePartBodyWithTrailingWhitespace_Success()
|
||||
{
|
||||
var stream = MakeStream(OnePartBodyWithTrailingWhitespace);
|
||||
var reader = new MultipartReader(Boundary, stream);
|
||||
|
|
@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_ReadSinglePartBodyWithoutLastCRLF_Success()
|
||||
public async Task MultipartReader_ReadSinglePartBodyWithoutLastCRLF_Success()
|
||||
{
|
||||
var stream = MakeStream(OnePartBodyWithoutFinalCRLF);
|
||||
var reader = new MultipartReader(Boundary, stream);
|
||||
|
|
@ -183,7 +183,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_ReadTwoPartBody_Success()
|
||||
public async Task MultipartReader_ReadTwoPartBody_Success()
|
||||
{
|
||||
var stream = MakeStream(TwoPartBody);
|
||||
var reader = new MultipartReader(Boundary, stream);
|
||||
|
|
@ -209,7 +209,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_ReadTwoPartBodyWithUnicodeFileName_Success()
|
||||
public async Task MultipartReader_ReadTwoPartBodyWithUnicodeFileName_Success()
|
||||
{
|
||||
var stream = MakeStream(TwoPartBodyWithUnicodeFileName);
|
||||
var reader = new MultipartReader(Boundary, stream);
|
||||
|
|
@ -235,7 +235,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_ThreePartBody_Success()
|
||||
public async Task MultipartReader_ThreePartBody_Success()
|
||||
{
|
||||
var stream = MakeStream(ThreePartBody);
|
||||
var reader = new MultipartReader(Boundary, stream);
|
||||
|
|
@ -270,7 +270,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void MutipartReader_BufferSizeMustBeLargerThanBoundary_Throws()
|
||||
public void MultipartReader_BufferSizeMustBeLargerThanBoundary_Throws()
|
||||
{
|
||||
var stream = MakeStream(ThreePartBody);
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
|
|
@ -280,7 +280,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_TwoPartBodyIncompleteBuffer_TwoSectionsReadSuccessfullyThirdSectionThrows()
|
||||
public async Task MultipartReader_TwoPartBodyIncompleteBuffer_TwoSectionsReadSuccessfullyThirdSectionThrows()
|
||||
{
|
||||
var stream = MakeStream(TwoPartBodyIncompleteBuffer);
|
||||
var reader = new MultipartReader(Boundary, stream);
|
||||
|
|
@ -311,7 +311,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_ReadInvalidUtf8Header_ReplacementCharacters()
|
||||
public async Task MultipartReader_ReadInvalidUtf8Header_ReplacementCharacters()
|
||||
{
|
||||
var body1 =
|
||||
"--9051914041544843365972754266\r\n" +
|
||||
|
|
@ -346,7 +346,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MutipartReader_ReadInvalidUtf8SurrogateHeader_ReplacementCharacters()
|
||||
public async Task MultipartReader_ReadInvalidUtf8SurrogateHeader_ReplacementCharacters()
|
||||
{
|
||||
var body1 =
|
||||
"--9051914041544843365972754266\r\n" +
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue