From 76193ecdfd92486001c974cc8febdeb5a6f46b25 Mon Sep 17 00:00:00 2001 From: Justin Kotalik Date: Wed, 30 Oct 2019 13:19:39 -0700 Subject: [PATCH] Set connection close with a switch for ANCM out of process (#16643) --- .../CommonLib/config_utility.h | 8 +++++ .../forwardinghandler.cpp | 9 ++++-- .../forwardinghandler.h | 1 + .../requesthandler_config.cpp | 6 ++++ .../RequestHandlerLib/requesthandler_config.h | 7 +++++ .../test/Common.FunctionalTests/HttpsTests.cs | 29 +++++++++++++++++++ .../testassets/InProcessWebSite/Startup.cs | 6 ++++ 7 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/config_utility.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/config_utility.h index ae4aeb0466..56a3f37246 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/config_utility.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/config_utility.h @@ -14,6 +14,7 @@ class ConfigUtility #define CS_ASPNETCORE_HANDLER_SETTINGS L"handlerSettings" #define CS_ASPNETCORE_HANDLER_VERSION L"handlerVersion" #define CS_ASPNETCORE_DEBUG_FILE L"debugFile" + #define CS_ASPNETCORE_FORWARD_RESPONSE_CONNECTION_HEADER L"forwardResponseConnectionHeader" #define CS_ASPNETCORE_DEBUG_LEVEL L"debugLevel" #define CS_ASPNETCORE_HANDLER_SETTINGS_NAME L"name" #define CS_ASPNETCORE_HANDLER_SETTINGS_VALUE L"value" @@ -40,6 +41,13 @@ public: return FindKeyValuePair(pElement, CS_ASPNETCORE_DEBUG_LEVEL, strDebugFile); } + static + HRESULT + FindForwardResponseConnectionHeader(IAppHostElement* pElement, STRU& strForwardResponseConnectionHeader) + { + return FindKeyValuePair(pElement, CS_ASPNETCORE_FORWARD_RESPONSE_CONNECTION_HEADER, strForwardResponseConnectionHeader); + } + private: static HRESULT diff --git a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp index 4fbf2abf40..82737cf24b 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.cpp @@ -55,6 +55,7 @@ FORWARDING_HANDLER::FORWARDING_HANDLER( LOG_TRACE(L"FORWARDING_HANDLER::FORWARDING_HANDLER"); m_fWebSocketSupported = m_pApplication->QueryWebsocketStatus(); + m_fForwardResponseConnectionHeader = m_pApplication->QueryConfig()->QueryForwardResponseConnectionHeader()->Equals(L"true", /* ignoreCase */ 1); InitializeSRWLock(&m_RequestLock); } @@ -2212,10 +2213,14 @@ FORWARDING_HANDLER::SetStatusAndHeaders( break; } __fallthrough; - case HttpHeaderConnection: case HttpHeaderDate: continue; - + case HttpHeaderConnection: + if (!m_fForwardResponseConnectionHeader) + { + continue; + } + break; case HttpHeaderServer: fServerHeaderPresent = TRUE; break; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.h b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.h index cc855dfcf2..c564a7b4f0 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/OutOfProcessRequestHandler/forwardinghandler.h @@ -179,6 +179,7 @@ private: HINTERNET m_hRequest; FORWARDING_REQUEST_STATUS m_RequestStatus; + BOOL m_fForwardResponseConnectionHeader; BOOL m_fWebSocketEnabled; BOOL m_fWebSocketSupported; BOOL m_fResponseHeadersReceivedAndSet; diff --git a/src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.cpp b/src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.cpp index f4507164df..f6769e30f0 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.cpp +++ b/src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.cpp @@ -379,6 +379,12 @@ REQUESTHANDLER_CONFIG::Populate( goto Finished; } + hr = ConfigUtility::FindForwardResponseConnectionHeader(pAspNetCoreElement, m_struForwardResponseConnectionHeader); + if (FAILED(hr)) + { + goto Finished; + } + Finished: if (pAspNetCoreElement != NULL) diff --git a/src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.h b/src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.h index 90a2b5a365..69fb59b970 100644 --- a/src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.h +++ b/src/Servers/IIS/AspNetCoreModuleV2/RequestHandlerLib/requesthandler_config.h @@ -218,6 +218,12 @@ public: return &m_struConfigPath; } + STRU* + QueryForwardResponseConnectionHeader() + { + return &m_struForwardResponseConnectionHeader; + } + protected: // @@ -249,6 +255,7 @@ protected: STRU m_struApplicationPhysicalPath; STRU m_struApplicationVirtualPath; STRU m_struConfigPath; + STRU m_struForwardResponseConnectionHeader; BOOL m_fStdoutLogEnabled; BOOL m_fForwardWindowsAuthToken; BOOL m_fDisableStartUpErrorPage; diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/HttpsTests.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/HttpsTests.cs index 5b206b101a..ecca4e7cc5 100644 --- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/HttpsTests.cs +++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/HttpsTests.cs @@ -162,6 +162,35 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests Assert.Equal("NOVALUE", await client.GetStringAsync("/HTTPS_PORT")); } + [ConditionalFact] + [RequiresNewHandler] + [RequiresNewShim] + public async Task SetsConnectionCloseHeader() + { + // Only tests OutOfProcess as the Connection header is removed for out of process and not inprocess. + // This test checks a quirk to allow setting the Connection header. + var deploymentParameters = Fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess); + + deploymentParameters.HandlerSettings["forwardResponseConnectionHeader"] = "true"; + var deploymentResult = await DeployAsync(deploymentParameters); + + var response = await deploymentResult.HttpClient.GetAsync("ConnectionClose"); + Assert.Equal(true, response.Headers.ConnectionClose); + } + + [ConditionalFact] + [RequiresNewHandler] + [RequiresNewShim] + public async Task ConnectionCloseIsNotPropagated() + { + var deploymentParameters = Fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess); + + var deploymentResult = await DeployAsync(deploymentParameters); + + var response = await deploymentResult.HttpClient.GetAsync("ConnectionClose"); + Assert.Null(response.Headers.ConnectionClose); + } + private static HttpClient CreateNonValidatingClient(IISDeploymentResult deploymentResult) { var handler = new HttpClientHandler diff --git a/src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs b/src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs index 85debbc4c1..db9aac663e 100644 --- a/src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs +++ b/src/Servers/IIS/IIS/test/testassets/InProcessWebSite/Startup.cs @@ -144,6 +144,12 @@ namespace TestSite return Task.CompletedTask; } + public Task ConnectionClose(HttpContext context) + { + context.Response.Headers["connection"] = "close"; + return Task.CompletedTask; + } + public Task OverrideServer(HttpContext context) { context.Response.Headers["Server"] = "MyServer/7.8";