Add IServerVariablesFeature
Enables fetching variables directly from IIS when using in-process hosting. This is not available for out-of-process hosting. Other changes: - Update tests to only run if IIS Express has been updated to support the new schema for hostingModel - Add a simpler test fixture for in-proc testing
This commit is contained in:
parent
6f54ed1c68
commit
011cf720e6
|
|
@ -6,6 +6,8 @@ branches:
|
||||||
- release
|
- release
|
||||||
- dev
|
- dev
|
||||||
- /^(.*\/)?ci-.*$/
|
- /^(.*\/)?ci-.*$/
|
||||||
|
install:
|
||||||
|
- ps: .\tools\update_schema.ps1
|
||||||
build_script:
|
build_script:
|
||||||
- ps: .\run.ps1 default-build
|
- ps: .\run.ps1 default-build
|
||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
|
|
@ -15,4 +17,4 @@ environment:
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
test: off
|
test: off
|
||||||
deploy: off
|
deploy: off
|
||||||
os: Visual Studio 2017
|
os: Visual Studio 2017
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.27130.2020
|
VisualStudioVersion = 15.0.27130.2026
|
||||||
MinimumVisualStudioVersion = 15.0.26730.03
|
MinimumVisualStudioVersion = 15.0.26730.03
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04B1EDB6-E967-4D25-89B9-E6F8304038CD}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04B1EDB6-E967-4D25-89B9-E6F8304038CD}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,13 @@
|
||||||
|
|
||||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
|
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
|
||||||
<!-- x86 -->
|
<!-- x86 -->
|
||||||
<None Include="..\..\src\RequestHandler\bin\$(Configuration)\Win32\aspnetcorerh.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" Link="x86\aspnetcorerh.dll" />
|
<None Include="..\..\src\RequestHandler\bin\$(Configuration)\Win32\*.*" CopyToOutputDirectory="PreserveNewest" Visible="false" Link="x86\%(FileName)%(Extension)" />
|
||||||
<None Include="..\..\src\AspNetCore\bin\$(Configuration)\Win32\aspnetcore.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" Link="x86\aspnetcore.dll" />
|
<None Include="..\..\src\AspNetCore\bin\$(Configuration)\Win32\*.*" CopyToOutputDirectory="PreserveNewest" Visible="false" Link="x86\%(FileName)%(Extension)" />
|
||||||
<!-- x64 -->
|
<!-- x64 -->
|
||||||
<None Include="..\..\src\RequestHandler\bin\$(Configuration)\x64\aspnetcorerh.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" Link="x64\aspnetcorerh.dll" />
|
<None Include="..\..\src\RequestHandler\bin\$(Configuration)\x64\*.*" CopyToOutputDirectory="PreserveNewest" Visible="false" Link="x64\%(FileName)%(Extension)" />
|
||||||
<None Include="..\..\src\AspNetCore\bin\$(Configuration)\x64\aspnetcore.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" Link="x64\aspnetcore.dll" />
|
<None Include="..\..\src\AspNetCore\bin\$(Configuration)\x64\*.*" CopyToOutputDirectory="PreserveNewest" Visible="false" Link="x64\%(FileName)%(Extension)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="$(MicrosoftAspNetCoreHostingPackageVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,20 @@ using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Server.IIS;
|
||||||
using Microsoft.AspNetCore.Server.IISIntegration;
|
using Microsoft.AspNetCore.Server.IISIntegration;
|
||||||
|
|
||||||
namespace NativeIISSample
|
namespace NativeIISSample
|
||||||
{
|
{
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAuthenticationSchemeProvider authSchemeProvider)
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAuthenticationSchemeProvider authSchemeProvider)
|
||||||
{
|
{
|
||||||
app.Run(async (context) =>
|
app.Run(async (context) =>
|
||||||
{
|
{
|
||||||
context.Response.ContentType = "text/plain";
|
context.Response.ContentType = "text/plain";
|
||||||
|
|
||||||
await context.Response.WriteAsync("Hello World - " + DateTimeOffset.Now + Environment.NewLine);
|
await context.Response.WriteAsync("Hello World - " + DateTimeOffset.Now + Environment.NewLine);
|
||||||
await context.Response.WriteAsync(Environment.NewLine);
|
await context.Response.WriteAsync(Environment.NewLine);
|
||||||
|
|
||||||
|
|
@ -60,9 +61,29 @@ namespace NativeIISSample
|
||||||
await context.Response.WriteAsync(key + ": " + value + Environment.NewLine);
|
await context.Response.WriteAsync(key + ": " + value + Environment.NewLine);
|
||||||
}
|
}
|
||||||
await context.Response.WriteAsync(Environment.NewLine);
|
await context.Response.WriteAsync(Environment.NewLine);
|
||||||
|
|
||||||
|
// accessing IIS server variables
|
||||||
|
await context.Response.WriteAsync("Server Variables:" + Environment.NewLine);
|
||||||
|
|
||||||
|
foreach (var varName in IISServerVarNames)
|
||||||
|
{
|
||||||
|
await context.Response.WriteAsync(varName + ": " + context.GetIISServerVariable(varName) + Environment.NewLine);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly string[] IISServerVarNames =
|
||||||
|
{
|
||||||
|
"AUTH_TYPE",
|
||||||
|
"AUTH_USER",
|
||||||
|
"CONTENT_TYPE",
|
||||||
|
"HTTP_HOST",
|
||||||
|
"HTTPS",
|
||||||
|
"REMOTE_PORT",
|
||||||
|
"REMOTE_USER",
|
||||||
|
"REQUEST_METHOD",
|
||||||
|
};
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
var host = new WebHostBuilder()
|
var host = new WebHostBuilder()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// 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 Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.IIS
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extensions to <see cref="HttpContext"/> that enable access to IIS features.
|
||||||
|
/// </summary>
|
||||||
|
public static class IISHttpContextExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of a server variable for the current request.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">The http context for the request.</param>
|
||||||
|
/// <param name="variableName">The name of the variable.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <c>null</c> if the feature does not support the <see cref="IServerVariablesFeature"/> feature.
|
||||||
|
/// May return null or empty if the variable does not exist or is not set.
|
||||||
|
/// </returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// For a list of common server variables available in IIS, see http://go.microsoft.com/fwlink/?LinkId=52471.
|
||||||
|
/// </remarks>
|
||||||
|
public static string GetIISServerVariable(this HttpContext context, string variableName)
|
||||||
|
{
|
||||||
|
var feature = context.Features.Get<IServerVariablesFeature>();
|
||||||
|
|
||||||
|
if (feature == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return feature[variableName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This feature provides access to request server variables set.
|
||||||
|
/// <para>
|
||||||
|
/// This feature is only available when hosting ASP.NET Core in-process with IIS or IIS Express.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// For a list of common server variables available in IIS, see http://go.microsoft.com/fwlink/?LinkId=52471.
|
||||||
|
/// </remarks>
|
||||||
|
public interface IServerVariablesFeature
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of a server variable for the current request.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="variableName">The variable name</param>
|
||||||
|
/// <returns>May return null or empty if the variable does not exist or is not set.</returns>
|
||||||
|
string this[string variableName] { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -77,6 +77,9 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
[DllImport(AspNetCoreModuleDll)]
|
[DllImport(AspNetCoreModuleDll)]
|
||||||
public unsafe static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);
|
public unsafe static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);
|
||||||
|
|
||||||
|
[DllImport(AspNetCoreModuleDll)]
|
||||||
|
public static extern int http_get_server_variable(IntPtr pInProcessHandler, [MarshalAs(UnmanagedType.AnsiBStr)] string variableName, [MarshalAs(UnmanagedType.BStr)] out string value);
|
||||||
|
|
||||||
[DllImport(AspNetCoreModuleDll)]
|
[DllImport(AspNetCoreModuleDll)]
|
||||||
public unsafe static extern bool http_shutdown();
|
public unsafe static extern bool http_shutdown();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
IHttpConnectionFeature,
|
IHttpConnectionFeature,
|
||||||
IHttpRequestLifetimeFeature,
|
IHttpRequestLifetimeFeature,
|
||||||
IHttpRequestIdentifierFeature,
|
IHttpRequestIdentifierFeature,
|
||||||
IHttpAuthenticationFeature
|
IHttpAuthenticationFeature,
|
||||||
|
IServerVariablesFeature
|
||||||
{
|
{
|
||||||
// NOTE: When feature interfaces are added to or removed from this HttpProtocol implementation,
|
// NOTE: When feature interfaces are added to or removed from this HttpProtocol implementation,
|
||||||
// then the list of `implementedFeatures` in the generated code project MUST also be updated.
|
// then the list of `implementedFeatures` in the generated code project MUST also be updated.
|
||||||
|
|
@ -234,6 +235,20 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
|
|
||||||
public IAuthenticationHandler Handler { get; set; }
|
public IAuthenticationHandler Handler { get; set; }
|
||||||
|
|
||||||
|
string IServerVariablesFeature.this[string variableName]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(variableName))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hr = NativeMethods.http_get_server_variable(_pInProcessHandler, variableName, out var value);
|
||||||
|
return hr == 0 ? value : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object IFeatureCollection.this[Type key]
|
object IFeatureCollection.this[Type key]
|
||||||
{
|
{
|
||||||
get => FastFeatureGet(key);
|
get => FastFeatureGet(key);
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.IISIntegration
|
namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
{
|
{
|
||||||
|
|
@ -28,6 +26,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
private static readonly Type IHttpBodyControlFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature);
|
private static readonly Type IHttpBodyControlFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature);
|
||||||
private static readonly Type IHttpSendFileFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature);
|
private static readonly Type IHttpSendFileFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature);
|
||||||
private static readonly Type IISHttpContextType = typeof(IISHttpContext);
|
private static readonly Type IISHttpContextType = typeof(IISHttpContext);
|
||||||
|
private static readonly Type IServerVariablesFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IServerVariablesFeature);
|
||||||
|
|
||||||
private object _currentIHttpRequestFeature;
|
private object _currentIHttpRequestFeature;
|
||||||
private object _currentIHttpResponseFeature;
|
private object _currentIHttpResponseFeature;
|
||||||
|
|
@ -49,6 +48,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
private object _currentISessionFeature;
|
private object _currentISessionFeature;
|
||||||
private object _currentIHttpBodyControlFeature;
|
private object _currentIHttpBodyControlFeature;
|
||||||
private object _currentIHttpSendFileFeature;
|
private object _currentIHttpSendFileFeature;
|
||||||
|
private object _currentIServerVariablesFeature;
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
|
|
@ -63,6 +63,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
_currentIHttpMinResponseDataRateFeature = this;
|
_currentIHttpMinResponseDataRateFeature = this;
|
||||||
_currentIHttpBodyControlFeature = this;
|
_currentIHttpBodyControlFeature = this;
|
||||||
_currentIHttpAuthenticationFeature = this;
|
_currentIHttpAuthenticationFeature = this;
|
||||||
|
_currentIServerVariablesFeature = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object FastFeatureGet(Type key)
|
internal object FastFeatureGet(Type key)
|
||||||
|
|
@ -139,6 +140,10 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
if (key == IServerVariablesFeature)
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
return ExtraFeatureGet(key);
|
return ExtraFeatureGet(key);
|
||||||
}
|
}
|
||||||
|
|
@ -232,6 +237,11 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
_currentIHttpSendFileFeature = feature;
|
_currentIHttpSendFileFeature = feature;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (key == IServerVariablesFeature)
|
||||||
|
{
|
||||||
|
_currentIServerVariablesFeature = feature;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (key == IISHttpContextType)
|
if (key == IISHttpContextType)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Cannot set IISHttpContext in feature collection");
|
throw new InvalidOperationException("Cannot set IISHttpContext in feature collection");
|
||||||
|
|
@ -309,6 +319,10 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
|
||||||
{
|
{
|
||||||
yield return new KeyValuePair<Type, object>(IHttpSendFileFeatureType, _currentIHttpSendFileFeature as global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature);
|
yield return new KeyValuePair<Type, object>(IHttpSendFileFeatureType, _currentIHttpSendFileFeature as global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature);
|
||||||
}
|
}
|
||||||
|
if (_currentIServerVariablesFeature != null)
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<Type, object>(IServerVariablesFeature, _currentIServerVariablesFeature as global::Microsoft.AspNetCore.Http.Features.IServerVariablesFeature);
|
||||||
|
}
|
||||||
|
|
||||||
if (MaybeExtra != null)
|
if (MaybeExtra != null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,37 @@ http_get_raw_response(
|
||||||
return pInProcessHandler->QueryHttpContext()->GetResponse()->GetRawHttpResponse();
|
return pInProcessHandler->QueryHttpContext()->GetResponse()->GetRawHttpResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||||
|
HRESULT
|
||||||
|
http_get_server_variable(
|
||||||
|
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||||
|
_In_ PCSTR pszVariableName,
|
||||||
|
_Out_ BSTR* pwszReturn
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCWSTR pszVariableValue;
|
||||||
|
DWORD cbLength;
|
||||||
|
HRESULT hr = pInProcessHandler
|
||||||
|
->QueryHttpContext()
|
||||||
|
->GetServerVariable(pszVariableName, &pszVariableValue, &cbLength);
|
||||||
|
|
||||||
|
if (FAILED(hr) || cbLength == 0)
|
||||||
|
{
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pwszReturn = SysAllocString(pszVariableValue);
|
||||||
|
|
||||||
|
if (*pwszReturn == NULL)
|
||||||
|
{
|
||||||
|
hr = E_OUTOFMEMORY;
|
||||||
|
goto Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
Finished:
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT VOID http_set_response_status_code(
|
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT VOID http_set_response_status_code(
|
||||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||||
_In_ USHORT statusCode,
|
_In_ USHORT statusCode,
|
||||||
|
|
@ -392,4 +423,4 @@ http_get_authentication_information(
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of export
|
// End of export
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,13 @@
|
||||||
#if NET461
|
#if NET461
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IIS.FunctionalTests;
|
using Microsoft.AspNetCore.Server.IIS.FunctionalTests;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -26,7 +25,7 @@ namespace IISIntegration.IISServerFunctionalTests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "See https://github.com/aspnet/IISIntegration/issues/424")]
|
[ConditionalFact]
|
||||||
public Task Authentication_InProcess_IISExpress()
|
public Task Authentication_InProcess_IISExpress()
|
||||||
{
|
{
|
||||||
return Authentication();
|
return Authentication();
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IIS.FunctionalTests;
|
using Microsoft.AspNetCore.Server.IIS.FunctionalTests;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -22,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory(Skip = "See https://github.com/aspnet/IISIntegration/issues/424")]
|
[ConditionalTheory]
|
||||||
[InlineData("SetRequestFeatures")]
|
[InlineData("SetRequestFeatures")]
|
||||||
[InlineData("SetResponseFeatures")]
|
[InlineData("SetResponseFeatures")]
|
||||||
[InlineData("SetConnectionFeatures")]
|
[InlineData("SetConnectionFeatures")]
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -21,7 +20,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "See https://github.com/aspnet/IISIntegration/issues/515")]
|
[ConditionalFact]
|
||||||
public Task HelloWorld_InProcess_IISExpress_CoreClr_X64_Portable()
|
public Task HelloWorld_InProcess_IISExpress_CoreClr_X64_Portable()
|
||||||
{
|
{
|
||||||
return HelloWorld(RuntimeFlavor.CoreClr, ApplicationType.Portable);
|
return HelloWorld(RuntimeFlavor.CoreClr, ApplicationType.Portable);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
<TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>
|
||||||
|
<RootNamespace>Microsoft.AspNetCore.Server.IIS.FunctionalTests</RootNamespace>
|
||||||
|
<AssemblyName>Microsoft.AspNetCore.Server.IIS.FunctionalTests</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,10 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IIS.FunctionalTests;
|
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -23,7 +21,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory(Skip = "See https://github.com/aspnet/IISIntegration/issues/424")]
|
[ConditionalTheory]
|
||||||
[InlineData(10000)]
|
[InlineData(10000)]
|
||||||
[InlineData(100000)]
|
[InlineData(100000)]
|
||||||
[InlineData(1000000)]
|
[InlineData(1000000)]
|
||||||
|
|
@ -84,7 +82,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact (Skip = "See https://github.com/aspnet/IISIntegration/issues/424")]
|
[ConditionalFact]
|
||||||
public Task LargeFileResponseBodyInternalCheck()
|
public Task LargeFileResponseBodyInternalCheck()
|
||||||
{
|
{
|
||||||
return LargeResponseBodyFromFile(RuntimeFlavor.CoreClr, ApplicationType.Portable);
|
return LargeResponseBodyFromFile(RuntimeFlavor.CoreClr, ApplicationType.Portable);
|
||||||
|
|
@ -106,7 +104,12 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
SiteName = "HttpTestSite", // This is configured in the Http.config
|
SiteName = "HttpTestSite", // This is configured in the Http.config
|
||||||
TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net461" : "netcoreapp2.0",
|
TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net461" : "netcoreapp2.0",
|
||||||
ApplicationType = applicationType,
|
ApplicationType = applicationType,
|
||||||
|
Configuration =
|
||||||
|
#if DEBUG
|
||||||
|
"Debug"
|
||||||
|
#else
|
||||||
|
"Release"
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// All functional tests in this project require a version of IIS express with an updated schema
|
||||||
|
[assembly: Microsoft.AspNetCore.Server.IIS.FunctionalTests.IISExpressSupportsInProcessHosting]
|
||||||
|
|
@ -2,13 +2,12 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
@ -24,7 +23,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "See https://github.com/aspnet/IISIntegration/issues/424")]
|
[ConditionalFact]
|
||||||
public Task AddResponseHeaders_HeaderValuesAreSetCorrectly()
|
public Task AddResponseHeaders_HeaderValuesAreSetCorrectly()
|
||||||
{
|
{
|
||||||
return RunResponseHeaders(ApplicationType.Portable);
|
return RunResponseHeaders(ApplicationType.Portable);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -19,7 +20,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory(Skip = "See https://github.com/aspnet/IISIntegration/issues/424")]
|
[ConditionalTheory]
|
||||||
[InlineData("SetStatusCodeAfterWrite")]
|
[InlineData("SetStatusCodeAfterWrite")]
|
||||||
[InlineData("SetHeaderAfterWrite")]
|
[InlineData("SetHeaderAfterWrite")]
|
||||||
public Task ResponseInvalidOrderingTests_ExpectFailure(string path)
|
public Task ResponseInvalidOrderingTests_ExpectFailure(string path)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// 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.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
|
{
|
||||||
|
[Collection(IISTestSiteCollection.Name)]
|
||||||
|
public class ServerVariablesTest
|
||||||
|
{
|
||||||
|
private readonly IISTestSiteFixture _fixture;
|
||||||
|
|
||||||
|
public ServerVariablesTest(IISTestSiteFixture fixture)
|
||||||
|
{
|
||||||
|
_fixture = fixture;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalFact]
|
||||||
|
public async Task ProvidesAccessToServerVariables()
|
||||||
|
{
|
||||||
|
var port = _fixture.Client.BaseAddress.Port;
|
||||||
|
Assert.Equal("SERVER_PORT: " + port, await _fixture.Client.GetStringAsync("/ServerVariable?q=SERVER_PORT"));
|
||||||
|
Assert.Equal("QUERY_STRING: q=QUERY_STRING", await _fixture.Client.GetStringAsync("/ServerVariable?q=QUERY_STRING"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalFact]
|
||||||
|
public async Task ReturnsNullForUndefinedServerVariable()
|
||||||
|
{
|
||||||
|
var port = _fixture.Client.BaseAddress.Port;
|
||||||
|
Assert.Equal("THIS_VAR_IS_UNDEFINED: (null)", await _fixture.Client.GetStringAsync("/ServerVariable?q=THIS_VAR_IS_UNDEFINED"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
// 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.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Assembly | AttributeTargets.Class)]
|
||||||
|
public sealed class IISExpressSupportsInProcessHostingAttribute : Attribute, ITestCondition
|
||||||
|
{
|
||||||
|
public bool IsMet => AncmSchema.SupportsInProcessHosting;
|
||||||
|
|
||||||
|
public string SkipReason => AncmSchema.SkipReason;
|
||||||
|
|
||||||
|
private class AncmSchema
|
||||||
|
{
|
||||||
|
public static bool SupportsInProcessHosting { get; }
|
||||||
|
public static string SkipReason { get; } = "IIS Express must be upgraded to support in-process hosting.";
|
||||||
|
|
||||||
|
static AncmSchema()
|
||||||
|
{
|
||||||
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
SkipReason = "IIS Express tests can only be run on Windows";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ancmConfigPath = Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
|
||||||
|
"IIS Express", "config", "schema", "aspnetcore_schema.xml");
|
||||||
|
|
||||||
|
if (!File.Exists(ancmConfigPath))
|
||||||
|
{
|
||||||
|
SkipReason = "IIS Express is not installed.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
XDocument ancmConfig;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ancmConfig = XDocument.Load(ancmConfigPath);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
SkipReason = "Could not read ANCM schema configuration";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SupportsInProcessHosting = ancmConfig
|
||||||
|
.Root
|
||||||
|
.Descendants("attribute")
|
||||||
|
.Any(n => "hostingModel".Equals(n.Attribute("name")?.Value, StringComparison.Ordinal));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// 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 Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This type just maps collection names to available fixtures
|
||||||
|
/// </summary>
|
||||||
|
[CollectionDefinition(Name)]
|
||||||
|
public class IISTestSiteCollection : ICollectionFixture<IISTestSiteFixture>
|
||||||
|
{
|
||||||
|
public const string Name = nameof(IISTestSiteCollection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
// 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.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||||
|
{
|
||||||
|
public class IISTestSiteFixture : IDisposable
|
||||||
|
{
|
||||||
|
private readonly IApplicationDeployer _deployer;
|
||||||
|
|
||||||
|
public IISTestSiteFixture()
|
||||||
|
{
|
||||||
|
var deploymentParameters = new DeploymentParameters(Helpers.GetTestSitesPath(),
|
||||||
|
ServerType.IISExpress,
|
||||||
|
RuntimeFlavor.CoreClr,
|
||||||
|
RuntimeArchitecture.x64)
|
||||||
|
{
|
||||||
|
ServerConfigTemplateContent = File.ReadAllText("Http.config"),
|
||||||
|
SiteName = "HttpTestSite",
|
||||||
|
TargetFramework = "netcoreapp2.0",
|
||||||
|
ApplicationType = ApplicationType.Portable,
|
||||||
|
Configuration =
|
||||||
|
#if DEBUG
|
||||||
|
"Debug"
|
||||||
|
#else
|
||||||
|
"Release"
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
_deployer = ApplicationDeployerFactory.Create(deploymentParameters, NullLoggerFactory.Instance);
|
||||||
|
var deploymentResult = _deployer.DeployAsync().Result;
|
||||||
|
Client = deploymentResult.HttpClient;
|
||||||
|
BaseUri = deploymentResult.ApplicationBaseUri;
|
||||||
|
ShutdownToken = deploymentResult.HostShutdownToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BaseUri { get; }
|
||||||
|
public HttpClient Client { get; }
|
||||||
|
public CancellationToken ShutdownToken { get; }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_deployer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// 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 Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Server.IIS;
|
||||||
|
|
||||||
|
namespace IISTestSite
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public void Configure(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.Map("/ServerVariable", ServerVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ServerVariable(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
app.Run(async ctx =>
|
||||||
|
{
|
||||||
|
var varName = ctx.Request.Query["q"];
|
||||||
|
await ctx.Response.WriteAsync($"{varName}: {ctx.GetIISServerVariable(varName) ?? "(null)"}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<#
|
||||||
|
.DESCRIPTION
|
||||||
|
Updates aspnetcore_schema.xml to the latest version.
|
||||||
|
Requires admin privileges.
|
||||||
|
#>
|
||||||
|
[cmdletbinding(SupportsShouldProcess = $true)]
|
||||||
|
param()
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
Set-StrictMode -Version 1
|
||||||
|
|
||||||
|
$schemaSource = Resolve-Path "$PSScriptRoot\..\src\AspNetCore\aspnetcore_schema.xml"
|
||||||
|
[bool]$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||||
|
|
||||||
|
if (-not $isAdmin -and -not $WhatIfPreference) {
|
||||||
|
if ($PSCmdlet.ShouldContinue("Continue as an admin?", "This script needs admin privileges to update IIS Express and IIS.")) {
|
||||||
|
$thisFile = Join-Path $PSScriptRoot $MyInvocation.MyCommand.Name
|
||||||
|
|
||||||
|
Start-Process `
|
||||||
|
-Verb runas `
|
||||||
|
-FilePath "powershell.exe" `
|
||||||
|
-ArgumentList $thisFile `
|
||||||
|
-Wait `
|
||||||
|
| Out-Null
|
||||||
|
|
||||||
|
if (-not $?) {
|
||||||
|
throw 'Update failed'
|
||||||
|
}
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw 'Requires admin privileges'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$destinations = @(
|
||||||
|
"${env:ProgramFiles(x86)}\IIS Express\config\schema\aspnetcore_schema.xml",
|
||||||
|
"${env:ProgramFiles}\IIS Express\config\schema\aspnetcore_schema.xml",
|
||||||
|
"${env:windir}\system32\inetsrv\config\schema\aspnetcore_schema.xml"
|
||||||
|
) | Get-Unique
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($dest in $destinations) {
|
||||||
|
if (-not (Test-Path $dest)) {
|
||||||
|
Write-Host -ForegroundColor Yellow "Skipping $dest. File does not already exist."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PSCmdlet.ShouldProcess($dest, "Replace file")) {
|
||||||
|
Write-Host "Updated $dest"
|
||||||
|
Move-Item $dest "${dest}.bak" -ErrorAction Ignore
|
||||||
|
Copy-Item $schemaSource $dest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue