IIS HTTP/2 Response Trailers (#24120)
This commit is contained in:
parent
ed5034eb8e
commit
c924af3bd7
151
AspNetCore.sln
151
AspNetCore.sln
|
|
@ -1457,6 +1457,28 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropWebsite", "src\Grpc\
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.ConsoleHost", "src\Components\benchmarkapps\Wasm.Performance\ConsoleHost\Wasm.Performance.ConsoleHost.csproj", "{E9408723-E6A9-4715-B906-3B25B0238ABA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InProcessWebSite", "src\Servers\IIS\IIS\test\testassets\InProcessWebSite\InProcessWebSite.csproj", "{8DA61885-B95E-4BA1-A752-C79B6597FC44}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ANCM", "ANCM", "{D62AF49B-F9FE-4794-AC39-A473FF13CA81}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AspNetCore", "src\Servers\IIS\AspNetCoreModuleV2\AspNetCore\AspNetCore.vcxproj", "{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLib", "src\Servers\IIS\AspNetCoreModuleV2\CommonLib\CommonLib.vcxproj", "{55494E58-E061-4C4C-A0A8-837008E72F85}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonLibTests", "src\Servers\IIS\AspNetCoreModuleV2\CommonLibTests\CommonLibTests.vcxproj", "{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "src\Servers\IIS\AspNetCoreModuleV2\gtest\gtest.vcxproj", "{CAC1267B-8778-4257-AAC6-CAF481723B01}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IISLib", "src\Servers\IIS\AspNetCoreModuleV2\IISLib\IISLib.vcxproj", "{09D9D1D6-2951-4E14-BC35-76A23CF9391A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InProcessRequestHandler", "src\Servers\IIS\AspNetCoreModuleV2\InProcessRequestHandler\InProcessRequestHandler.vcxproj", "{D57EA297-6DC2-4BC0-8C91-334863327863}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OutOfProcessRequestHandler", "src\Servers\IIS\AspNetCoreModuleV2\OutOfProcessRequestHandler\OutOfProcessRequestHandler.vcxproj", "{7F87406C-A3C8-4139-A68D-E4C344294A67}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RequestHandlerLib", "src\Servers\IIS\AspNetCoreModuleV2\RequestHandlerLib\RequestHandlerLib.vcxproj", "{1533E271-F61B-441B-8B74-59FB61DF0552}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ANCMSymbols", "src\Servers\IIS\AspNetCoreModuleV2\Symbols\Microsoft.AspNetCore.ANCMSymbols.csproj", "{7E268085-1046-4362-80CB-2977FF826DCA}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -6903,6 +6925,124 @@ Global
|
|||
{E9408723-E6A9-4715-B906-3B25B0238ABA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E9408723-E6A9-4715-B906-3B25B0238ABA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E9408723-E6A9-4715-B906-3B25B0238ABA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Debug|x64.Build.0 = Debug|x64
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Debug|x86.Build.0 = Debug|x86
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Release|x64.ActiveCfg = Release|x64
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Release|x64.Build.0 = Release|x64
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Release|x86.ActiveCfg = Release|x86
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44}.Release|x86.Build.0 = Release|x86
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x64.Build.0 = Debug|x64
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x86.Build.0 = Debug|Win32
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x64.ActiveCfg = Release|x64
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x64.Build.0 = Release|x64
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x86.Build.0 = Release|Win32
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B}.Release|x86.Deploy.0 = Release|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x64.Build.0 = Debug|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x86.Build.0 = Debug|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x64.ActiveCfg = Release|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x64.Build.0 = Release|x64
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x86.ActiveCfg = Release|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x86.Build.0 = Release|Win32
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85}.Release|x86.Deploy.0 = Release|Win32
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Debug|x64.Build.0 = Debug|x64
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Debug|x86.Build.0 = Debug|Win32
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Release|x64.ActiveCfg = Release|x64
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Release|x64.Build.0 = Release|x64
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Release|x86.ActiveCfg = Release|Win32
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Release|x86.Build.0 = Release|Win32
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1}.Release|x86.Deploy.0 = Release|Win32
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Debug|x64.Build.0 = Debug|x64
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Debug|x86.Build.0 = Debug|Win32
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Release|x64.ActiveCfg = Release|x64
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Release|x64.Build.0 = Release|x64
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Release|x86.ActiveCfg = Release|Win32
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Release|x86.Build.0 = Release|Win32
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01}.Release|x86.Deploy.0 = Release|Win32
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x64.Build.0 = Debug|x64
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x86.Build.0 = Debug|Win32
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x64.ActiveCfg = Release|x64
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x64.Build.0 = Release|x64
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x86.ActiveCfg = Release|Win32
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x86.Build.0 = Release|Win32
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A}.Release|x86.Deploy.0 = Release|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|x64.Build.0 = Debug|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|x86.Build.0 = Debug|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x64.ActiveCfg = Release|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x64.Build.0 = Release|x64
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x86.ActiveCfg = Release|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x86.Build.0 = Release|Win32
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863}.Release|x86.Deploy.0 = Release|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Debug|x64.Build.0 = Debug|x64
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Debug|x86.Build.0 = Debug|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|x64.ActiveCfg = Release|x64
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|x64.Build.0 = Release|x64
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|x86.Build.0 = Release|Win32
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67}.Release|x86.Deploy.0 = Release|Win32
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Debug|x64.Build.0 = Debug|x64
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Debug|x86.Build.0 = Debug|Win32
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Debug|x86.Deploy.0 = Debug|Win32
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Release|x64.ActiveCfg = Release|x64
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Release|x64.Build.0 = Release|x64
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Release|x86.ActiveCfg = Release|Win32
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Release|x86.Build.0 = Release|Win32
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552}.Release|x86.Deploy.0 = Release|Win32
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -7633,6 +7773,17 @@ Global
|
|||
{C3A0F425-669F-46A8-893F-CF449A6DAE56} = {00B2DD87-7E2A-4460-BE1B-5E18B1062B7F}
|
||||
{19189670-E206-471D-94F8-7D3D545E5020} = {00B2DD87-7E2A-4460-BE1B-5E18B1062B7F}
|
||||
{E9408723-E6A9-4715-B906-3B25B0238ABA} = {6276A9A0-791B-49C1-AD8F-50AC47CDC196}
|
||||
{8DA61885-B95E-4BA1-A752-C79B6597FC44} = {41BB7BA4-AC08-4E9A-83EA-6D587A5B951C}
|
||||
{D62AF49B-F9FE-4794-AC39-A473FF13CA81} = {D67E977E-75DF-41EE-8315-6DBF5C2B7357}
|
||||
{EC82302F-D2F0-4727-99D1-EABC0DD9DC3B} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{55494E58-E061-4C4C-A0A8-837008E72F85} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{1EAC8125-1765-4E2D-8CBE-56DC98A1C8C1} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{CAC1267B-8778-4257-AAC6-CAF481723B01} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{09D9D1D6-2951-4E14-BC35-76A23CF9391A} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{D57EA297-6DC2-4BC0-8C91-334863327863} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{7F87406C-A3C8-4139-A68D-E4C344294A67} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,50 @@ extern bool g_fInProcessApplicationCreated;
|
|||
extern std::string g_errorPageContent;
|
||||
extern IHttpServer* g_pHttpServer;
|
||||
|
||||
//
|
||||
// Add support for certain HTTP/2.0 features like trailing headers
|
||||
// and GOAWAY or RST_STREAM frames.
|
||||
//
|
||||
|
||||
class __declspec(uuid("1a2acc57-cae2-4f28-b4ab-00c8f96b12ec"))
|
||||
IHttpResponse4 : public IHttpResponse3
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
HRESULT
|
||||
DeleteTrailer(
|
||||
_In_ PCSTR pszHeaderName
|
||||
) = 0;
|
||||
|
||||
virtual
|
||||
PCSTR
|
||||
GetTrailer(
|
||||
_In_ PCSTR pszHeaderName,
|
||||
_Out_ USHORT* pcchHeaderValue = NULL
|
||||
) const = 0;
|
||||
|
||||
virtual
|
||||
VOID
|
||||
ResetStream(
|
||||
_In_ ULONG errorCode
|
||||
) = 0;
|
||||
|
||||
virtual
|
||||
VOID
|
||||
SetNeedGoAway(
|
||||
VOID
|
||||
) = 0;
|
||||
|
||||
virtual
|
||||
HRESULT
|
||||
SetTrailer(
|
||||
_In_ PCSTR pszHeaderName,
|
||||
_In_ PCSTR pszHeaderValue,
|
||||
_In_ USHORT cchHeaderValue,
|
||||
_In_ BOOL fReplace
|
||||
) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// Initialization export
|
||||
//
|
||||
|
|
@ -517,4 +561,32 @@ http_set_startup_error_page_content(_In_ byte* errorPageContent, int length)
|
|||
memcpy(&g_errorPageContent[0], errorPageContent, length);
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_has_response4(
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_Out_ BOOL* supportsTrailers
|
||||
)
|
||||
{
|
||||
IHttpResponse4* pHttpResponse;
|
||||
|
||||
HRESULT hr = HttpGetExtendedInterface(g_pHttpServer, pInProcessHandler->QueryHttpContext()->GetResponse(), &pHttpResponse);
|
||||
*supportsTrailers = SUCCEEDED(hr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXTERN_C __MIDL_DECLSPEC_DLLEXPORT
|
||||
HRESULT
|
||||
http_response_set_trailer(
|
||||
_In_ IN_PROCESS_HANDLER* pInProcessHandler,
|
||||
_In_ PCSTR pszHeaderName,
|
||||
_In_ PCSTR pszHeaderValue,
|
||||
_In_ USHORT usHeaderValueLength,
|
||||
_In_ BOOL fReplace)
|
||||
{
|
||||
// always unknown
|
||||
IHttpResponse4* pHttpResponse = (IHttpResponse4*)pInProcessHandler->QueryHttpContext()->GetResponse();
|
||||
return pHttpResponse->SetTrailer(pszHeaderName, pszHeaderValue, usHeaderValueLength, fReplace);
|
||||
}
|
||||
// End of export
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
IServerVariablesFeature,
|
||||
ITlsConnectionFeature,
|
||||
IHttpBodyControlFeature,
|
||||
IHttpMaxRequestBodySizeFeature
|
||||
IHttpMaxRequestBodySizeFeature,
|
||||
IHttpResponseTrailersFeature
|
||||
{
|
||||
// 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.
|
||||
|
|
@ -376,6 +377,23 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
}
|
||||
}
|
||||
|
||||
internal IHttpResponseTrailersFeature GetResponseTrailersFeature()
|
||||
{
|
||||
// Check version is above 2.
|
||||
if (HttpVersion >= System.Net.HttpVersion.Version20 && NativeMethods.HttpSupportTrailer(_pInProcessHandler))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
IHeaderDictionary IHttpResponseTrailersFeature.Trailers
|
||||
{
|
||||
get => ResponseTrailers ??= HttpResponseTrailers;
|
||||
set => ResponseTrailers = value;
|
||||
}
|
||||
|
||||
void IHttpResponseBodyFeature.DisableBuffering()
|
||||
{
|
||||
NativeMethods.HttpDisableBuffering(_pInProcessHandler);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
private static readonly Type IISHttpContextType = typeof(IISHttpContext);
|
||||
private static readonly Type IServerVariablesFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IServerVariablesFeature);
|
||||
private static readonly Type IHttpMaxRequestBodySizeFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpMaxRequestBodySizeFeature);
|
||||
private static readonly Type IHttpResponseTrailersFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpResponseTrailersFeature);
|
||||
|
||||
private object _currentIHttpRequestFeature;
|
||||
private object _currentIHttpResponseFeature;
|
||||
|
|
@ -48,6 +49,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
private object _currentIHttpBodyControlFeature;
|
||||
private object _currentIServerVariablesFeature;
|
||||
private object _currentIHttpMaxRequestBodySizeFeature;
|
||||
private object _currentIHttpResponseTrailersFeature;
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
|
|
@ -63,6 +65,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
_currentIServerVariablesFeature = this;
|
||||
_currentIHttpMaxRequestBodySizeFeature = this;
|
||||
_currentITlsConnectionFeature = this;
|
||||
_currentIHttpResponseTrailersFeature = GetResponseTrailersFeature();
|
||||
}
|
||||
|
||||
internal object FastFeatureGet(Type key)
|
||||
|
|
@ -147,6 +150,10 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
{
|
||||
return _currentIHttpMaxRequestBodySizeFeature;
|
||||
}
|
||||
if (key == IHttpResponseTrailersFeature)
|
||||
{
|
||||
return _currentIHttpResponseTrailersFeature;
|
||||
}
|
||||
|
||||
return ExtraFeatureGet(key);
|
||||
}
|
||||
|
|
@ -249,6 +256,10 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
{
|
||||
_currentIHttpMaxRequestBodySizeFeature = feature;
|
||||
}
|
||||
if (key == IHttpResponseTrailersFeature)
|
||||
{
|
||||
_currentIHttpResponseTrailersFeature = feature;
|
||||
}
|
||||
if (key == IISHttpContextType)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot set IISHttpContext in feature collection");
|
||||
|
|
@ -334,6 +345,10 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpMaxRequestBodySizeFeature, _currentIHttpMaxRequestBodySizeFeature as global::Microsoft.AspNetCore.Http.Features.IHttpMaxRequestBodySizeFeature);
|
||||
}
|
||||
if (_currentIHttpResponseTrailersFeature != null)
|
||||
{
|
||||
yield return new KeyValuePair<Type, object>(IHttpResponseTrailersFeature, _currentIHttpResponseTrailersFeature as global::Microsoft.AspNetCore.Http.Features.IHttpResponseTrailersFeature);
|
||||
}
|
||||
|
||||
if (MaybeExtra != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -169,6 +169,12 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
// if request is done no need to flush, http.sys would do it for us
|
||||
if (result.IsCompleted)
|
||||
{
|
||||
// When is the reader completed? Is it always after the request pipeline exits? Or can CompleteAsync make it complete early?
|
||||
if (HasTrailers)
|
||||
{
|
||||
SetResponseTrailers();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
protected Pipe _bodyInputPipe;
|
||||
protected OutputProducer _bodyOutput;
|
||||
|
||||
private HeaderCollection _trailers;
|
||||
|
||||
private const string NtlmString = "NTLM";
|
||||
private const string NegotiateString = "Negotiate";
|
||||
private const string BasicString = "Basic";
|
||||
|
|
@ -114,7 +116,11 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
|
||||
public IHeaderDictionary RequestHeaders { get; set; }
|
||||
public IHeaderDictionary ResponseHeaders { get; set; }
|
||||
public IHeaderDictionary ResponseTrailers { get; set; }
|
||||
private HeaderCollection HttpResponseHeaders { get; set; }
|
||||
private HeaderCollection HttpResponseTrailers => _trailers ??= new HeaderCollection(checkTrailers: true);
|
||||
internal bool HasTrailers => _trailers?.Count > 0;
|
||||
|
||||
internal HttpApiTypes.HTTP_VERB KnownMethod { get; private set; }
|
||||
|
||||
private bool HasStartedConsumingRequestBody { get; set; }
|
||||
|
|
@ -418,6 +424,42 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
|
|||
}
|
||||
}
|
||||
|
||||
public unsafe void SetResponseTrailers()
|
||||
{
|
||||
HttpResponseTrailers.IsReadOnly = true;
|
||||
foreach (var headerPair in HttpResponseTrailers)
|
||||
{
|
||||
var headerValues = headerPair.Value;
|
||||
|
||||
if (headerValues.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var headerNameBytes = Encoding.ASCII.GetBytes(headerPair.Key);
|
||||
fixed (byte* pHeaderName = headerNameBytes)
|
||||
{
|
||||
var isFirst = true;
|
||||
for (var i = 0; i < headerValues.Count; i++)
|
||||
{
|
||||
var headerValue = headerValues[i];
|
||||
if (string.IsNullOrEmpty(headerValue))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var headerValueBytes = Encoding.UTF8.GetBytes(headerValue);
|
||||
fixed (byte* pHeaderValue = headerValueBytes)
|
||||
{
|
||||
NativeMethods.HttpResponseSetTrailer(_pInProcessHandler, pHeaderName, pHeaderValue, (ushort)headerValueBytes.Length, replace: isFirst);
|
||||
}
|
||||
|
||||
isFirst = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Task<bool> ProcessRequestAsync();
|
||||
|
||||
public void OnStarting(Func<object, Task> callback, object state)
|
||||
|
|
|
|||
|
|
@ -141,6 +141,11 @@ namespace Microsoft.AspNetCore.Server.IIS
|
|||
[DllImport(AspNetCoreModuleDll)]
|
||||
private static extern unsafe int http_response_set_unknown_header(IntPtr pInProcessHandler, byte* pszHeaderName, byte* pszHeaderValue, ushort usHeaderValueLength, bool fReplace);
|
||||
|
||||
[DllImport(AspNetCoreModuleDll)]
|
||||
private static extern unsafe int http_has_response4(IntPtr pInProcessHandler, out bool isResponse4);
|
||||
[DllImport(AspNetCoreModuleDll)]
|
||||
private static extern unsafe int http_response_set_trailer(IntPtr pInProcessHandler, byte* pszHeaderName, byte* pszHeaderValue, ushort usHeaderValueLength, bool replace);
|
||||
|
||||
[DllImport(AspNetCoreModuleDll)]
|
||||
private static extern unsafe int http_response_set_known_header(IntPtr pInProcessHandler, int headerId, byte* pHeaderValue, ushort length, bool fReplace);
|
||||
|
||||
|
|
@ -308,6 +313,18 @@ namespace Microsoft.AspNetCore.Server.IIS
|
|||
}
|
||||
}
|
||||
|
||||
internal static unsafe void HttpResponseSetTrailer(IntPtr pInProcessHandler, byte* pHeaderName, byte* pHeaderValue, ushort length, bool replace)
|
||||
{
|
||||
Validate(http_response_set_trailer(pInProcessHandler, pHeaderName, pHeaderValue, length, false));
|
||||
}
|
||||
|
||||
internal static unsafe bool HttpSupportTrailer(IntPtr pInProcessHandler)
|
||||
{
|
||||
bool supportsTrailers;
|
||||
Validate(http_has_response4(pInProcessHandler, out supportsTrailers));
|
||||
return supportsTrailers;
|
||||
}
|
||||
|
||||
private static void Validate(int hr)
|
||||
{
|
||||
if (hr != HR_OK)
|
||||
|
|
|
|||
|
|
@ -10,22 +10,22 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
|||
{
|
||||
public class FixtureLoggedTest : LoggedTest
|
||||
{
|
||||
private readonly IISTestSiteFixture _fixture;
|
||||
protected IISTestSiteFixture Fixture { get; set; }
|
||||
|
||||
public FixtureLoggedTest(IISTestSiteFixture fixture)
|
||||
{
|
||||
_fixture = fixture;
|
||||
Fixture = fixture;
|
||||
}
|
||||
|
||||
public override void Initialize(TestContext context, MethodInfo methodInfo, object[] testMethodArguments, ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
base.Initialize(context, methodInfo, testMethodArguments, testOutputHelper);
|
||||
_fixture.Attach(this);
|
||||
Fixture.Attach(this);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_fixture.Detach(this);
|
||||
Fixture.Detach(this);
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,199 @@
|
|||
// 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.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting.Common;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests
|
||||
{
|
||||
[Collection(PublishedSitesCollection.Name)]
|
||||
public class ResponseTrailersTests : IISFunctionalTestBase
|
||||
{
|
||||
private const string WindowsVersionForTrailers = "10.0.20180";
|
||||
|
||||
public ResponseTrailersTests(PublishedSitesFixture fixture) : base(fixture)
|
||||
{
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_HTTP2_TrailersAvailable()
|
||||
{
|
||||
var version = System.Environment.OSVersion.Version;
|
||||
|
||||
var deploymentParameters = GetHttpsDeploymentParameters();
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_HTTP2_TrailersAvailable");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version20, response.Version);
|
||||
Assert.Empty(response.TrailingHeaders);
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_HTTP1_TrailersNotAvailable()
|
||||
{
|
||||
var deploymentParameters = Fixture.GetBaseDeploymentParameters(hostingModel: IntegrationTesting.HostingModel.OutOfProcess);
|
||||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_HTTP1_TrailersNotAvailable");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version11, response.Version);
|
||||
Assert.Empty(response.TrailingHeaders);
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_ProhibitedTrailers_Blocked()
|
||||
{
|
||||
var deploymentParameters = GetHttpsDeploymentParameters();
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_ProhibitedTrailers_Blocked");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version20, response.Version);
|
||||
Assert.Empty(response.TrailingHeaders);
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_NoBody_TrailersSent()
|
||||
{
|
||||
var deploymentParameters = GetHttpsDeploymentParameters();
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_NoBody_TrailersSent");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version20, response.Version);
|
||||
Assert.NotEmpty(response.TrailingHeaders);
|
||||
Assert.Equal("TrailerValue", response.TrailingHeaders.GetValues("TrailerName").Single());
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_WithBody_TrailersSent()
|
||||
{
|
||||
var deploymentParameters = GetHttpsDeploymentParameters();
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_WithBody_TrailersSent");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version20, response.Version);
|
||||
Assert.Equal("Hello World", await response.Content.ReadAsStringAsync());
|
||||
Assert.NotEmpty(response.TrailingHeaders);
|
||||
Assert.Equal("Trailer Value", response.TrailingHeaders.GetValues("TrailerName").Single());
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_WithContentLengthBody_TrailersSent()
|
||||
{
|
||||
var body = "Hello World";
|
||||
|
||||
var deploymentParameters = GetHttpsDeploymentParameters();
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_WithContentLengthBody_TrailersSent");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version20, response.Version);
|
||||
Assert.Equal(body, await response.Content.ReadAsStringAsync());
|
||||
Assert.NotEmpty(response.TrailingHeaders);
|
||||
Assert.Equal("Trailer Value", response.TrailingHeaders.GetValues("TrailerName").Single());
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_WithTrailersBeforeContentLengthBody_TrailersSent()
|
||||
{
|
||||
var body = "Hello World";
|
||||
|
||||
var deploymentParameters = GetHttpsDeploymentParameters();
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_WithTrailersBeforeContentLengthBody_TrailersSent");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version20, response.Version);
|
||||
// Avoid HttpContent's automatic content-length calculation.
|
||||
Assert.True(response.Content.Headers.TryGetValues(HeaderNames.ContentLength, out var contentLength), HeaderNames.ContentLength);
|
||||
Assert.Equal((2 * body.Length).ToString(CultureInfo.InvariantCulture), contentLength.First());
|
||||
Assert.Equal(body + body, await response.Content.ReadAsStringAsync());
|
||||
Assert.NotEmpty(response.TrailingHeaders);
|
||||
Assert.Equal("Trailer Value", response.TrailingHeaders.GetValues("TrailerName").Single());
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_WithContentLengthBodyAndDeclared_TrailersSent()
|
||||
{
|
||||
var body = "Hello World";
|
||||
|
||||
var deploymentParameters = GetHttpsDeploymentParameters();
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_WithContentLengthBodyAndDeclared_TrailersSent");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version20, response.Version);
|
||||
// Avoid HttpContent's automatic content-length calculation.
|
||||
Assert.True(response.Content.Headers.TryGetValues(HeaderNames.ContentLength, out var contentLength), HeaderNames.ContentLength);
|
||||
Assert.Equal(body.Length.ToString(CultureInfo.InvariantCulture), contentLength.First());
|
||||
Assert.Equal("TrailerName", response.Headers.Trailer.Single());
|
||||
Assert.Equal(body, await response.Content.ReadAsStringAsync());
|
||||
Assert.NotEmpty(response.TrailingHeaders);
|
||||
Assert.Equal("Trailer Value", response.TrailingHeaders.GetValues("TrailerName").Single());
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[MinimumOSVersion(OperatingSystems.Windows, WindowsVersionForTrailers)]
|
||||
public async Task ResponseTrailers_MultipleValues_SentAsSeparateHeaders()
|
||||
{
|
||||
var deploymentParameters = GetHttpsDeploymentParameters();
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
|
||||
var response = await SendRequestAsync(deploymentResult.HttpClient.BaseAddress.ToString() + "ResponseTrailers_MultipleValues_SentAsSeparateHeaders");
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpVersion.Version20, response.Version);
|
||||
Assert.NotEmpty(response.TrailingHeaders);
|
||||
|
||||
Assert.Equal(new[] { "TrailerValue0", "TrailerValue1" }, response.TrailingHeaders.GetValues("TrailerName"));
|
||||
}
|
||||
|
||||
private IISDeploymentParameters GetHttpsDeploymentParameters()
|
||||
{
|
||||
var port = TestPortHelper.GetNextSSLPort();
|
||||
var deploymentParameters = Fixture.GetBaseDeploymentParameters();
|
||||
deploymentParameters.ApplicationBaseUriHint = $"https://localhost:{port}/";
|
||||
deploymentParameters.AddHttpsToServerConfig();
|
||||
return deploymentParameters;
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> SendRequestAsync(string uri, bool http2 = true)
|
||||
{
|
||||
var handler = new HttpClientHandler();
|
||||
handler.MaxResponseHeadersLength = 128;
|
||||
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
||||
using var client = new HttpClient(handler);
|
||||
client.DefaultRequestVersion = http2 ? HttpVersion.Version20 : HttpVersion.Version11;
|
||||
return await client.GetAsync(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
|
@ -25,6 +26,7 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
using HttpFeatures = Microsoft.AspNetCore.Http.Features;
|
||||
|
||||
|
|
@ -1030,5 +1032,145 @@ namespace TestSite
|
|||
Assert.Equal("<22>", value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
#if !FORWARDCOMPAT
|
||||
public Task ResponseTrailers_HTTP2_TrailersAvailable(HttpContext context)
|
||||
{
|
||||
Assert.Equal("HTTP/2", context.Request.Protocol);
|
||||
Assert.True(context.Response.SupportsTrailers());
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ResponseTrailers_HTTP1_TrailersNotAvailable(HttpContext context)
|
||||
{
|
||||
Assert.Equal("HTTP/1.1", context.Request.Protocol);
|
||||
Assert.False(context.Response.SupportsTrailers());
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ResponseTrailers_ProhibitedTrailers_Blocked(HttpContext context)
|
||||
{
|
||||
Assert.True(context.Response.SupportsTrailers());
|
||||
foreach (var header in DisallowedTrailers)
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() => context.Response.AppendTrailer(header, "value"));
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ResponseTrailers_NoBody_TrailersSent(HttpContext context)
|
||||
{
|
||||
context.Response.DeclareTrailer("trailername");
|
||||
context.Response.AppendTrailer("trailername", "TrailerValue");
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public async Task ResponseTrailers_WithBody_TrailersSent(HttpContext context)
|
||||
{
|
||||
await context.Response.WriteAsync("Hello World");
|
||||
context.Response.AppendTrailer("TrailerName", "Trailer Value");
|
||||
}
|
||||
|
||||
public async Task ResponseTrailers_WithContentLengthBody_TrailersSent(HttpContext context)
|
||||
{
|
||||
var body = "Hello World";
|
||||
context.Response.ContentLength = body.Length;
|
||||
await context.Response.WriteAsync(body);
|
||||
context.Response.AppendTrailer("TrailerName", "Trailer Value");
|
||||
}
|
||||
|
||||
public async Task ResponseTrailers_WithTrailersBeforeContentLengthBody_TrailersSent(HttpContext context)
|
||||
{
|
||||
var body = "Hello World";
|
||||
context.Response.ContentLength = body.Length * 2;
|
||||
await context.Response.WriteAsync(body);
|
||||
context.Response.AppendTrailer("TrailerName", "Trailer Value");
|
||||
await context.Response.WriteAsync(body);
|
||||
}
|
||||
|
||||
public async Task ResponseTrailers_WithContentLengthBodyAndDeclared_TrailersSent(HttpContext context)
|
||||
{
|
||||
var body = "Hello World";
|
||||
context.Response.ContentLength = body.Length;
|
||||
context.Response.DeclareTrailer("TrailerName");
|
||||
await context.Response.WriteAsync(body);
|
||||
context.Response.AppendTrailer("TrailerName", "Trailer Value");
|
||||
}
|
||||
|
||||
public async Task ResponseTrailers_WithContentLengthBodyAndDeclaredButMissingTrailers_Completes(HttpContext context)
|
||||
{
|
||||
var body = "Hello World";
|
||||
context.Response.ContentLength = body.Length;
|
||||
context.Response.DeclareTrailer("TrailerName");
|
||||
await context.Response.WriteAsync(body);
|
||||
}
|
||||
|
||||
public Task ResponseTrailers_MultipleValues_SentAsSeparateHeaders(HttpContext context)
|
||||
{
|
||||
context.Response.AppendTrailer("trailername", new StringValues(new[] { "TrailerValue0", "TrailerValue1" }));
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ResponseTrailers_LargeTrailers_Success(HttpContext context)
|
||||
{
|
||||
var values = new[] {
|
||||
new string('a', 1024),
|
||||
new string('b', 1024 * 4),
|
||||
new string('c', 1024 * 8),
|
||||
new string('d', 1024 * 16),
|
||||
new string('e', 1024 * 32),
|
||||
new string('f', 1024 * 64 - 1) }; // Max header size
|
||||
|
||||
context.Response.AppendTrailer("ThisIsALongerHeaderNameThatStillWorksForReals", new StringValues(values));
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ResponseTrailers_NullValues_Ignored(HttpContext context)
|
||||
{
|
||||
foreach (var kvp in NullTrailers)
|
||||
{
|
||||
context.Response.AppendTrailer(kvp.Item1, kvp.Item2);
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
internal static readonly HashSet<(string, StringValues, StringValues)> NullTrailers = new HashSet<(string, StringValues, StringValues)>()
|
||||
{
|
||||
("NullString", (string)null, (string)null),
|
||||
("EmptyString", "", ""),
|
||||
("NullStringArray", new string[] { null }, ""),
|
||||
("EmptyStringArray", new string[] { "" }, ""),
|
||||
("MixedStringArray", new string[] { null, "" }, new string[] { "", "" }),
|
||||
("WithValidStrings", new string[] { null, "Value", "" }, new string[] { "", "Value", "" })
|
||||
};
|
||||
|
||||
// https://tools.ietf.org/html/rfc7230#section-4.1.2
|
||||
internal static readonly HashSet<string> DisallowedTrailers = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
// Message framing headers.
|
||||
HeaderNames.TransferEncoding, HeaderNames.ContentLength,
|
||||
|
||||
// Routing headers.
|
||||
HeaderNames.Host,
|
||||
|
||||
// Request modifiers: controls and conditionals.
|
||||
// rfc7231#section-5.1: Controls.
|
||||
HeaderNames.CacheControl, HeaderNames.Expect, HeaderNames.MaxForwards, HeaderNames.Pragma, HeaderNames.Range, HeaderNames.TE,
|
||||
|
||||
// rfc7231#section-5.2: Conditionals.
|
||||
HeaderNames.IfMatch, HeaderNames.IfNoneMatch, HeaderNames.IfModifiedSince, HeaderNames.IfUnmodifiedSince, HeaderNames.IfRange,
|
||||
|
||||
// Authentication headers.
|
||||
HeaderNames.WWWAuthenticate, HeaderNames.Authorization, HeaderNames.ProxyAuthenticate, HeaderNames.ProxyAuthorization, HeaderNames.SetCookie, HeaderNames.Cookie,
|
||||
|
||||
// Response control data.
|
||||
// rfc7231#section-7.1: Control Data.
|
||||
HeaderNames.Age, HeaderNames.Expires, HeaderNames.Date, HeaderNames.Location, HeaderNames.RetryAfter, HeaderNames.Vary, HeaderNames.Warning,
|
||||
|
||||
// Content-Encoding, Content-Type, Content-Range, and Trailer itself.
|
||||
HeaderNames.ContentEncoding, HeaderNames.ContentType, HeaderNames.ContentRange, HeaderNames.Trailer
|
||||
};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
(Get-Content C:\Windows\System32\inetsrv\config\redirection.config) -replace 'enabled="true"', 'enabled="false"' | Out-File C:\Windows\System32\inetsrv\config\redirection.config
|
||||
Loading…
Reference in New Issue