Merge remote-tracking branch 'origin/release/3.1' into merge/release/3.1-to-master
This commit is contained in:
commit
2587f74c31
|
|
@ -451,6 +451,10 @@ stages:
|
|||
testResultsFiles: '*.xml'
|
||||
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Flaky'
|
||||
artifacts:
|
||||
- name: Windows_Test_Dumps
|
||||
path: artifacts/dumps/
|
||||
publishOnError: true
|
||||
includeForks: false
|
||||
- name: Windows_Test_Logs
|
||||
path: artifacts/log/
|
||||
publishOnError: true
|
||||
|
|
@ -475,6 +479,10 @@ stages:
|
|||
- script: ./src/ProjectTemplates/build.cmd -ci -test -NoRestore -NoBuild -NoBuilddeps "/p:RunTemplateTests=true /bl:artifacts/log/template.test.binlog"
|
||||
displayName: Test Templates
|
||||
artifacts:
|
||||
- name: Windows_Test_Templates_Dumps
|
||||
path: artifacts/dumps/
|
||||
publishOnError: true
|
||||
includeForks: false
|
||||
- name: Windows_Test_Templates_Logs
|
||||
path: artifacts/log/
|
||||
publishOnError: true
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ jobs:
|
|||
- ${{ if and(eq(parameters.agentOs, 'Windows'), eq(parameters.isTestingJob, true)) }}:
|
||||
- powershell: ./eng/scripts/InstallProcDump.ps1
|
||||
displayName: Install ProcDump
|
||||
- powershell: ./eng/scripts/StartDumpCollectionForHangingBuilds.ps1 $(ProcDumpPath)procdump.exe artifacts/log/ (Get-Date).AddMinutes(160) dotnet
|
||||
- powershell: ./eng/scripts/StartDumpCollectionForHangingBuilds.ps1 $(ProcDumpPath)procdump.exe artifacts/dumps/ (Get-Date).AddMinutes(160) dotnet
|
||||
displayName: Start background dump collection
|
||||
- ${{ if eq(parameters.installNodeJs, 'true') }}:
|
||||
- task: NodeTool@0
|
||||
|
|
@ -171,7 +171,7 @@ jobs:
|
|||
- ${{ parameters.afterBuild }}
|
||||
|
||||
- ${{ if and(eq(parameters.agentOs, 'Windows'), eq(parameters.isTestingJob, true)) }}:
|
||||
- powershell: ./eng/scripts/FinishDumpCollectionForHangingBuilds.ps1 artifacts/log/
|
||||
- powershell: ./eng/scripts/FinishDumpCollectionForHangingBuilds.ps1 artifacts/dumps/
|
||||
displayName: Finish background dump collection
|
||||
continueOnError: true
|
||||
condition: always()
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
public Microsoft.AspNetCore.Server.HttpSys.TimeoutManager Timeouts { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public Microsoft.AspNetCore.Server.HttpSys.UrlPrefixCollection UrlPrefixes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
public partial interface IHttpSysRequestInfoFeature
|
||||
{
|
||||
System.Collections.Generic.IReadOnlyDictionary<int, System.ReadOnlyMemory<byte>> RequestInfo { get; }
|
||||
}
|
||||
public sealed partial class TimeoutManager
|
||||
{
|
||||
internal TimeoutManager() { }
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
IHttpUpgradeFeature,
|
||||
IHttpRequestIdentifierFeature,
|
||||
IHttpMaxRequestBodySizeFeature,
|
||||
IHttpBodyControlFeature
|
||||
IHttpBodyControlFeature,
|
||||
IHttpSysRequestInfoFeature
|
||||
{
|
||||
private RequestContext _requestContext;
|
||||
private IFeatureCollection _features;
|
||||
|
|
@ -546,6 +547,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
|
||||
int ITlsHandshakeFeature.KeyExchangeStrength => Request.KeyExchangeStrength;
|
||||
|
||||
IReadOnlyDictionary<int, ReadOnlyMemory<byte>> IHttpSysRequestInfoFeature.RequestInfo => Request.RequestInfo;
|
||||
|
||||
internal async Task OnResponseStart()
|
||||
{
|
||||
if (_responseStarted)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
// 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;
|
||||
|
||||
// Note: This will also be useful for IIS in-proc.
|
||||
// Plan: Have Microsoft.AspNetCore.Server.IIS take a dependency on Microsoft.AspNetCore.Server.HttpSys and implement this interface.
|
||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||
{
|
||||
/// <summary>
|
||||
/// This exposes the Http.Sys HTTP_REQUEST_INFO extensibility point as opaque data for the caller to interperate.
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/api/http/ns-http-http_request_v2
|
||||
/// https://docs.microsoft.com/en-us/windows/win32/api/http/ns-http-http_request_info
|
||||
/// </summary>
|
||||
public interface IHttpSysRequestInfoFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of the HTTP_REQUEST_INFO for the current request. The integer represents the identifying
|
||||
/// HTTP_REQUEST_INFO_TYPE enum value. The Memory is opaque bytes that need to be interperted in the format
|
||||
/// specified by the enum value.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<int, ReadOnlyMemory<byte>> RequestInfo { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// 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.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
|
@ -31,6 +32,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
private AspNetCore.HttpSys.Internal.SocketAddress _localEndPoint;
|
||||
private AspNetCore.HttpSys.Internal.SocketAddress _remoteEndPoint;
|
||||
|
||||
private IReadOnlyDictionary<int, ReadOnlyMemory<byte>> _requestInfo;
|
||||
|
||||
private bool _isDisposed = false;
|
||||
|
||||
internal Request(RequestContext requestContext, NativeRequestContext nativeRequestContext)
|
||||
|
|
@ -252,6 +255,18 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
|
||||
public int KeyExchangeStrength { get; private set; }
|
||||
|
||||
public IReadOnlyDictionary<int, ReadOnlyMemory<byte>> RequestInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_requestInfo == null)
|
||||
{
|
||||
_requestInfo = _nativeRequestContext.GetRequestInfo();
|
||||
}
|
||||
return _requestInfo;
|
||||
}
|
||||
}
|
||||
|
||||
private void GetTlsHandshakeResults()
|
||||
{
|
||||
var handshake = _nativeRequestContext.GetTlsHandshake();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{ typeof(RequestContext), ctx => ctx.RequestContext },
|
||||
{ typeof(IHttpMaxRequestBodySizeFeature), _identityFunc },
|
||||
{ typeof(IHttpBodyControlFeature), _identityFunc },
|
||||
{ typeof(IHttpSysRequestInfoFeature), _identityFunc },
|
||||
};
|
||||
|
||||
private readonly FeatureContext _featureContext;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
|
|
@ -12,6 +14,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Connections.Features;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -160,6 +163,46 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2)]
|
||||
public async Task Https_ITlsHandshakeFeature_MatchesIHttpSysExtensionInfoFeature()
|
||||
{
|
||||
using (Utilities.CreateDynamicHttpsServer(out var address, async httpContext =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var tlsFeature = httpContext.Features.Get<ITlsHandshakeFeature>();
|
||||
var requestInfoFeature = httpContext.Features.Get<IHttpSysRequestInfoFeature>();
|
||||
Assert.NotNull(tlsFeature);
|
||||
Assert.NotNull(requestInfoFeature);
|
||||
Assert.True(requestInfoFeature.RequestInfo.Count > 0);
|
||||
var tlsInfo = requestInfoFeature.RequestInfo[(int)HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslProtocol];
|
||||
HttpApiTypes.HTTP_SSL_PROTOCOL_INFO tlsCopy;
|
||||
unsafe
|
||||
{
|
||||
using var handle = tlsInfo.Pin();
|
||||
tlsCopy = Marshal.PtrToStructure<HttpApiTypes.HTTP_SSL_PROTOCOL_INFO>((IntPtr)handle.Pointer);
|
||||
}
|
||||
|
||||
// Assert.Equal(tlsFeature.Protocol, tlsCopy.Protocol); // These don't directly match because the native and managed enums use different values.
|
||||
Assert.Equal(tlsFeature.CipherAlgorithm, tlsCopy.CipherType);
|
||||
Assert.Equal(tlsFeature.CipherStrength, (int)tlsCopy.CipherStrength);
|
||||
Assert.Equal(tlsFeature.HashAlgorithm, tlsCopy.HashType);
|
||||
Assert.Equal(tlsFeature.HashStrength, (int)tlsCopy.HashStrength);
|
||||
Assert.Equal(tlsFeature.KeyExchangeAlgorithm, tlsCopy.KeyExchangeType);
|
||||
Assert.Equal(tlsFeature.KeyExchangeStrength, (int)tlsCopy.KeyExchangeStrength);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await httpContext.Response.WriteAsync(ex.ToString());
|
||||
}
|
||||
}))
|
||||
{
|
||||
string response = await SendRequestAsync(address);
|
||||
Assert.Equal(string.Empty, response);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> SendRequestAsync(string uri,
|
||||
X509Certificate cert = null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<TestGroupName>HttpSys.FunctionalTests</TestGroupName>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
|
|
@ -478,5 +480,43 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
}
|
||||
return dataRead;
|
||||
}
|
||||
|
||||
internal IReadOnlyDictionary<int, ReadOnlyMemory<byte>> GetRequestInfo()
|
||||
{
|
||||
if (_permanentlyPinned)
|
||||
{
|
||||
return GetRequestInfo((IntPtr)_nativeRequest, (HttpApiTypes.HTTP_REQUEST_V2*)_nativeRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||
{
|
||||
var request = (HttpApiTypes.HTTP_REQUEST_V2*)(pMemoryBlob + _bufferAlignment);
|
||||
return GetRequestInfo(_originalBufferAddress, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IReadOnlyDictionary<int, ReadOnlyMemory<byte>> GetRequestInfo(IntPtr baseAddress, HttpApiTypes.HTTP_REQUEST_V2* nativeRequest)
|
||||
{
|
||||
var count = nativeRequest->RequestInfoCount;
|
||||
if (count == 0)
|
||||
{
|
||||
return ImmutableDictionary<int, ReadOnlyMemory<byte>>.Empty;
|
||||
}
|
||||
|
||||
var info = new Dictionary<int, ReadOnlyMemory<byte>>(count);
|
||||
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var requestInfo = nativeRequest->pRequestInfo[i];
|
||||
var offset = (long)requestInfo.pInfo - (long)baseAddress;
|
||||
info.Add(
|
||||
(int)requestInfo.InfoType,
|
||||
new ReadOnlyMemory<byte>(_backingBuffer, (int)offset, (int)requestInfo.InfoLength));
|
||||
}
|
||||
|
||||
return new ReadOnlyDictionary<int, ReadOnlyMemory<byte>>(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue