[
  {
    "path": ".appveyor.yml",
    "content": "init:\n- git config --global core.autocrlf true\nbranches:\n  only:\n  - master\n  - /^release\\/.*$/\n  - /^(.*\\/)?ci-.*$/\nbuild_script:\n- ps: .\\run.ps1 default-build\nclone_depth: 1\nenvironment:\n  global:\n    DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true\n    DOTNET_CLI_TELEMETRY_OPTOUT: 1\ntest: 'off'\ndeploy: 'off'\nos: Visual Studio 2017\n"
  },
  {
    "path": ".gitattributes",
    "content": "*.doc  diff=astextplain\n*.DOC\tdiff=astextplain\n*.docx\tdiff=astextplain\n*.DOCX\tdiff=astextplain\n*.dot\tdiff=astextplain\n*.DOT\tdiff=astextplain\n*.pdf\tdiff=astextplain\n*.PDF\tdiff=astextplain\n*.rtf\tdiff=astextplain\n*.RTF\tdiff=astextplain\n\n*.jpg  \tbinary\n*.png \tbinary\n*.gif \tbinary\n\n*.cs text=auto diff=csharp \n*.vb text=auto\n*.resx text=auto\n*.c text=auto\n*.cpp text=auto\n*.cxx text=auto\n*.h text=auto\n*.hxx text=auto\n*.py text=auto\n*.rb text=auto\n*.java text=auto\n*.html text=auto\n*.htm text=auto\n*.css text=auto\n*.scss text=auto\n*.sass text=auto\n*.less text=auto\n*.js text=auto\n*.lisp text=auto\n*.clj text=auto\n*.sql text=auto\n*.php text=auto\n*.lua text=auto\n*.m text=auto\n*.asm text=auto\n*.erl text=auto\n*.fs text=auto\n*.fsx text=auto\n*.hs text=auto\n\n*.csproj text=auto\n*.vbproj text=auto\n*.fsproj text=auto\n*.dbproj text=auto\n*.sln text=auto eol=crlf\n*.sh eol=lf"
  },
  {
    "path": ".gitignore",
    "content": "[Oo]bj/\n[Bb]in/\nTestResults/\n.nuget/\n*.sln.ide/\n_ReSharper.*/\npackages/\nartifacts/\nPublishProfiles/\n*.user\n*.suo\n*.cache\n*.docstates\n_ReSharper.*\nnuget.exe\nproject.lock.json\n*net45.csproj\n*net451.csproj\n*k10.csproj\n*.psess\n*.vsp\n*.pidb\n*.userprefs\n*DS_Store\n*.ncrunchsolution\n*.*sdf\n*.ipch\n.vs/\n.build/\n.testPublish/\n.idea/\n.vscode/\n*.nuget.props\n*.nuget.targets\nglobal.json\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: csharp\nsudo: false\ndist: trusty\nenv:\n  global:\n  - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true\n  - DOTNET_CLI_TELEMETRY_OPTOUT: 1\nmono: none\nos:\n- linux\n- osx\nosx_image: xcode8.2\naddons:\n  apt:\n    packages:\n    - libunwind8\nbranches:\n  only:\n  - master\n  - /^release\\/.*$/\n  - /^(.*\\/)?ci-.*$/\nbefore_install:\n- if test \"$TRAVIS_OS_NAME\" == \"osx\"; then brew update; brew install openssl; ln -s\n  /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib\n  /usr/local/lib/; fi\nscript:\n- ./build.sh\n"
  },
  {
    "path": ".vsts-pipelines/builds/ci-internal.yml",
    "content": "trigger:\n- master\n- release/*\n\nresources:\n  repositories:\n  - repository: buildtools\n    type: git\n    name: aspnet-BuildTools\n    ref: refs/heads/master\n\nphases:\n- template: .vsts-pipelines/templates/project-ci.yml@buildtools\n"
  },
  {
    "path": ".vsts-pipelines/builds/ci-public.yml",
    "content": "trigger:\n- master\n- release/*\n\n# See https://github.com/aspnet/BuildTools\nresources:\n  repositories:\n  - repository: buildtools\n    type: github\n    endpoint: DotNet-Bot GitHub Connection\n    name: aspnet/BuildTools\n    ref: refs/heads/master\n\nphases:\n- template: .vsts-pipelines/templates/project-ci.yml@buildtools\n"
  },
  {
    "path": "BasicMiddleware.sln",
    "content": "Microsoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.27130.2027\r\nMinimumVisualStudioVersion = 15.0.26730.03\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.HttpOverrides\", \"src\\Microsoft.AspNetCore.HttpOverrides\\Microsoft.AspNetCore.HttpOverrides.csproj\", \"{517308C3-B477-4B01-B461-CAB9C10B6928}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"src\", \"src\", \"{A5076D28-FA7E-4606-9410-FEDD0D603527}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\tsrc\\Directory.Build.props = src\\Directory.Build.props\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"test\", \"test\", \"{8437B0F3-3894-4828-A945-A9187F37631D}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\ttest\\Directory.Build.props = test\\Directory.Build.props\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.HttpOverrides.Tests\", \"test\\Microsoft.AspNetCore.HttpOverrides.Tests\\Microsoft.AspNetCore.HttpOverrides.Tests.csproj\", \"{D6341B92-3416-4F11-8DF4-CB274296175F}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.Buffering\", \"src\\Microsoft.AspNetCore.Buffering\\Microsoft.AspNetCore.Buffering.csproj\", \"{2363D0DD-A3BF-437E-9B64-B33AE132D875}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.Buffering.Tests\", \"test\\Microsoft.AspNetCore.Buffering.Tests\\Microsoft.AspNetCore.Buffering.Tests.csproj\", \"{F5F1D123-9C81-4A9E-8644-AA46B8E578FB}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"samples\", \"samples\", \"{9587FE9F-5A17-42C4-8021-E87F59CECB98}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"ResponseBufferingSample\", \"samples\\ResponseBufferingSample\\ResponseBufferingSample.csproj\", \"{E5C55B80-7827-40EB-B661-32B0E0E431CA}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"HttpOverridesSample\", \"samples\\HttpOverridesSample\\HttpOverridesSample.csproj\", \"{7F95478D-E1D4-4A64-BA42-B041591A96EB}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.Rewrite\", \"src\\Microsoft.AspNetCore.Rewrite\\Microsoft.AspNetCore.Rewrite.csproj\", \"{0E7CA1A7-1DC3-4CE6-B9C7-1688FE1410F1}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"RewriteSample\", \"samples\\RewriteSample\\RewriteSample.csproj\", \"{9E049645-13BC-4598-89E1-5B43D36E5D14}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.Rewrite.Tests\", \"test\\Microsoft.AspNetCore.Rewrite.Tests\\Microsoft.AspNetCore.Rewrite.Tests.csproj\", \"{31794F9E-A1AA-4535-B03C-A3233737CD1A}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.ResponseCompression\", \"src\\Microsoft.AspNetCore.ResponseCompression\\Microsoft.AspNetCore.ResponseCompression.csproj\", \"{45308A9D-F4C6-46A8-A24F-E73D995CC223}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.ResponseCompression.Tests\", \"test\\Microsoft.AspNetCore.ResponseCompression.Tests\\Microsoft.AspNetCore.ResponseCompression.Tests.csproj\", \"{3360A5D1-70C0-49EE-9051-04A6A6B836DC}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"ResponseCompressionSample\", \"samples\\ResponseCompressionSample\\ResponseCompressionSample.csproj\", \"{B2A3CE38-51B2-4486-982C-98C380AF140E}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{59A9B64C-E9BE-409E-89A2-58D72E2918F5}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\t.appveyor.yml = .appveyor.yml\r\n\t\t.gitattributes = .gitattributes\r\n\t\t.gitignore = .gitignore\r\n\t\t.travis.yml = .travis.yml\r\n\t\tbuild.cmd = build.cmd\r\n\t\tbuild.ps1 = build.ps1\r\n\t\tbuild.sh = build.sh\r\n\t\tCONTRIBUTING.md = CONTRIBUTING.md\r\n\t\tDirectory.Build.props = Directory.Build.props\r\n\t\tDirectory.Build.targets = Directory.Build.targets\r\n\t\tLICENSE.txt = LICENSE.txt\r\n\t\tNuGet.config = NuGet.config\r\n\t\tNuGetPackageVerifier.json = NuGetPackageVerifier.json\r\n\t\tREADME.md = README.md\r\n\t\tversion.xml = version.xml\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.HttpsPolicy\", \"src\\Microsoft.AspNetCore.HttpsPolicy\\Microsoft.AspNetCore.HttpsPolicy.csproj\", \"{4D39C29B-4EC8-497C-B411-922DA494D71B}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"HttpsPolicySample\", \"samples\\HttpsPolicySample\\HttpsPolicySample.csproj\", \"{AC424AEE-4883-49C6-945F-2FC916B8CA1C}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.HttpsPolicy.Tests\", \"test\\Microsoft.AspNetCore.HttpsPolicy.Tests\\Microsoft.AspNetCore.HttpsPolicy.Tests.csproj\", \"{1C67B0F1-6E70-449E-A2F1-98B9D5C576CE}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"HostFilteringSample\", \"samples\\HostFilteringSample\\HostFilteringSample.csproj\", \"{368B00A2-992A-4B0E-9085-A8136A22922D}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"build\", \"build\", \"{5CEA6F31-A829-4A02-8CD5-EC3DDD4CC1EA}\"\r\n\tProjectSection(SolutionItems) = preProject\r\n\t\tbuild\\dependencies.props = build\\dependencies.props\r\n\t\tbuild\\repo.props = build\\repo.props\r\n\t\tbuild\\sources.props = build\\sources.props\r\n\tEndProjectSection\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.HostFiltering.Tests\", \"test\\Microsoft.AspNetCore.HostFiltering.Tests\\Microsoft.AspNetCore.HostFiltering.Tests.csproj\", \"{4BC947ED-13B8-4BE6-82A4-96A48D86980B}\"\r\nEndProject\r\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Microsoft.AspNetCore.HostFiltering\", \"src\\Microsoft.AspNetCore.HostFiltering\\Microsoft.AspNetCore.HostFiltering.csproj\", \"{762F7276-C916-4111-A6C0-41668ABB3823}\"\r\nEndProject\r\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"benchmarks\", \"benchmarks\", \"{C6DA6317-30FC-42FE-891C-64E75D88FF12}\"\r\nEndProject\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"Microsoft.AspNetCore.ResponseCompression.Benchmarks\", \"benchmarks\\Microsoft.AspNetCore.ResponseCompression.Benchmarks\\Microsoft.AspNetCore.ResponseCompression.Benchmarks.csproj\", \"{5AF10E85-5076-40B9-84CF-9830B585ABE5}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Any CPU = Debug|Any CPU\r\n\t\tRelease|Any CPU = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{517308C3-B477-4B01-B461-CAB9C10B6928}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{517308C3-B477-4B01-B461-CAB9C10B6928}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{517308C3-B477-4B01-B461-CAB9C10B6928}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{517308C3-B477-4B01-B461-CAB9C10B6928}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{D6341B92-3416-4F11-8DF4-CB274296175F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{D6341B92-3416-4F11-8DF4-CB274296175F}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{D6341B92-3416-4F11-8DF4-CB274296175F}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{D6341B92-3416-4F11-8DF4-CB274296175F}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{2363D0DD-A3BF-437E-9B64-B33AE132D875}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{2363D0DD-A3BF-437E-9B64-B33AE132D875}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{2363D0DD-A3BF-437E-9B64-B33AE132D875}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{2363D0DD-A3BF-437E-9B64-B33AE132D875}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{F5F1D123-9C81-4A9E-8644-AA46B8E578FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{F5F1D123-9C81-4A9E-8644-AA46B8E578FB}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{F5F1D123-9C81-4A9E-8644-AA46B8E578FB}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{F5F1D123-9C81-4A9E-8644-AA46B8E578FB}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{E5C55B80-7827-40EB-B661-32B0E0E431CA}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{7F95478D-E1D4-4A64-BA42-B041591A96EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{7F95478D-E1D4-4A64-BA42-B041591A96EB}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{7F95478D-E1D4-4A64-BA42-B041591A96EB}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{7F95478D-E1D4-4A64-BA42-B041591A96EB}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{0E7CA1A7-1DC3-4CE6-B9C7-1688FE1410F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{0E7CA1A7-1DC3-4CE6-B9C7-1688FE1410F1}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{0E7CA1A7-1DC3-4CE6-B9C7-1688FE1410F1}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{0E7CA1A7-1DC3-4CE6-B9C7-1688FE1410F1}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{9E049645-13BC-4598-89E1-5B43D36E5D14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{9E049645-13BC-4598-89E1-5B43D36E5D14}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{9E049645-13BC-4598-89E1-5B43D36E5D14}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{9E049645-13BC-4598-89E1-5B43D36E5D14}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{31794F9E-A1AA-4535-B03C-A3233737CD1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{31794F9E-A1AA-4535-B03C-A3233737CD1A}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{31794F9E-A1AA-4535-B03C-A3233737CD1A}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{31794F9E-A1AA-4535-B03C-A3233737CD1A}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{45308A9D-F4C6-46A8-A24F-E73D995CC223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{45308A9D-F4C6-46A8-A24F-E73D995CC223}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{45308A9D-F4C6-46A8-A24F-E73D995CC223}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{45308A9D-F4C6-46A8-A24F-E73D995CC223}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{3360A5D1-70C0-49EE-9051-04A6A6B836DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{3360A5D1-70C0-49EE-9051-04A6A6B836DC}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{3360A5D1-70C0-49EE-9051-04A6A6B836DC}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{3360A5D1-70C0-49EE-9051-04A6A6B836DC}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{B2A3CE38-51B2-4486-982C-98C380AF140E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{B2A3CE38-51B2-4486-982C-98C380AF140E}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{B2A3CE38-51B2-4486-982C-98C380AF140E}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{B2A3CE38-51B2-4486-982C-98C380AF140E}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{4D39C29B-4EC8-497C-B411-922DA494D71B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{4D39C29B-4EC8-497C-B411-922DA494D71B}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{4D39C29B-4EC8-497C-B411-922DA494D71B}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{4D39C29B-4EC8-497C-B411-922DA494D71B}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{AC424AEE-4883-49C6-945F-2FC916B8CA1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{AC424AEE-4883-49C6-945F-2FC916B8CA1C}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{AC424AEE-4883-49C6-945F-2FC916B8CA1C}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{AC424AEE-4883-49C6-945F-2FC916B8CA1C}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{1C67B0F1-6E70-449E-A2F1-98B9D5C576CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{1C67B0F1-6E70-449E-A2F1-98B9D5C576CE}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{1C67B0F1-6E70-449E-A2F1-98B9D5C576CE}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{1C67B0F1-6E70-449E-A2F1-98B9D5C576CE}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{368B00A2-992A-4B0E-9085-A8136A22922D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{368B00A2-992A-4B0E-9085-A8136A22922D}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{368B00A2-992A-4B0E-9085-A8136A22922D}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{368B00A2-992A-4B0E-9085-A8136A22922D}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{4BC947ED-13B8-4BE6-82A4-96A48D86980B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{4BC947ED-13B8-4BE6-82A4-96A48D86980B}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{4BC947ED-13B8-4BE6-82A4-96A48D86980B}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{4BC947ED-13B8-4BE6-82A4-96A48D86980B}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{762F7276-C916-4111-A6C0-41668ABB3823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{762F7276-C916-4111-A6C0-41668ABB3823}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{762F7276-C916-4111-A6C0-41668ABB3823}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{762F7276-C916-4111-A6C0-41668ABB3823}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\t\t{5AF10E85-5076-40B9-84CF-9830B585ABE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{5AF10E85-5076-40B9-84CF-9830B585ABE5}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{5AF10E85-5076-40B9-84CF-9830B585ABE5}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{5AF10E85-5076-40B9-84CF-9830B585ABE5}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(NestedProjects) = preSolution\r\n\t\t{517308C3-B477-4B01-B461-CAB9C10B6928} = {A5076D28-FA7E-4606-9410-FEDD0D603527}\r\n\t\t{D6341B92-3416-4F11-8DF4-CB274296175F} = {8437B0F3-3894-4828-A945-A9187F37631D}\r\n\t\t{2363D0DD-A3BF-437E-9B64-B33AE132D875} = {A5076D28-FA7E-4606-9410-FEDD0D603527}\r\n\t\t{F5F1D123-9C81-4A9E-8644-AA46B8E578FB} = {8437B0F3-3894-4828-A945-A9187F37631D}\r\n\t\t{E5C55B80-7827-40EB-B661-32B0E0E431CA} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}\r\n\t\t{7F95478D-E1D4-4A64-BA42-B041591A96EB} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}\r\n\t\t{0E7CA1A7-1DC3-4CE6-B9C7-1688FE1410F1} = {A5076D28-FA7E-4606-9410-FEDD0D603527}\r\n\t\t{9E049645-13BC-4598-89E1-5B43D36E5D14} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}\r\n\t\t{31794F9E-A1AA-4535-B03C-A3233737CD1A} = {8437B0F3-3894-4828-A945-A9187F37631D}\r\n\t\t{45308A9D-F4C6-46A8-A24F-E73D995CC223} = {A5076D28-FA7E-4606-9410-FEDD0D603527}\r\n\t\t{3360A5D1-70C0-49EE-9051-04A6A6B836DC} = {8437B0F3-3894-4828-A945-A9187F37631D}\r\n\t\t{B2A3CE38-51B2-4486-982C-98C380AF140E} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}\r\n\t\t{4D39C29B-4EC8-497C-B411-922DA494D71B} = {A5076D28-FA7E-4606-9410-FEDD0D603527}\r\n\t\t{AC424AEE-4883-49C6-945F-2FC916B8CA1C} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}\r\n\t\t{1C67B0F1-6E70-449E-A2F1-98B9D5C576CE} = {8437B0F3-3894-4828-A945-A9187F37631D}\r\n\t\t{368B00A2-992A-4B0E-9085-A8136A22922D} = {9587FE9F-5A17-42C4-8021-E87F59CECB98}\r\n\t\t{5CEA6F31-A829-4A02-8CD5-EC3DDD4CC1EA} = {59A9B64C-E9BE-409E-89A2-58D72E2918F5}\r\n\t\t{4BC947ED-13B8-4BE6-82A4-96A48D86980B} = {8437B0F3-3894-4828-A945-A9187F37631D}\r\n\t\t{762F7276-C916-4111-A6C0-41668ABB3823} = {A5076D28-FA7E-4606-9410-FEDD0D603527}\r\n\t\t{5AF10E85-5076-40B9-84CF-9830B585ABE5} = {C6DA6317-30FC-42FE-891C-64E75D88FF12}\r\n\tEndGlobalSection\r\n\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n\t\tSolutionGuid = {4518E9CE-3680-4E05-9259-B64EA7807158}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing\n======\n\nInformation on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo.\n"
  },
  {
    "path": "Directory.Build.props",
    "content": "﻿<Project>\n  <Import\n    Project=\"$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))\\AspNetCoreSettings.props\"\n    Condition=\" '$(CI)' != 'true' AND '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), AspNetCoreSettings.props))' != '' \" />\n\n  <Import Project=\"version.props\" />\n  <Import Project=\"build\\dependencies.props\" />\n  <Import Project=\"build\\sources.props\" />\n\n  <PropertyGroup>\n    <Product>Microsoft ASP.NET Core</Product>\n    <RepositoryUrl>https://github.com/aspnet/BasicMiddleware</RepositoryUrl>\n    <RepositoryType>git</RepositoryType>\n    <RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>\n    <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)build\\Key.snk</AssemblyOriginatorKeyFile>\n    <SignAssembly>true</SignAssembly>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n  </PropertyGroup>\n\n</Project>\n"
  },
  {
    "path": "Directory.Build.targets",
    "content": "<Project>\n  <PropertyGroup>\n    <RuntimeFrameworkVersion Condition=\" '$(TargetFramework)' == 'netcoreapp2.1' \">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>\n    <RuntimeFrameworkVersion Condition=\" '$(TargetFramework)' == 'netcoreapp2.2' \">$(MicrosoftNETCoreApp22PackageVersion)</RuntimeFrameworkVersion>\n    <NETStandardImplicitPackageVersion Condition=\" '$(TargetFramework)' == 'netstandard2.0' \">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>\n    <!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->\n    <NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>\n  </PropertyGroup>\n</Project>\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright (c) .NET Foundation and Contributors\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "NuGet.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n  <packageSources>\n    <clear />\n    <!-- Restore sources should be defined in build/sources.props. -->\n  </packageSources>\n</configuration>\n"
  },
  {
    "path": "NuGetPackageVerifier.json",
    "content": "{\n    \"Default\": {\n        \"rules\": [\n            \"DefaultCompositeRule\"\n        ]\n    }\n}"
  },
  {
    "path": "README.md",
    "content": "ASP.NET Core Basic Middleware Components [Archived]\n===================================================\n\n**This GitHub project has been archived.** Ongoing development on this project can be found in <https://github.com/aspnet/AspNetCore>.\n\nThis repo hosts a collection of basic middleware components for ASP.NET Core. This includes Buffering, HTTP Overrides, Response Compression, and URL Rewriting. \nThe Rewrite middleware can import rules from IIS's UrlRewrite and Apache's mod_rewrite.\n\nThis project is part of ASP.NET Core. You can find samples, documentation and getting started instructions for ASP.NET Core at the [AspNetCore](https://github.com/aspnet/AspNetCore) repo.\n"
  },
  {
    "path": "benchmarks/Microsoft.AspNetCore.ResponseCompression.Benchmarks/AssemblyInfo.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\n[assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark]\n"
  },
  {
    "path": "benchmarks/Microsoft.AspNetCore.ResponseCompression.Benchmarks/Microsoft.AspNetCore.ResponseCompression.Benchmarks.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>netcoreapp2.1</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.ResponseCompression\\Microsoft.AspNetCore.ResponseCompression.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"BenchmarkDotNet\" Version=\"$(BenchmarkDotNetPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Http\" Version=\"$(MicrosoftAspNetCoreHttpPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.BenchmarkRunner.Sources\" Version=\"$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"$(MicrosoftExtensionsDependencyInjectionPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "benchmarks/Microsoft.AspNetCore.ResponseCompression.Benchmarks/ResponseCompressionProviderBenchmark.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing BenchmarkDotNet.Attributes;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Options;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.ResponseCompression.Benchmarks\n{\n    public class ResponseCompressionProviderBenchmark\n    {\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            var services = new ServiceCollection()\n                .AddOptions()\n                .AddResponseCompression()\n                .BuildServiceProvider();\n\n            var options = new ResponseCompressionOptions();\n\n            Provider = new ResponseCompressionProvider(services, Options.Create(options));\n        }\n\n        [ParamsSource(nameof(EncodingStrings))]\n        public string AcceptEncoding { get; set; }\n\n        public static IEnumerable<string> EncodingStrings()\n        {\n            return new[]\n            {\n                \"gzip;q=0.8, compress;q=0.6, br;q=0.4\",\n                \"gzip, compress, br\",\n                \"br, compress, gzip\",\n                \"gzip, compress\",\n                \"identity\",\n                \"*\"\n            };\n        }\n\n        public ResponseCompressionProvider Provider { get; set; }\n\n        [Benchmark]\n        public ICompressionProvider GetCompressionProvider()\n        {\n            var context = new DefaultHttpContext();\n\n            context.Request.Headers[HeaderNames.AcceptEncoding] = AcceptEncoding;\n\n            return Provider.GetCompressionProvider(context);\n        }\n    }\n}"
  },
  {
    "path": "build/dependencies.props",
    "content": "﻿<Project>\n  <PropertyGroup>\n    <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>\n  </PropertyGroup>\n  <PropertyGroup Label=\"Package Versions\">\n    <BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>\n    <InternalAspNetCoreSdkPackageVersion>3.0.0-alpha1-20181011.3</InternalAspNetCoreSdkPackageVersion>\n    <MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>\n    <MicrosoftAspNetCoreHostingAbstractionsPackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>\n    <MicrosoftAspNetCoreHttpAbstractionsPackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreHttpAbstractionsPackageVersion>\n    <MicrosoftAspNetCoreHttpExtensionsPackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreHttpExtensionsPackageVersion>\n    <MicrosoftAspNetCoreHttpPackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreHttpPackageVersion>\n    <MicrosoftAspNetCoreServerKestrelCorePackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreServerKestrelCorePackageVersion>\n    <MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreServerKestrelHttpsPackageVersion>\n    <MicrosoftAspNetCoreServerKestrelPackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreServerKestrelPackageVersion>\n    <MicrosoftAspNetCoreTestHostPackageVersion>3.0.0-alpha1-10605</MicrosoftAspNetCoreTestHostPackageVersion>\n    <MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>\n    <MicrosoftExtensionsConfigurationBinderPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsConfigurationBinderPackageVersion>\n    <MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsConfigurationJsonPackageVersion>\n    <MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsDependencyInjectionPackageVersion>\n    <MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>\n    <MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsLoggingAbstractionsPackageVersion>\n    <MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsLoggingConsolePackageVersion>\n    <MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsLoggingTestingPackageVersion>\n    <MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>\n    <MicrosoftExtensionsOptionsPackageVersion>3.0.0-alpha1-10605</MicrosoftExtensionsOptionsPackageVersion>\n    <MicrosoftNETCoreApp21PackageVersion>2.1.3</MicrosoftNETCoreApp21PackageVersion>\n    <MicrosoftNETCoreApp22PackageVersion>2.2.0-preview2-26905-02</MicrosoftNETCoreApp22PackageVersion>\n    <MicrosoftNetHttpHeadersPackageVersion>3.0.0-alpha1-10605</MicrosoftNetHttpHeadersPackageVersion>\n    <MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>\n    <MoqPackageVersion>4.10.0</MoqPackageVersion>\n    <NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>\n    <XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>\n    <XunitPackageVersion>2.3.1</XunitPackageVersion>\n    <XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>\n  </PropertyGroup>\n  <PropertyGroup Label=\"Package Versions: Pinned\" />\n  <Import Project=\"$(DotNetPackageVersionPropsPath)\" Condition=\" '$(DotNetPackageVersionPropsPath)' != '' \" />\n  <PropertyGroup Label=\"Package Versions: Pinned\" />\n</Project>\n"
  },
  {
    "path": "build/repo.props",
    "content": "<Project>\n  <Import Project=\"dependencies.props\" />\n\n  <PropertyGroup>\n    <!-- These properties are use by the automation that updates dependencies.props -->\n    <LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>\n    <LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <DotNetCoreRuntime Include=\"$(MicrosoftNETCoreApp22PackageVersion)\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "build/sources.props",
    "content": "<Project>\n  <Import Project=\"$(DotNetRestoreSourcePropsPath)\" Condition=\"'$(DotNetRestoreSourcePropsPath)' != ''\"/>\n\n  <PropertyGroup Label=\"RestoreSources\">\n    <RestoreSources>$(DotNetRestoreSources)</RestoreSources>\n    <RestoreSources Condition=\"'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' \">\n      $(RestoreSources);\n      https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;\n      https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;\n      https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;\n    </RestoreSources>\n    <RestoreSources Condition=\"'$(DotNetBuildOffline)' != 'true'\">\n      $(RestoreSources);\n      https://api.nuget.org/v3/index.json;\n    </RestoreSources>\n  </PropertyGroup>\n</Project>\n"
  },
  {
    "path": "build.cmd",
    "content": "@ECHO OFF\nPowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command \"[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE\"\n"
  },
  {
    "path": "build.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\n# Call \"sync\" between \"chmod\" and execution to prevent \"text file busy\" error in Docker (aufs)\nchmod +x \"$DIR/run.sh\"; sync\n\"$DIR/run.sh\" default-build \"$@\"\n"
  },
  {
    "path": "korebuild-lock.txt",
    "content": "version:3.0.0-alpha1-20181011.3\ncommithash:e7569d931e994629267ab2646e9926140962b4ac\n"
  },
  {
    "path": "korebuild.json",
    "content": "{\n  \"$schema\": \"https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json\",\n  \"channel\": \"master\"\n}\n"
  },
  {
    "path": "run.cmd",
    "content": "@ECHO OFF\nPowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command \"[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE\"\n"
  },
  {
    "path": "run.ps1",
    "content": "#!/usr/bin/env powershell\n#requires -version 4\n\n<#\n.SYNOPSIS\nExecutes KoreBuild commands.\n\n.DESCRIPTION\nDownloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`.\n\n.PARAMETER Command\nThe KoreBuild command to run.\n\n.PARAMETER Path\nThe folder to build. Defaults to the folder containing this script.\n\n.PARAMETER Channel\nThe channel of KoreBuild to download. Overrides the value from the config file.\n\n.PARAMETER DotNetHome\nThe directory where .NET Core tools will be stored.\n\n.PARAMETER ToolsSource\nThe base url where build tools can be downloaded. Overrides the value from the config file.\n\n.PARAMETER Update\nUpdates KoreBuild to the latest version even if a lock file is present.\n\n.PARAMETER Reinstall\nRe-installs KoreBuild\n\n.PARAMETER ConfigFile\nThe path to the configuration file that stores values. Defaults to korebuild.json.\n\n.PARAMETER ToolsSourceSuffix\nThe Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores.\n\n.PARAMETER CI\nSets up CI specific settings and variables.\n\n.PARAMETER Arguments\nArguments to be passed to the command\n\n.NOTES\nThis function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.\nWhen the lockfile is not present, KoreBuild will create one using latest available version from $Channel.\n\nThe $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set\nin the file are overridden by command line parameters.\n\n.EXAMPLE\nExample config file:\n```json\n{\n  \"$schema\": \"https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json\",\n  \"channel\": \"master\",\n  \"toolsSource\": \"https://aspnetcore.blob.core.windows.net/buildtools\"\n}\n```\n#>\n[CmdletBinding(PositionalBinding = $false)]\nparam(\n    [Parameter(Mandatory = $true, Position = 0)]\n    [string]$Command,\n    [string]$Path = $PSScriptRoot,\n    [Alias('c')]\n    [string]$Channel,\n    [Alias('d')]\n    [string]$DotNetHome,\n    [Alias('s')]\n    [string]$ToolsSource,\n    [Alias('u')]\n    [switch]$Update,\n    [switch]$Reinstall,\n    [string]$ToolsSourceSuffix,\n    [string]$ConfigFile = $null,\n    [switch]$CI,\n    [Parameter(ValueFromRemainingArguments = $true)]\n    [string[]]$Arguments\n)\n\nSet-StrictMode -Version 2\n$ErrorActionPreference = 'Stop'\n\n#\n# Functions\n#\n\nfunction Get-KoreBuild {\n\n    $lockFile = Join-Path $Path 'korebuild-lock.txt'\n\n    if (!(Test-Path $lockFile) -or $Update) {\n        Get-RemoteFile \"$ToolsSource/korebuild/channels/$Channel/latest.txt\" $lockFile $ToolsSourceSuffix\n    }\n\n    $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1\n    if (!$version) {\n        Write-Error \"Failed to parse version from $lockFile. Expected a line that begins with 'version:'\"\n    }\n    $version = $version.TrimStart('version:').Trim()\n    $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)\n\n    if ($Reinstall -and (Test-Path $korebuildPath)) {\n        Remove-Item -Force -Recurse $korebuildPath\n    }\n\n    if (!(Test-Path $korebuildPath)) {\n        Write-Host -ForegroundColor Magenta \"Downloading KoreBuild $version\"\n        New-Item -ItemType Directory -Path $korebuildPath | Out-Null\n        $remotePath = \"$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip\"\n\n        try {\n            $tmpfile = Join-Path ([IO.Path]::GetTempPath()) \"KoreBuild-$([guid]::NewGuid()).zip\"\n            Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix\n            if (Get-Command -Name 'Microsoft.PowerShell.Archive\\Expand-Archive' -ErrorAction Ignore) {\n                # Use built-in commands where possible as they are cross-plat compatible\n                Microsoft.PowerShell.Archive\\Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath\n            }\n            else {\n                # Fallback to old approach for old installations of PowerShell\n                Add-Type -AssemblyName System.IO.Compression.FileSystem\n                [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)\n            }\n        }\n        catch {\n            Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore\n            throw\n        }\n        finally {\n            Remove-Item $tmpfile -ErrorAction Ignore\n        }\n    }\n\n    return $korebuildPath\n}\n\nfunction Join-Paths([string]$path, [string[]]$childPaths) {\n    $childPaths | ForEach-Object { $path = Join-Path $path $_ }\n    return $path\n}\n\nfunction Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) {\n    if ($RemotePath -notlike 'http*') {\n        Copy-Item $RemotePath $LocalPath\n        return\n    }\n\n    $retries = 10\n    while ($retries -gt 0) {\n        $retries -= 1\n        try {\n            Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath\n            return\n        }\n        catch {\n            Write-Verbose \"Request failed. $retries retries remaining\"\n        }\n    }\n\n    Write-Error \"Download failed: '$RemotePath'.\"\n}\n\n#\n# Main\n#\n\n# Load configuration or set defaults\n\n$Path = Resolve-Path $Path\nif (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' }\n\nif (Test-Path $ConfigFile) {\n    try {\n        $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json\n        if ($config) {\n            if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }\n            if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}\n        }\n    }\n    catch {\n        Write-Host -ForegroundColor Red $Error[0]\n        Write-Error \"$ConfigFile contains invalid JSON.\"\n        exit 1\n    }\n}\n\nif (!$DotNetHome) {\n    $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `\n        elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `\n        elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`\n        else { Join-Path $PSScriptRoot '.dotnet'}\n}\n\nif (!$Channel) { $Channel = 'master' }\nif (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }\n\n# Execute\n\n$korebuildPath = Get-KoreBuild\nImport-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')\n\ntry {\n    Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile -CI:$CI\n    Invoke-KoreBuildCommand $Command @Arguments\n}\nfinally {\n    Remove-Module 'KoreBuild' -ErrorAction Ignore\n}\n"
  },
  {
    "path": "run.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\n#\n# variables\n#\n\nRESET=\"\\033[0m\"\nRED=\"\\033[0;31m\"\nYELLOW=\"\\033[0;33m\"\nMAGENTA=\"\\033[0;95m\"\nDIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n[ -z \"${DOTNET_HOME:-}\" ] && DOTNET_HOME=\"$HOME/.dotnet\"\nverbose=false\nupdate=false\nreinstall=false\nrepo_path=\"$DIR\"\nchannel=''\ntools_source=''\ntools_source_suffix=''\nci=false\n\n#\n# Functions\n#\n__usage() {\n    echo \"Usage: $(basename \"${BASH_SOURCE[0]}\") command [options] [[--] <Arguments>...]\"\n    echo \"\"\n    echo \"Arguments:\"\n    echo \"    command                The command to be run.\"\n    echo \"    <Arguments>...         Arguments passed to the command. Variable number of arguments allowed.\"\n    echo \"\"\n    echo \"Options:\"\n    echo \"    --verbose                                             Show verbose output.\"\n    echo \"    -c|--channel <CHANNEL>                                The channel of KoreBuild to download. Overrides the value from the config file..\"\n    echo \"    --config-file <FILE>                                  The path to the configuration file that stores values. Defaults to korebuild.json.\"\n    echo \"    -d|--dotnet-home <DIR>                                The directory where .NET Core tools will be stored. Defaults to '\\$DOTNET_HOME' or '\\$HOME/.dotnet.\"\n    echo \"    --path <PATH>                                         The directory to build. Defaults to the directory containing the script.\"\n    echo \"    -s|--tools-source|-ToolsSource <URL>                  The base url where build tools can be downloaded. Overrides the value from the config file.\"\n    echo \"    --tools-source-suffix|-ToolsSourceSuffix <SUFFIX>     The suffix to append to tools-source. Useful for query strings.\"\n    echo \"    -u|--update                                           Update to the latest KoreBuild even if the lock file is present.\"\n    echo \"    --reinstall                                           Reinstall KoreBuild.\"\n    echo \"    --ci                                                  Apply CI specific settings and environment variables.\"\n    echo \"\"\n    echo \"Description:\"\n    echo \"    This function will create a file \\$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.\"\n    echo \"    When the lockfile is not present, KoreBuild will create one using latest available version from \\$channel.\"\n\n    if [[ \"${1:-}\" != '--no-exit' ]]; then\n        exit 2\n    fi\n}\n\nget_korebuild() {\n    local version\n    local lock_file=\"$repo_path/korebuild-lock.txt\"\n    if [ ! -f \"$lock_file\" ] || [ \"$update\" = true ]; then\n        __get_remote_file \"$tools_source/korebuild/channels/$channel/latest.txt\" \"$lock_file\" \"$tools_source_suffix\"\n    fi\n    version=\"$(grep 'version:*' -m 1 \"$lock_file\")\"\n    if [[ \"$version\" == '' ]]; then\n        __error \"Failed to parse version from $lock_file. Expected a line that begins with 'version:'\"\n        return 1\n    fi\n    version=\"$(echo \"${version#version:}\" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')\"\n    local korebuild_path=\"$DOTNET_HOME/buildtools/korebuild/$version\"\n\n    if [ \"$reinstall\" = true ] && [ -d \"$korebuild_path\" ]; then\n        rm -rf \"$korebuild_path\"\n    fi\n\n    {\n        if [ ! -d \"$korebuild_path\" ]; then\n            mkdir -p \"$korebuild_path\"\n            local remote_path=\"$tools_source/korebuild/artifacts/$version/korebuild.$version.zip\"\n            tmpfile=\"$(mktemp)\"\n            echo -e \"${MAGENTA}Downloading KoreBuild ${version}${RESET}\"\n            if __get_remote_file \"$remote_path\" \"$tmpfile\" \"$tools_source_suffix\"; then\n                unzip -q -d \"$korebuild_path\" \"$tmpfile\"\n            fi\n            rm \"$tmpfile\" || true\n        fi\n\n        source \"$korebuild_path/KoreBuild.sh\"\n    } || {\n        if [ -d \"$korebuild_path\" ]; then\n            echo \"Cleaning up after failed installation\"\n            rm -rf \"$korebuild_path\" || true\n        fi\n        return 1\n    }\n}\n\n__error() {\n    echo -e \"${RED}error: $*${RESET}\" 1>&2\n}\n\n__warn() {\n    echo -e \"${YELLOW}warning: $*${RESET}\"\n}\n\n__machine_has() {\n    hash \"$1\" > /dev/null 2>&1\n    return $?\n}\n\n__get_remote_file() {\n    local remote_path=$1\n    local local_path=$2\n    local remote_path_suffix=$3\n\n    if [[ \"$remote_path\" != 'http'* ]]; then\n        cp \"$remote_path\" \"$local_path\"\n        return 0\n    fi\n\n    local failed=false\n    if __machine_has wget; then\n        wget --tries 10 --quiet -O \"$local_path\" \"${remote_path}${remote_path_suffix}\" || failed=true\n    else\n        failed=true\n    fi\n\n    if [ \"$failed\" = true ] && __machine_has curl; then\n        failed=false\n        curl --retry 10 -sSL -f --create-dirs -o \"$local_path\" \"${remote_path}${remote_path_suffix}\" || failed=true\n    fi\n\n    if [ \"$failed\" = true ]; then\n        __error \"Download failed: $remote_path\" 1>&2\n        return 1\n    fi\n}\n\n#\n# main\n#\n\ncommand=\"${1:-}\"\nshift\n\nwhile [[ $# -gt 0 ]]; do\n    case $1 in\n        -\\?|-h|--help)\n            __usage --no-exit\n            exit 0\n            ;;\n        -c|--channel|-Channel)\n            shift\n            channel=\"${1:-}\"\n            [ -z \"$channel\" ] && __usage\n            ;;\n        --config-file|-ConfigFile)\n            shift\n            config_file=\"${1:-}\"\n            [ -z \"$config_file\" ] && __usage\n            if [ ! -f \"$config_file\" ]; then\n                __error \"Invalid value for --config-file. $config_file does not exist.\"\n                exit 1\n            fi\n            ;;\n        -d|--dotnet-home|-DotNetHome)\n            shift\n            DOTNET_HOME=\"${1:-}\"\n            [ -z \"$DOTNET_HOME\" ] && __usage\n            ;;\n        --path|-Path)\n            shift\n            repo_path=\"${1:-}\"\n            [ -z \"$repo_path\" ] && __usage\n            ;;\n        -s|--tools-source|-ToolsSource)\n            shift\n            tools_source=\"${1:-}\"\n            [ -z \"$tools_source\" ] && __usage\n            ;;\n        --tools-source-suffix|-ToolsSourceSuffix)\n            shift\n            tools_source_suffix=\"${1:-}\"\n            [ -z \"$tools_source_suffix\" ] && __usage\n            ;;\n        -u|--update|-Update)\n            update=true\n            ;;\n        --reinstall|-[Rr]einstall)\n            reinstall=true\n            ;;\n        --ci|-[Cc][Ii])\n            ci=true\n            ;;\n        --verbose|-Verbose)\n            verbose=true\n            ;;\n        --)\n            shift\n            break\n            ;;\n        *)\n            break\n            ;;\n    esac\n    shift\ndone\n\nif ! __machine_has unzip; then\n    __error 'Missing required command: unzip'\n    exit 1\nfi\n\nif ! __machine_has curl && ! __machine_has wget; then\n    __error 'Missing required command. Either wget or curl is required.'\n    exit 1\nfi\n\n[ -z \"${config_file:-}\" ] && config_file=\"$repo_path/korebuild.json\"\nif [ -f \"$config_file\" ]; then\n    if __machine_has jq ; then\n        if jq '.' \"$config_file\" >/dev/null ; then\n            config_channel=\"$(jq -r 'select(.channel!=null) | .channel' \"$config_file\")\"\n            config_tools_source=\"$(jq -r 'select(.toolsSource!=null) | .toolsSource' \"$config_file\")\"\n        else\n            __error \"$config_file contains invalid JSON.\"\n            exit 1\n        fi\n    elif __machine_has python ; then\n        if python -c \"import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))\" >/dev/null ; then\n            config_channel=\"$(python -c \"import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')\")\"\n            config_tools_source=\"$(python -c \"import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')\")\"\n        else\n            __error \"$config_file contains invalid JSON.\"\n            exit 1\n        fi\n    elif __machine_has python3 ; then\n        if python3 -c \"import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))\" >/dev/null ; then\n            config_channel=\"$(python3 -c \"import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')\")\"\n            config_tools_source=\"$(python3 -c \"import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')\")\"\n        else\n            __error \"$config_file contains invalid JSON.\"\n            exit 1\n        fi\n    else\n        __error 'Missing required command: jq or python. Could not parse the JSON file.'\n        exit 1\n    fi\n\n    [ ! -z \"${config_channel:-}\" ] && channel=\"$config_channel\"\n    [ ! -z \"${config_tools_source:-}\" ] && tools_source=\"$config_tools_source\"\nfi\n\n[ -z \"$channel\" ] && channel='master'\n[ -z \"$tools_source\" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'\n\nget_korebuild\nset_korebuildsettings \"$tools_source\" \"$DOTNET_HOME\" \"$repo_path\" \"$config_file\" \"$ci\"\ninvoke_korebuild_command \"$command\" \"$@\"\n"
  },
  {
    "path": "samples/HostFilteringSample/HostFilteringSample.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.HostFiltering\\Microsoft.AspNetCore.HostFiltering.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Server.Kestrel\" Version=\"$(MicrosoftAspNetCoreServerKestrelPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Configuration.Json\" Version=\"$(MicrosoftExtensionsConfigurationJsonPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Console\" Version=\"$(MicrosoftExtensionsLoggingConsolePackageVersion)\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <Content Update=\"appsettings.Development.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Update=\"appsettings.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n    <Content Update=\"appsettings.Production.json\">\n      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n    </Content>\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/HostFilteringSample/Program.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Logging;\n\nnamespace HostFilteringSample\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            BuildWebHost(args).Run();\n        }\n\n        public static IWebHost BuildWebHost(string[] args)\n        {\n            var hostBuilder = new WebHostBuilder()\n                .ConfigureLogging((_, factory) =>\n                {\n                    factory.SetMinimumLevel(LogLevel.Debug);\n                    factory.AddConsole();\n                })\n                .ConfigureAppConfiguration((hostingContext, config) =>\n                {\n                    var env = hostingContext.HostingEnvironment;\n                    config.AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: true)\n                          .AddJsonFile($\"appsettings.{env.EnvironmentName}.json\", optional: true, reloadOnChange: true);\n                })\n                .UseKestrel()\n                .UseStartup<Startup>();\n\n            return hostBuilder.Build();\n        }\n    }\n}\n"
  },
  {
    "path": "samples/HostFilteringSample/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:14124/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"HostFilteringSample\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      },\n      \"applicationUrl\": \"http://localhost:14125/\"\n    }\n  }\n}"
  },
  {
    "path": "samples/HostFilteringSample/Startup.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.HostFiltering;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Options;\n\nnamespace HostFilteringSample\n{\n    public class Startup\n    {\n        public IConfiguration Config { get; }\n\n        public Startup(IConfiguration config)\n        {\n            Config = config;\n        }\n\n        public void ConfigureServices(IServiceCollection services)\n        {\n            services.AddHostFiltering(options =>\n            {\n\n            });\n\n            // Fallback\n            services.PostConfigure<HostFilteringOptions>(options =>\n            {\n                if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)\n                {\n                    // \"AllowedHosts\": \"localhost;127.0.0.1;[::1]\"\n                    var hosts = Config[\"AllowedHosts\"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);\n                    // Fall back to \"*\" to disable.\n                    options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { \"*\" });\n                }\n            });\n            // Change notification\n            services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(new ConfigurationChangeTokenSource<HostFilteringOptions>(Config));\n        }\n\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {\n            app.UseHostFiltering();\n\n            app.Run(context =>\n            {\n                return context.Response.WriteAsync(\"Hello World! \" + context.Request.Host);\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "samples/HostFilteringSample/appsettings.Development.json",
    "content": "﻿{\n  \"AllowedHosts\": \"localhost;127.0.0.1;[::1]\"\n}\n"
  },
  {
    "path": "samples/HostFilteringSample/appsettings.Production.json",
    "content": "﻿{\n  \"AllowedHosts\": \"example.com;localhost\"\n}\n"
  },
  {
    "path": "samples/HostFilteringSample/appsettings.json",
    "content": "﻿{\n\n}"
  },
  {
    "path": "samples/HttpOverridesSample/HttpOverridesSample.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.HttpOverrides\\Microsoft.AspNetCore.HttpOverrides.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Server.Kestrel\" Version=\"$(MicrosoftAspNetCoreServerKestrelPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/HttpOverridesSample/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:1658/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"web\": {\n      \"commandName\": \"web\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "samples/HttpOverridesSample/Startup.cs",
    "content": "using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.HttpOverrides;\n\nnamespace HttpOverridesSample\n{\n    public class Startup\n    {\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n        public void Configure(IApplicationBuilder app)\n        {\n            app.UseForwardedHeaders(new ForwardedHeadersOptions\n            {\n                ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto\n            });\n            app.UseHttpMethodOverride();\n\n            app.Run(async (context) =>\n            {\n                foreach (var header in context.Request.Headers)\n                {\n                    await context.Response.WriteAsync($\"{header.Key}: {header.Value}\\r\\n\");\n                }\n                await context.Response.WriteAsync($\"Method: {context.Request.Method}\\r\\n\");\n                await context.Response.WriteAsync($\"Scheme: {context.Request.Scheme}\\r\\n\");\n                await context.Response.WriteAsync($\"RemoteIP: {context.Connection.RemoteIpAddress}\\r\\n\");\n                await context.Response.WriteAsync($\"RemotePort: {context.Connection.RemotePort}\\r\\n\");\n            });\n        }\n\n        // Entry point for the application.\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                // .UseIIS() // This repo can no longer reference IIS because IISIntegration depends on it.\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n\n"
  },
  {
    "path": "samples/HttpsPolicySample/HttpsPolicySample.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFrameworks>net461;netcoreapp2.2</TargetFrameworks>\n    <TargetFrameworks Condition=\" '$(OS)' != 'Windows_NT' \">netcoreapp2.2</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Server.Kestrel\" Version=\"$(MicrosoftAspNetCoreServerKestrelPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Server.Kestrel.Https\" Version=\"$(MicrosoftAspNetCoreServerKestrelHttpsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Console\" Version=\"$(MicrosoftExtensionsLoggingConsolePackageVersion)\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.HttpsPolicy\\Microsoft.AspNetCore.HttpsPolicy.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/HttpsPolicySample/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:31894/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"HttpsSample\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      },\n      \"applicationUrl\": \"http://localhost:5000/\"\n    }\n  }\n}"
  },
  {
    "path": "samples/HttpsPolicySample/Startup.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Net;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.HttpsPolicy;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\n\nnamespace HttpsSample\n{\n    public class Startup\n    {\n        // This method gets called by the runtime. Use this method to add services to the container.\n        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940\n        public void ConfigureServices(IServiceCollection services)\n        {\n            services.AddHttpsRedirection(options =>\n            {\n                options.RedirectStatusCode = StatusCodes.Status301MovedPermanently;\n                options.HttpsPort = 5001;\n            });\n\n            services.AddHsts(options =>\n            {\n                options.MaxAge = TimeSpan.FromDays(30);\n                options.Preload = true;\n                options.IncludeSubDomains = true;\n            });\n        }\n\n        public void Configure(IApplicationBuilder app, IHostingEnvironment environment)\n        {\n            if (!environment.IsDevelopment())\n            {\n                app.UseHsts();\n            }\n            app.UseHttpsRedirection();\n\n            app.Run(async context =>\n            {\n                await context.Response.WriteAsync(\"Hello world!\");\n            });\n        }\n\n        // Entry point for the application.\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel(\n                options =>\n                {\n                    options.Listen(new IPEndPoint(IPAddress.Loopback, 5001), listenOptions =>\n                    {\n                        listenOptions.UseHttps(\"testCert.pfx\", \"testPassword\");\n                    });\n                    options.Listen(new IPEndPoint(IPAddress.Loopback, 5000), listenOptions =>\n                    {\n                    });\n                })\n                .UseContentRoot(Directory.GetCurrentDirectory()) // for the cert file\n                .ConfigureLogging(factory =>\n                {\n                    factory.SetMinimumLevel(LogLevel.Debug);\n                    factory.AddConsole();\n                })\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "samples/ResponseBufferingSample/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:49657/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNET_ENV\": \"Development\"\n      }\n    },\n    \"web\": {\n      \"commandName\": \"web\",\n      \"environmentVariables\": {\n        \"Hosting:Environment\": \"Development\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "samples/ResponseBufferingSample/ResponseBufferingSample.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.Buffering\\Microsoft.AspNetCore.Buffering.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Server.Kestrel\" Version=\"$(MicrosoftAspNetCoreServerKestrelPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/ResponseBufferingSample/Startup.cs",
    "content": "using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace ResponseBufferingSample\n{\n    public class Startup\n    {\n        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940\n        public void ConfigureServices(IServiceCollection services)\n        {\n        }\n\n        public void Configure(IApplicationBuilder app)\n        {\n            app.UseResponseBuffering();\n            app.Run(async (context) =>\n            {\n                // Write some stuff\n                context.Response.ContentType = \"text/other\";\n                await context.Response.WriteAsync(\"Hello World!\");\n\n                // ... more work ...\n\n                // Something went wrong and we want to replace the response\n                context.Response.StatusCode = 200;\n                context.Response.Headers.Clear();\n                context.Response.Body.SetLength(0);\n\n                // Try again\n                context.Response.ContentType = \"text/plain\";\n                await context.Response.WriteAsync(\"Hi Bob!\");\n            });\n        }\n\n        // Entry point for the application.\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                // .UseIIS() // This repo can no longer reference IIS because IISIntegration depends on it.\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n\n"
  },
  {
    "path": "samples/ResponseCompressionSample/CustomCompressionProvider.cs",
    "content": "﻿using System.IO;\nusing Microsoft.AspNetCore.ResponseCompression;\n\nnamespace ResponseCompressionSample\n{\n    public class CustomCompressionProvider : ICompressionProvider\n    {\n        public string EncodingName => \"custom\";\n\n        public bool SupportsFlush => true;\n\n        public Stream CreateStream(Stream outputStream)\n        {\n            // Create a custom compression stream wrapper here\n            return outputStream;\n        }\n    }\n}\n"
  },
  {
    "path": "samples/ResponseCompressionSample/LoremIpsum.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace ResponseCompressionSample\n{\n    internal static class LoremIpsum\n    {\n        internal const string Text = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales hendrerit.\" +\n            \"Ut velit mauris, egestas sed, gravida nec, ornare ut, mi. Aenean ut orci vel massa suscipit pulvinar.Nulla sollicitudin.Fusce varius, ligula non tempus aliquam, nunc turpis ullamcorper nibh, in tempus sapien eros vitae ligula.Pellentesque rhoncus nunc et augue.Integer id felis.Curabitur aliquet pellentesque diam. Integer quis metus vitae elit lobortis egestas.Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Morbi vel erat non mauris convallis vehicula.Nulla et sapien.Integer tortor tellus, aliquam faucibus, convallis id, congue eu, quam.Mauris ullamcorper felis vitae erat.Proin feugiat, augue non elementum posuere, metus purus iaculis lectus, et tristique ligula justo vitae magna.\" +\n            \"Aliquam convallis sollicitudin purus. Praesent aliquam, enim at fermentum mollis, ligula massa adipiscing nisl, ac euismod nibh nisl eu lectus. Fusce vulputate sem at sapien.Vivamus leo. Aliquam euismod libero eu enim.Nulla nec felis sed leo placerat imperdiet.Aenean suscipit nulla in justo.Suspendisse cursus rutrum augue. Nulla tincidunt tincidunt mi. Curabitur iaculis, lorem vel rhoncus faucibus, felis magna fermentum augue, et ultricies lacus lorem varius purus. Curabitur eu amet.\";\n    }\n}\n"
  },
  {
    "path": "samples/ResponseCompressionSample/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:6164/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"ResponseCompressionSample\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000/\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}"
  },
  {
    "path": "samples/ResponseCompressionSample/ResponseCompressionSample.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Content Update=\"testfile1kb.txt\" CopyToOutputDirectory=\"PreserveNewest\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.ResponseCompression\\Microsoft.AspNetCore.ResponseCompression.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Server.Kestrel\" Version=\"$(MicrosoftAspNetCoreServerKestrelPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Console\" Version=\"$(MicrosoftExtensionsLoggingConsolePackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/ResponseCompressionSample/Startup.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO.Compression;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.AspNetCore.ResponseCompression;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\n\nnamespace ResponseCompressionSample\n{\n    public class Startup\n    {\n        public void ConfigureServices(IServiceCollection services)\n        {\n            services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);\n            services.AddResponseCompression(options =>\n            {\n                options.Providers.Add<GzipCompressionProvider>();\n                options.Providers.Add<CustomCompressionProvider>();\n                // .Append(TItem) is only available on Core.\n                options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { \"image/svg+xml\" });\n\n                ////Example of using excluded and wildcard MIME types:\n                ////Compress all MIME types except various media types, but do compress SVG images.\n                //options.MimeTypes = new[] { \"*/*\", \"image/svg+xml\" };\n                //options.ExcludedMimeTypes = new[] { \"image/*\", \"audio/*\", \"video/*\" };\n            });\n        }\n\n        public void Configure(IApplicationBuilder app)\n        {\n            app.UseResponseCompression();\n\n            app.Map(\"/testfile1kb.txt\", fileApp =>\n            {\n                fileApp.Run(context =>\n                {\n                    context.Response.ContentType = \"text/plain\";\n                    return context.Response.SendFileAsync(\"testfile1kb.txt\");\n                });\n            });\n\n            app.Map(\"/trickle\", trickleApp =>\n            {\n                trickleApp.Run(async context =>\n                {\n                    context.Response.ContentType = \"text/plain\";\n                    // Disables compression on net451 because that GZipStream does not implement Flush.\n                    context.Features.Get<IHttpBufferingFeature>()?.DisableResponseBuffering();\n\n                    for (int i = 0; i < 100; i++)\n                    {\n                        await context.Response.WriteAsync(\"a\");\n                        await context.Response.Body.FlushAsync();\n                        await Task.Delay(TimeSpan.FromSeconds(1));\n                    }\n                });\n            });\n\n            app.Run(async context =>\n            {\n                context.Response.ContentType = \"text/plain\";\n                await context.Response.WriteAsync(LoremIpsum.Text);\n            });\n        }\n\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .ConfigureLogging(factory =>\n                {\n                    factory.AddConsole()\n                        .SetMinimumLevel(LogLevel.Debug);\n                })\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "samples/ResponseCompressionSample/testfile1kb.txt",
    "content": "﻿aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  },
  {
    "path": "samples/RewriteSample/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:6156/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"RewriteSample\": {\n      \"commandName\": \"Project\"\n    }\n  }\n}"
  },
  {
    "path": "samples/RewriteSample/Rewrite.txt",
    "content": "﻿# Rewrite path with additional sub directory\nRewriteCond %{HTTP_HOST}   !^www\\.example\\.com [NC,OR]\nRewriteCond %{SERVER_PORT} !^5000$\nRewriteRule ^/(.*)         http://www.example.com/$1 [L,R=302]"
  },
  {
    "path": "samples/RewriteSample/RewriteSample.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n  <PropertyGroup>\n    <TargetFrameworks>netcoreapp2.2;net461</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.Rewrite\\Microsoft.AspNetCore.Rewrite.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Server.Kestrel\" Version=\"$(MicrosoftAspNetCoreServerKestrelPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Server.Kestrel.Https\" Version=\"$(MicrosoftAspNetCoreServerKestrelHttpsPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/RewriteSample/Startup.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing System.Net;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace RewriteSample\n{\n    public class Startup\n    {\n        public Startup(IHostingEnvironment environment)\n        {\n            Environment = environment;\n        }\n\n        public IHostingEnvironment Environment { get; private set; }\n\n        public void ConfigureServices(IServiceCollection services)\n        {\n            services.Configure<RewriteOptions>(options =>\n            {\n                options.AddRedirect(\"(.*)/$\", \"$1\")\n                       .AddRewrite(@\"app/(\\d+)\", \"app?id=$1\", skipRemainingRules: false)\n                       .AddRedirectToHttps(302, 5001)\n                       .AddIISUrlRewrite(Environment.ContentRootFileProvider, \"UrlRewrite.xml\")\n                       .AddApacheModRewrite(Environment.ContentRootFileProvider, \"Rewrite.txt\");\n            });\n        }\n\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\n        {\n            app.UseRewriter();\n\n            app.Run(context =>\n            {\n                return context.Response.WriteAsync($\"Rewritten Url: {context.Request.Path + context.Request.QueryString}\");\n            });\n        }\n\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel(options =>\n                {\n                    options.Listen(IPAddress.Loopback, 5000);\n                    options.Listen(IPAddress.Loopback, 5001, listenOptions =>\n                    {\n                        // Configure SSL\n                        listenOptions.UseHttps(\"testCert.pfx\", \"testPassword\");\n                    });\n                })\n                .UseStartup<Startup>()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "samples/RewriteSample/UrlRewrite.xml",
    "content": "﻿<rewrite>\n  <rules>\n    <rule name=\"Rewrite 20 to 10\" stopProcessing=\"true\">\n      <match url=\"^app$\" />\n      <conditions>\n        <add input=\"{QUERY_STRING}\" pattern=\"id=20\" />\n      </conditions>\n      <action type=\"Rewrite\" url=\"app?id=10\" appendQueryString=\"false\"/>\n    </rule>\n  </rules>\n</rewrite>"
  },
  {
    "path": "src/Directory.Build.props",
    "content": "<Project>\n  <Import Project=\"..\\Directory.Build.props\" />\n\n  <ItemGroup>\n    <PackageReference Include=\"Internal.AspNetCore.Sdk\" PrivateAssets=\"All\" Version=\"$(InternalAspNetCoreSdkPackageVersion)\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Buffering/BufferingWriteStream.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Microsoft.AspNetCore.Buffering\n{\n    internal class BufferingWriteStream : Stream\n    {\n        private readonly Stream _innerStream;\n        private readonly MemoryStream _buffer = new MemoryStream();\n        private bool _isBuffering = true;\n\n        public BufferingWriteStream(Stream innerStream)\n        {\n            _innerStream = innerStream;\n        }\n\n        public override bool CanRead\n        {\n            get { return false; }\n        }\n\n        public override bool CanSeek\n        {\n            get { return _isBuffering; }\n        }\n\n        public override bool CanWrite\n        {\n            get { return _innerStream.CanWrite; }\n        }\n\n        public override long Length\n        {\n            get\n            {\n                if (_isBuffering)\n                {\n                    return _buffer.Length;\n                }\n                // May throw\n                return _innerStream.Length;\n            }\n        }\n\n        // Clear/Reset the buffer by setting Position, Seek, or SetLength to 0. Random access is not supported.\n        public override long Position\n        {\n            get\n            {\n                if (_isBuffering)\n                {\n                    return _buffer.Position;\n                }\n                // May throw\n                return _innerStream.Position;\n            }\n            set\n            {\n                if (_isBuffering)\n                {\n                    if (value != 0)\n                    {\n                        throw new ArgumentOutOfRangeException(nameof(value), value, nameof(Position) + \" can only be set to 0.\");\n                    }\n                    _buffer.Position = value;\n                    _buffer.SetLength(value);\n                }\n                else\n                {\n                    // May throw\n                    _innerStream.Position = value;\n                }\n            }\n        }\n\n        // Clear/Reset the buffer by setting Position, Seek, or SetLength to 0. Random access is not supported.\n        public override void SetLength(long value)\n        {\n            if (_isBuffering)\n            {\n                if (value != 0)\n                {\n                    throw new ArgumentOutOfRangeException(nameof(value), value, nameof(Length) + \" can only be set to 0.\");\n                }\n                _buffer.Position = value;\n                _buffer.SetLength(value);\n            }\n            else\n            {\n                // May throw\n                _innerStream.SetLength(value);\n            }\n        }\n\n        // Clear/Reset the buffer by setting Position, Seek, or SetLength to 0. Random access is not supported.\n        public override long Seek(long offset, SeekOrigin origin)\n        {\n            if (_isBuffering)\n            {\n                if (origin != SeekOrigin.Begin)\n                {\n                    throw new ArgumentException(nameof(origin), nameof(Seek) + \" can only be set to \" + nameof(SeekOrigin.Begin) + \".\");\n                }\n                if (offset != 0)\n                {\n                    throw new ArgumentOutOfRangeException(nameof(offset), offset, nameof(Seek) + \" can only be set to 0.\");\n                }\n                _buffer.SetLength(offset);\n                return _buffer.Seek(offset, origin);\n            }\n            // Try the inner stream instead, but this will usually fail.\n            return _innerStream.Seek(offset, origin);\n        }\n\n        internal void DisableBuffering()\n        {\n            _isBuffering = false;\n            if (_buffer.Length > 0)\n            {\n                Flush();\n            }\n        }\n\n        internal Task DisableBufferingAsync(CancellationToken cancellationToken)\n        {\n            _isBuffering = false;\n            if (_buffer.Length > 0)\n            {\n                return FlushAsync(cancellationToken);\n            }\n            return Task.CompletedTask;\n        }\n\n        public override void Write(byte[] buffer, int offset, int count)\n        {\n            if (_isBuffering)\n            {\n                _buffer.Write(buffer, offset, count);\n            }\n            else\n            {\n                _innerStream.Write(buffer, offset, count);\n            }\n        }\n\n        public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)\n        {\n            if (_isBuffering)\n            {\n                return _buffer.WriteAsync(buffer, offset, count, cancellationToken);\n            }\n            else\n            {\n                return _innerStream.WriteAsync(buffer, offset, count, cancellationToken);\n            }\n        }\n\n        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)\n        {\n            if (_isBuffering)\n            {\n                return _buffer.BeginWrite(buffer, offset, count, callback, state);\n            }\n            else\n            {\n                return _innerStream.BeginWrite(buffer, offset, count, callback, state);\n            }\n        }\n\n        public override void EndWrite(IAsyncResult asyncResult)\n        {\n            if (_isBuffering)\n            {\n                _buffer.EndWrite(asyncResult);\n            }\n            else\n            {\n                _innerStream.EndWrite(asyncResult);\n            }\n        }\n\n        public override void Flush()\n        {\n            _isBuffering = false;\n            if (_buffer.Length > 0)\n            {\n                _buffer.Seek(0, SeekOrigin.Begin);\n                _buffer.CopyTo(_innerStream);\n                _buffer.Seek(0, SeekOrigin.Begin);\n                _buffer.SetLength(0);\n            }\n            _innerStream.Flush();\n        }\n\n        public override async Task FlushAsync(CancellationToken cancellationToken)\n        {\n            _isBuffering = false;\n            if (_buffer.Length > 0)\n            {\n                _buffer.Seek(0, SeekOrigin.Begin);\n                await _buffer.CopyToAsync(_innerStream, 1024 * 16, cancellationToken);\n                _buffer.Seek(0, SeekOrigin.Begin);\n                _buffer.SetLength(0);\n            }\n            await _innerStream.FlushAsync(cancellationToken);\n        }\n\n        public override int Read(byte[] buffer, int offset, int count)\n        {\n            throw new NotSupportedException(\"This Stream only supports Write operations.\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Buffering/HttpBufferingFeature.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http.Features;\n\nnamespace Microsoft.AspNetCore.Buffering\n{\n    internal class HttpBufferingFeature : IHttpBufferingFeature\n    {\n        private readonly BufferingWriteStream _buffer;\n        private readonly IHttpBufferingFeature _innerFeature;\n\n        internal HttpBufferingFeature(BufferingWriteStream buffer, IHttpBufferingFeature innerFeature)\n        {\n            _buffer = buffer;\n            _innerFeature = innerFeature;\n        }\n\n        public void DisableRequestBuffering()\n        {\n            _innerFeature?.DisableRequestBuffering();\n        }\n\n        public void DisableResponseBuffering()\n        {\n            _buffer.DisableBuffering();\n            _innerFeature?.DisableResponseBuffering();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Buffering/Microsoft.AspNetCore.Buffering.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <VersionPrefix Condition=\"'$(ExperimentalVersionPrefix)' != ''\">$(ExperimentalVersionPrefix)</VersionPrefix>\n    <VersionSuffix Condition=\"'$(ExperimentalVersionSuffix)' != ''\">$(ExperimentalVersionSuffix)</VersionSuffix>\n    <VerifyVersion Condition=\"'$(ExperimentalVersionPrefix)' != ''\">false</VerifyVersion>\n    <PackageVersion Condition=\"'$(ExperimentalPackageVersion)' != ''\">$(ExperimentalPackageVersion)</PackageVersion>\n    <Description>ASP.NET Core middleware for buffering response bodies.</Description>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <NoWarn>$(NoWarn);CS1591</NoWarn>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <PackageTags>aspnetcore;buffer;buffering</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Http.Abstractions\" Version=\"$(MicrosoftAspNetCoreHttpAbstractionsPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Buffering/ResponseBufferingMiddleware.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Features;\n\nnamespace Microsoft.AspNetCore.Buffering\n{\n    public class ResponseBufferingMiddleware\n    {\n        private readonly RequestDelegate _next;\n\n        public ResponseBufferingMiddleware(RequestDelegate next)\n        {\n            _next = next;\n        }\n\n        public async Task Invoke(HttpContext httpContext)\n        {\n            var originalResponseBody = httpContext.Response.Body;\n\n            // no-op if buffering is already available.\n            if (originalResponseBody.CanSeek)\n            {\n                await _next(httpContext);\n                return;\n            }\n\n            var originalBufferingFeature = httpContext.Features.Get<IHttpBufferingFeature>();\n            var originalSendFileFeature = httpContext.Features.Get<IHttpSendFileFeature>();\n            try\n            {\n                // Shim the response stream\n                var bufferStream = new BufferingWriteStream(originalResponseBody);\n                httpContext.Response.Body = bufferStream;\n                httpContext.Features.Set<IHttpBufferingFeature>(new HttpBufferingFeature(bufferStream, originalBufferingFeature));\n                if (originalSendFileFeature != null)\n                {\n                    httpContext.Features.Set<IHttpSendFileFeature>(new SendFileFeatureWrapper(originalSendFileFeature, bufferStream));\n                }\n\n                await _next(httpContext);\n\n                // If we're still buffered, set the content-length header and flush the buffer.\n                // Only if the content-length header is not already set, and some content was buffered.\n                if (!httpContext.Response.HasStarted && bufferStream.CanSeek && bufferStream.Length > 0)\n                {\n                    if (!httpContext.Response.ContentLength.HasValue)\n                    {\n                        httpContext.Response.ContentLength = bufferStream.Length;\n                    }\n                    await bufferStream.FlushAsync();\n                }\n            }\n            finally\n            {\n                // undo everything\n                httpContext.Features.Set(originalBufferingFeature);\n                httpContext.Features.Set(originalSendFileFeature);\n                httpContext.Response.Body = originalResponseBody;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Buffering/ResponseBufferingMiddlewareExtensions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Buffering;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    public static class ResponseBufferingMiddlewareExtensions\n    {\n        /// <summary>\n        /// Enables full buffering of response bodies. This can be disabled on a per request basis using IHttpBufferingFeature.\n        /// </summary>\n        /// <param name=\"builder\"></param>\n        /// <returns></returns>\n        public static IApplicationBuilder UseResponseBuffering(this IApplicationBuilder builder)\n        {\n            return builder.UseMiddleware<ResponseBufferingMiddleware>();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Buffering/SendFileFeatureWrapper.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http.Features;\n\nnamespace Microsoft.AspNetCore.Buffering\n{\n    internal class SendFileFeatureWrapper : IHttpSendFileFeature\n    {\n        private readonly IHttpSendFileFeature _originalSendFileFeature;\n        private readonly BufferingWriteStream _bufferStream;\n\n        public SendFileFeatureWrapper(IHttpSendFileFeature originalSendFileFeature, BufferingWriteStream bufferStream)\n        {\n            _originalSendFileFeature = originalSendFileFeature;\n            _bufferStream = bufferStream;\n        }\n\n        // Flush and disable the buffer if anyone tries to call the SendFile feature.\n        public async Task SendFileAsync(string path, long offset, long? length, CancellationToken cancellation)\n        {\n            await _bufferStream.DisableBufferingAsync(cancellation);\n            await _originalSendFileFeature.SendFileAsync(path, offset, length, cancellation);\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.HostFiltering/HostFilteringBuilderExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.HostFiltering;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the HostFiltering middleware.\n    /// </summary>\n    public static class HostFilteringBuilderExtensions\n    {\n        /// <summary>\n        /// Adds middleware for filtering requests by allowed host headers. Invalid requests will be rejected with a\n        /// 400 status code.\n        /// </summary>\n        /// <param name=\"app\">The <see cref=\"IApplicationBuilder\"/> instance this method extends.</param>\n        /// <returns>The original <see cref=\"IApplicationBuilder\"/>.</returns>\n        public static IApplicationBuilder UseHostFiltering(this IApplicationBuilder app)\n        {\n            if (app == null)\n            {\n                throw new ArgumentNullException(nameof(app));\n            }\n\n            app.UseMiddleware<HostFilteringMiddleware>();\n\n            return app;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HostFiltering/HostFilteringMiddleware.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\nusing Microsoft.Extensions.Primitives;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.HostFiltering\n{\n    /// <summary>\n    /// A middleware used to filter requests by their Host header.\n    /// </summary>\n    public class HostFilteringMiddleware\n    {\n        // Matches Http.Sys.\n        private static readonly byte[] DefaultResponse = Encoding.ASCII.GetBytes(\n            \"<!DOCTYPE HTML PUBLIC \\\"-//W3C//DTD HTML 4.01//EN\\\"\\\"http://www.w3.org/TR/html4/strict.dtd\\\">\\r\\n\"\n            + \"<HTML><HEAD><TITLE>Bad Request</TITLE>\\r\\n\"\n            + \"<META HTTP-EQUIV=\\\"Content-Type\\\" Content=\\\"text/html; charset=us-ascii\\\"></ HEAD >\\r\\n\"\n            + \"<BODY><h2>Bad Request - Invalid Hostname</h2>\\r\\n\"\n            + \"<hr><p>HTTP Error 400. The request hostname is invalid.</p>\\r\\n\"\n            + \"</BODY></HTML>\");\n\n        private readonly RequestDelegate _next;\n        private readonly ILogger<HostFilteringMiddleware> _logger;\n        private readonly IOptionsMonitor<HostFilteringOptions> _optionsMonitor;\n        private HostFilteringOptions _options;\n        private IList<StringSegment> _allowedHosts;\n        private bool? _allowAnyNonEmptyHost;\n\n        /// <summary>\n        /// A middleware used to filter requests by their Host header.\n        /// </summary>\n        /// <param name=\"next\"></param>\n        /// <param name=\"logger\"></param>\n        /// <param name=\"optionsMonitor\"></param>\n        public HostFilteringMiddleware(RequestDelegate next, ILogger<HostFilteringMiddleware> logger, \n            IOptionsMonitor<HostFilteringOptions> optionsMonitor)\n        {\n            _next = next ?? throw new ArgumentNullException(nameof(next));\n            _logger = logger ?? throw new ArgumentNullException(nameof(logger));\n            _optionsMonitor = optionsMonitor ?? throw new ArgumentNullException(nameof(optionsMonitor));\n            _options = _optionsMonitor.CurrentValue;\n            _optionsMonitor.OnChange(options =>\n            {\n                // Clear the cached settings so the next EnsureConfigured will re-evaluate.\n                _options = options;\n                _allowedHosts = new List<StringSegment>();\n                _allowAnyNonEmptyHost = null;\n            });\n        }\n\n        /// <summary>\n        /// Processes requests\n        /// </summary>\n        /// <param name=\"context\"></param>\n        /// <returns></returns>\n        public Task Invoke(HttpContext context)\n        {\n            var allowedHosts = EnsureConfigured();\n\n            if (!CheckHost(context, allowedHosts))\n            {\n                context.Response.StatusCode = 400;\n                if (_options.IncludeFailureMessage)\n                {\n                    context.Response.ContentLength = DefaultResponse.Length;\n                    context.Response.ContentType = \"text/html\";\n                    return context.Response.Body.WriteAsync(DefaultResponse, 0, DefaultResponse.Length);\n                }\n                return Task.CompletedTask;\n            }\n\n            return _next(context);\n        }\n\n        private IList<StringSegment> EnsureConfigured()\n        {\n            if (_allowAnyNonEmptyHost == true || _allowedHosts?.Count > 0)\n            {\n                return _allowedHosts;\n            }\n\n            var allowedHosts = new List<StringSegment>();\n            if (_options.AllowedHosts?.Count > 0 && !TryProcessHosts(_options.AllowedHosts, allowedHosts))\n            {\n                _logger.LogDebug(\"Wildcard detected, all requests with hosts will be allowed.\");\n                _allowedHosts = allowedHosts;\n                _allowAnyNonEmptyHost = true;\n                return _allowedHosts;\n            }\n\n            if (allowedHosts.Count == 0)\n            {\n                throw new InvalidOperationException(\"No allowed hosts were configured.\");\n            }\n\n            if (_logger.IsEnabled(LogLevel.Debug))\n            {\n                _logger.LogDebug(\"Allowed hosts: {Hosts}\", string.Join(\"; \", allowedHosts));\n            }\n\n            _allowedHosts = allowedHosts;\n            return _allowedHosts;\n        }\n\n        // returns false if any wildcards were found\n        private bool TryProcessHosts(IEnumerable<string> incoming, IList<StringSegment> results)\n        {\n            foreach (var entry in incoming)\n            {\n                // Punycode. Http.Sys requires you to register Unicode hosts, but the headers contain punycode.\n                var host = new HostString(entry).ToUriComponent();\n\n                if (IsTopLevelWildcard(host))\n                {\n                    // Disable filtering\n                    return false;\n                }\n\n                if (!results.Contains(host, StringSegmentComparer.OrdinalIgnoreCase))\n                {\n                    results.Add(host);\n                }\n            }\n\n            return true;\n        }\n\n        private bool IsTopLevelWildcard(string host)\n        {\n            return (string.Equals(\"*\", host, StringComparison.Ordinal) // HttpSys wildcard\n                           || string.Equals(\"[::]\", host, StringComparison.Ordinal) // Kestrel wildcard, IPv6 Any\n                           || string.Equals(\"0.0.0.0\", host, StringComparison.Ordinal)); // IPv4 Any\n        }\n\n        // This does not duplicate format validations that are expected to be performed by the host.\n        private bool CheckHost(HttpContext context, IList<StringSegment> allowedHosts)\n        {\n            var host = new StringSegment(context.Request.Headers[HeaderNames.Host].ToString()).Trim();\n\n            if (StringSegment.IsNullOrEmpty(host))\n            {\n                // Http/1.0 does not require the host header.\n                // Http/1.1 requires the header but the value may be empty.\n                if (!_options.AllowEmptyHosts)\n                {\n                    _logger.LogInformation(\"{Protocol} request rejected due to missing or empty host header.\", context.Request.Protocol);\n                    return false;\n                }\n                _logger.LogDebug(\"{Protocol} request allowed with missing or empty host header.\", context.Request.Protocol);\n                return true;\n            }\n\n            if (_allowAnyNonEmptyHost == true)\n            {\n                _logger.LogTrace(\"All hosts are allowed.\");\n                return true;\n            }\n\n            if (HostString.MatchesAny(host, allowedHosts))\n            {\n                _logger.LogTrace(\"The host '{Host}' matches an allowed host.\", host);\n                return true;\n            }\n            \n            _logger.LogInformation(\"The host '{Host}' does not match an allowed host.\", host);\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HostFiltering/HostFilteringOptions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.HostFiltering\n{\n    /// <summary>\n    /// Options for the HostFiltering middleware\n    /// </summary>\n    public class HostFilteringOptions\n    {\n        /// <summary>\n        /// The hosts headers that are allowed to access this site. At least one value is required.\n        /// </summary>\n        /// <remarks>\n        /// <list type=\"bullet\">\n        /// <item><description>Port numbers must be excluded.</description></item>\n        /// <item><description>A top level wildcard \"*\" allows all non-empty hosts.</description></item>\n        /// <item><description>Subdomain wildcards are permitted. E.g. \"*.example.com\" matches subdomains like foo.example.com,\n        ///    but not the parent domain example.com.</description></item>\n        /// <item><description>Unicode host names are allowed but will be converted to punycode for matching.</description></item>\n        /// <item><description>IPv6 addresses must include their bounding brackets and be in their normalized form.</description></item>\n        /// </list>\n        /// </remarks>\n        public IList<string> AllowedHosts { get; set; } = new List<string>();\n\n        /// <summary>\n        /// Indicates if requests without hosts are allowed. The default is true.\n        /// </summary>\n        /// <remarks>\n        /// HTTP/1.0 does not require a host header.\n        /// Http/1.1 requires a host header, but says the value may be empty.\n        /// </remarks>\n        public bool AllowEmptyHosts { get; set; } = true;\n\n        // Note if this were disabled then things like the status code middleware may try to re-execute\n        // the request. This is a low level protocol violation, pretty error pages should not be required.\n        /// <summary>\n        /// Indicates if the 400 response should include a default message or be empty. This is enabled by default.\n        /// </summary>\n        public bool IncludeFailureMessage { get; set; } = true;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HostFiltering/HostFilteringServicesExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.HostFiltering;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the host filtering middleware.\n    /// </summary>\n    public static class HostFilteringServicesExtensions\n    {\n        /// <summary>\n        /// Adds services and options for the host filtering middleware.\n        /// </summary>\n        /// <param name=\"services\">The <see cref=\"IServiceCollection\"/> for adding services.</param>\n        /// <param name=\"configureOptions\">A delegate to configure the <see cref=\"HostFilteringOptions\"/>.</param>\n        /// <returns></returns>\n        public static IServiceCollection AddHostFiltering(this IServiceCollection services, Action<HostFilteringOptions> configureOptions)\n        {\n            if (services == null)\n            {\n                throw new ArgumentNullException(nameof(services));\n            }\n            if (configureOptions == null)\n            {\n                throw new ArgumentNullException(nameof(configureOptions));\n            }\n\n            services.Configure(configureOptions);\n            return services;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HostFiltering/Microsoft.AspNetCore.HostFiltering.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <Description>\n      ASP.NET Core middleware for filtering out requests with unknown HTTP host headers.\n    </Description>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <PackageTags>aspnetcore</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Http\" Version=\"$(MicrosoftAspNetCoreHttpAbstractionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Http.Extensions\" Version=\"$(MicrosoftAspNetCoreHttpExtensionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Options\" Version=\"$(MicrosoftExtensionsOptionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Hosting.Abstractions\" Version=\"$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)\" /> \n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HostFiltering/baseline.netcore.json",
    "content": "{\n  \"AssemblyIdentity\": \"Microsoft.AspNetCore.HostFiltering, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60\",\n  \"Types\": [\n    {\n      \"Name\": \"Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"logger\",\n              \"Type\": \"Microsoft.Extensions.Logging.ILogger<Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware>\"\n            },\n            {\n              \"Name\": \"optionsMonitor\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptionsMonitor<Microsoft.AspNetCore.HostFiltering.HostFilteringOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HostFiltering.HostFilteringOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_AllowedHosts\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IList<System.String>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_AllowedHosts\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Collections.Generic.IList<System.String>\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_AllowEmptyHosts\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_AllowEmptyHosts\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_IncludeFailureMessage\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_IncludeFailureMessage\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HostFilteringBuilderExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseHostFiltering\",\n          \"Parameters\": [\n            {\n              \"Name\": \"app\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HostFilteringServicesExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddHostFiltering\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\"\n            },\n            {\n              \"Name\": \"configureOptions\",\n              \"Type\": \"System.Action<Microsoft.AspNetCore.HostFiltering.HostFilteringOptions>\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    }\n  ]\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/ForwardedHeaders.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.AspNetCore.HttpOverrides\n{\n    [Flags]\n    public enum ForwardedHeaders\n    {\n        None = 0,\n        XForwardedFor = 1 << 0,\n        XForwardedHost = 1 << 1,\n        XForwardedProto = 1 << 2,\n        All = XForwardedFor | XForwardedHost | XForwardedProto\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/ForwardedHeadersDefaults.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.HttpOverrides\n{\n    /// <summary>\n    /// Default values related to <see cref=\"ForwardedHeadersMiddleware\"/> middleware\n    /// </summary>\n    /// <seealso cref=\"Microsoft.AspNetCore.Builder.ForwardedHeadersOptions\"/>\n    public static class ForwardedHeadersDefaults\n    {\n        /// <summary>\n        /// X-Forwarded-For\n        /// </summary>\n        public static string XForwardedForHeaderName { get; } = \"X-Forwarded-For\";\n\n        /// <summary>\n        /// X-Forwarded-Host\n        /// </summary>\n        public static string XForwardedHostHeaderName { get; } = \"X-Forwarded-Host\";\n\n        /// <summary>\n        /// X-Forwarded-Proto\n        /// </summary>\n        public static string XForwardedProtoHeaderName { get; } = \"X-Forwarded-Proto\";\n\n        /// <summary>\n        /// X-Original-For\n        /// </summary>\n        public static string XOriginalForHeaderName { get; } = \"X-Original-For\";\n\n        /// <summary>\n        /// X-Original-Host\n        /// </summary>\n        public static string XOriginalHostHeaderName { get; } = \"X-Original-Host\";\n\n        /// <summary>\n        /// X-Original-Proto\n        /// </summary>\n        public static string XOriginalProtoHeaderName { get; } = \"X-Original-Proto\";\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/ForwardedHeadersExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.HttpOverrides;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    public static class ForwardedHeadersExtensions\n    {\n        /// <summary>\n        /// Forwards proxied headers onto current request\n        /// </summary>\n        /// <param name=\"builder\"></param>\n        /// <returns></returns>\n        public static IApplicationBuilder UseForwardedHeaders(this IApplicationBuilder builder)\n        {\n            if (builder == null)\n            {\n                throw new ArgumentNullException(nameof(builder));\n            }\n\n            return builder.UseMiddleware<ForwardedHeadersMiddleware>();\n        }\n\n        /// <summary>\n        /// Forwards proxied headers onto current request\n        /// </summary>\n        /// <param name=\"builder\"></param>\n        /// <param name=\"options\">Enables the different forwarding options.</param>\n        /// <returns></returns>\n        public static IApplicationBuilder UseForwardedHeaders(this IApplicationBuilder builder, ForwardedHeadersOptions options)\n        {\n            if (builder == null)\n            {\n                throw new ArgumentNullException(nameof(builder));\n            }\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            return builder.UseMiddleware<ForwardedHeadersMiddleware>(Options.Create(options));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/ForwardedHeadersMiddleware.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net;\nusing System.Runtime.CompilerServices;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.HttpOverrides.Internal;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\nusing Microsoft.Extensions.Primitives;\n\nnamespace Microsoft.AspNetCore.HttpOverrides\n{\n    public class ForwardedHeadersMiddleware\n    {\n        private static readonly bool[] HostCharValidity = new bool[127];\n        private static readonly bool[] SchemeCharValidity = new bool[123];\n\n        private readonly ForwardedHeadersOptions _options;\n        private readonly RequestDelegate _next;\n        private readonly ILogger _logger;\n        private bool _allowAllHosts;\n        private IList<StringSegment> _allowedHosts;\n\n        static ForwardedHeadersMiddleware()\n        {\n            // RFC 3986 scheme = ALPHA * (ALPHA / DIGIT / \"+\" / \"-\" / \".\")\n            SchemeCharValidity['+'] = true;\n            SchemeCharValidity['-'] = true;\n            SchemeCharValidity['.'] = true;\n\n            // Host Matches Http.Sys and Kestrel\n            // Host Matches RFC 3986 except \"*\" / \"+\" / \",\" / \";\" / \"=\" and \"%\" HEXDIG HEXDIG which are not allowed by Http.Sys\n            HostCharValidity['!'] = true;\n            HostCharValidity['$'] = true;\n            HostCharValidity['&'] = true;\n            HostCharValidity['\\''] = true;\n            HostCharValidity['('] = true;\n            HostCharValidity[')'] = true;\n            HostCharValidity['-'] = true;\n            HostCharValidity['.'] = true;\n            HostCharValidity['_'] = true;\n            HostCharValidity['~'] = true;\n            for (var ch = '0'; ch <= '9'; ch++)\n            {\n                SchemeCharValidity[ch] = true;\n                HostCharValidity[ch] = true;\n            }\n            for (var ch = 'A'; ch <= 'Z'; ch++)\n            {\n                SchemeCharValidity[ch] = true;\n                HostCharValidity[ch] = true;\n            }\n            for (var ch = 'a'; ch <= 'z'; ch++)\n            {\n                SchemeCharValidity[ch] = true;\n                HostCharValidity[ch] = true;\n            }\n        }\n\n        public ForwardedHeadersMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions<ForwardedHeadersOptions> options)\n        {\n            if (next == null)\n            {\n                throw new ArgumentNullException(nameof(next));\n            }\n            if (loggerFactory == null)\n            {\n                throw new ArgumentNullException(nameof(loggerFactory));\n            }\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            // Make sure required options is not null or whitespace\n            EnsureOptionNotNullorWhitespace(options.Value.ForwardedForHeaderName, nameof(options.Value.ForwardedForHeaderName));\n            EnsureOptionNotNullorWhitespace(options.Value.ForwardedHostHeaderName, nameof(options.Value.ForwardedHostHeaderName));\n            EnsureOptionNotNullorWhitespace(options.Value.ForwardedProtoHeaderName, nameof(options.Value.ForwardedProtoHeaderName));\n            EnsureOptionNotNullorWhitespace(options.Value.OriginalForHeaderName, nameof(options.Value.OriginalForHeaderName));\n            EnsureOptionNotNullorWhitespace(options.Value.OriginalHostHeaderName, nameof(options.Value.OriginalHostHeaderName));\n            EnsureOptionNotNullorWhitespace(options.Value.OriginalProtoHeaderName, nameof(options.Value.OriginalProtoHeaderName));\n\n            _options = options.Value;\n            _logger = loggerFactory.CreateLogger<ForwardedHeadersMiddleware>();\n            _next = next;\n\n            PreProcessHosts();\n        }\n\n        private static void EnsureOptionNotNullorWhitespace(string value, string propertyName)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                throw new ArgumentException($\"options.{propertyName} is required\", \"options\");\n            }\n        }\n\n        private void PreProcessHosts()\n        {\n            if (_options.AllowedHosts == null || _options.AllowedHosts.Count == 0)\n            {\n                _allowAllHosts = true;\n                return;\n            }\n\n            var allowedHosts = new List<StringSegment>();\n            foreach (var entry in _options.AllowedHosts)\n            {\n                // Punycode. Http.Sys requires you to register Unicode hosts, but the headers contain punycode.\n                var host = new HostString(entry).ToUriComponent();\n\n                if (IsTopLevelWildcard(host))\n                {\n                    // Disable filtering\n                    _allowAllHosts = true;\n                    return;\n                }\n\n                if (!allowedHosts.Contains(host, StringSegmentComparer.OrdinalIgnoreCase))\n                {\n                    allowedHosts.Add(host);\n                }\n            }\n\n            _allowedHosts = allowedHosts;\n        }\n\n        private bool IsTopLevelWildcard(string host)\n        {\n            return (string.Equals(\"*\", host, StringComparison.Ordinal) // HttpSys wildcard\n                           || string.Equals(\"[::]\", host, StringComparison.Ordinal) // Kestrel wildcard, IPv6 Any\n                           || string.Equals(\"0.0.0.0\", host, StringComparison.Ordinal)); // IPv4 Any\n        }\n\n        public Task Invoke(HttpContext context)\n        {\n            ApplyForwarders(context);\n            return _next(context);\n        }\n\n        public void ApplyForwarders(HttpContext context)\n        {\n            // Gather expected headers.\n            string[] forwardedFor = null, forwardedProto = null, forwardedHost = null;\n            bool checkFor = false, checkProto = false, checkHost = false;\n            int entryCount = 0;\n\n            if ((_options.ForwardedHeaders & ForwardedHeaders.XForwardedFor) == ForwardedHeaders.XForwardedFor)\n            {\n                checkFor = true;\n                forwardedFor = context.Request.Headers.GetCommaSeparatedValues(_options.ForwardedForHeaderName);\n                entryCount = Math.Max(forwardedFor.Length, entryCount);\n            }\n\n            if ((_options.ForwardedHeaders & ForwardedHeaders.XForwardedProto) == ForwardedHeaders.XForwardedProto)\n            {\n                checkProto = true;\n                forwardedProto = context.Request.Headers.GetCommaSeparatedValues(_options.ForwardedProtoHeaderName);\n                if (_options.RequireHeaderSymmetry && checkFor && forwardedFor.Length != forwardedProto.Length)\n                {\n                    _logger.LogWarning(1, \"Parameter count mismatch between X-Forwarded-For and X-Forwarded-Proto.\");\n                    return;\n                }\n                entryCount = Math.Max(forwardedProto.Length, entryCount);\n            }\n\n            if ((_options.ForwardedHeaders & ForwardedHeaders.XForwardedHost) == ForwardedHeaders.XForwardedHost)\n            {\n                checkHost = true;\n                forwardedHost = context.Request.Headers.GetCommaSeparatedValues(_options.ForwardedHostHeaderName);\n                if (_options.RequireHeaderSymmetry\n                    && ((checkFor && forwardedFor.Length != forwardedHost.Length)\n                        || (checkProto && forwardedProto.Length != forwardedHost.Length)))\n                {\n                    _logger.LogWarning(1, \"Parameter count mismatch between X-Forwarded-Host and X-Forwarded-For or X-Forwarded-Proto.\");\n                    return;\n                }\n                entryCount =  Math.Max(forwardedHost.Length, entryCount);\n            }\n\n            // Apply ForwardLimit, if any\n            if (_options.ForwardLimit.HasValue && entryCount > _options.ForwardLimit)\n            {\n                entryCount = _options.ForwardLimit.Value;\n            }\n\n            // Group the data together.\n            var sets = new SetOfForwarders[entryCount];\n            for (int i = 0; i < sets.Length; i++)\n            {\n                // They get processed in reverse order, right to left.\n                var set = new SetOfForwarders();\n                if (checkFor && i < forwardedFor.Length)\n                {\n                    set.IpAndPortText = forwardedFor[forwardedFor.Length - i - 1];\n                }\n                if (checkProto && i < forwardedProto.Length)\n                {\n                    set.Scheme = forwardedProto[forwardedProto.Length - i - 1];\n                }\n                if (checkHost && i < forwardedHost.Length)\n                {\n                    set.Host = forwardedHost[forwardedHost.Length - i - 1];\n                }\n                sets[i] = set;\n            }\n\n            // Gather initial values\n            var connection = context.Connection;\n            var request = context.Request;\n            var currentValues = new SetOfForwarders()\n            {\n                RemoteIpAndPort = connection.RemoteIpAddress != null ? new IPEndPoint(connection.RemoteIpAddress, connection.RemotePort) : null,\n                // Host and Scheme initial values are never inspected, no need to set them here.\n            };\n\n            var checkKnownIps = _options.KnownNetworks.Count > 0 || _options.KnownProxies.Count > 0;\n            bool applyChanges = false;\n            int entriesConsumed = 0;\n\n            for ( ; entriesConsumed < sets.Length; entriesConsumed++)\n            {\n                var set = sets[entriesConsumed];\n                if (checkFor)\n                {\n                    // For the first instance, allow remoteIp to be null for servers that don't support it natively.\n                    if (currentValues.RemoteIpAndPort != null && checkKnownIps && !CheckKnownAddress(currentValues.RemoteIpAndPort.Address))\n                    {\n                        // Stop at the first unknown remote IP, but still apply changes processed so far.\n                        _logger.LogDebug(1, \"Unknown proxy: {RemoteIpAndPort}\", currentValues.RemoteIpAndPort);\n                        break;\n                    }\n\n                    IPEndPoint parsedEndPoint;\n                    if (IPEndPointParser.TryParse(set.IpAndPortText, out parsedEndPoint))\n                    {\n                        applyChanges = true;\n                        set.RemoteIpAndPort = parsedEndPoint;\n                        currentValues.IpAndPortText = set.IpAndPortText;\n                        currentValues.RemoteIpAndPort = set.RemoteIpAndPort;\n                    }\n                    else if (!string.IsNullOrEmpty(set.IpAndPortText))\n                    {\n                        // Stop at the first unparsable IP, but still apply changes processed so far.\n                        _logger.LogDebug(1, \"Unparsable IP: {IpAndPortText}\", set.IpAndPortText);\n                        break;\n                    }\n                    else if (_options.RequireHeaderSymmetry)\n                    {\n                        _logger.LogWarning(2, \"Missing forwarded IPAddress.\");\n                        return;\n                    }\n                }\n\n                if (checkProto)\n                {\n                    if (!string.IsNullOrEmpty(set.Scheme) && TryValidateScheme(set.Scheme))\n                    {\n                        applyChanges = true;\n                        currentValues.Scheme = set.Scheme;\n                    }\n                    else if (_options.RequireHeaderSymmetry)\n                    {\n                        _logger.LogWarning(3, $\"Forwarded scheme is not present, this is required by {nameof(_options.RequireHeaderSymmetry)}\");\n                        return;\n                    }\n                }\n\n                if (checkHost)\n                {\n                    if (!string.IsNullOrEmpty(set.Host) && TryValidateHost(set.Host)\n                        && (_allowAllHosts || HostString.MatchesAny(set.Host, _allowedHosts)))\n                    {\n                        applyChanges = true;\n                        currentValues.Host = set.Host;\n                    }\n                    else if (_options.RequireHeaderSymmetry)\n                    {\n                        _logger.LogWarning(4, $\"Incorrect number of x-forwarded-host header values, see {nameof(_options.RequireHeaderSymmetry)}.\");\n                        return;\n                    }\n                }\n            }\n\n            if (applyChanges)\n            {\n                if (checkFor && currentValues.RemoteIpAndPort != null)\n                {\n                    if (connection.RemoteIpAddress != null)\n                    {\n                        // Save the original\n                        request.Headers[_options.OriginalForHeaderName] = new IPEndPoint(connection.RemoteIpAddress, connection.RemotePort).ToString();\n                    }\n                    if (forwardedFor.Length > entriesConsumed)\n                    {\n                        // Truncate the consumed header values\n                        request.Headers[_options.ForwardedForHeaderName] = forwardedFor.Take(forwardedFor.Length - entriesConsumed).ToArray();\n                    }\n                    else\n                    {\n                        // All values were consumed\n                        request.Headers.Remove(_options.ForwardedForHeaderName);\n                    }\n                    connection.RemoteIpAddress = currentValues.RemoteIpAndPort.Address;\n                    connection.RemotePort = currentValues.RemoteIpAndPort.Port;\n                }\n\n                if (checkProto && currentValues.Scheme != null)\n                {\n                    // Save the original\n                    request.Headers[_options.OriginalProtoHeaderName] = request.Scheme;\n                    if (forwardedProto.Length > entriesConsumed)\n                    {\n                        // Truncate the consumed header values\n                        request.Headers[_options.ForwardedProtoHeaderName] = forwardedProto.Take(forwardedProto.Length - entriesConsumed).ToArray();\n                    }\n                    else\n                    {\n                        // All values were consumed\n                        request.Headers.Remove(_options.ForwardedProtoHeaderName);\n                    }\n                    request.Scheme = currentValues.Scheme;\n                }\n\n                if (checkHost && currentValues.Host != null)\n                {\n                    // Save the original\n                    request.Headers[_options.OriginalHostHeaderName] = request.Host.ToString();\n                    if (forwardedHost.Length > entriesConsumed)\n                    {\n                        // Truncate the consumed header values\n                        request.Headers[_options.ForwardedHostHeaderName] = forwardedHost.Take(forwardedHost.Length - entriesConsumed).ToArray();\n                    }\n                    else\n                    {\n                        // All values were consumed\n                        request.Headers.Remove(_options.ForwardedHostHeaderName);\n                    }\n                    request.Host = HostString.FromUriComponent(currentValues.Host);\n                }\n            }\n        }\n\n        private bool CheckKnownAddress(IPAddress address)\n        {\n            if (address.IsIPv4MappedToIPv6)\n            {\n                var ipv4Address = address.MapToIPv4();\n                if (CheckKnownAddress(ipv4Address))\n                {\n                    return true;\n                }\n            }\n            if (_options.KnownProxies.Contains(address))\n            {\n                return true;\n            }\n            foreach (var network in _options.KnownNetworks)\n            {\n                if (network.Contains(address))\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private struct SetOfForwarders\n        {\n            public string IpAndPortText;\n            public IPEndPoint RemoteIpAndPort;\n            public string Host;\n            public string Scheme;\n        }\n\n        // Empty was checked for by the caller\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private bool TryValidateScheme(string scheme)\n        {\n            for (var i = 0; i < scheme.Length; i++)\n            {\n                if (!IsValidSchemeChar(scheme[i]))\n                {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static bool IsValidSchemeChar(char ch)\n        {\n            return ch < SchemeCharValidity.Length && SchemeCharValidity[ch];\n        }\n\n        // Empty was checked for by the caller\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private bool TryValidateHost(string host)\n        {\n            if (host[0] == '[')\n            {\n                return TryValidateIPv6Host(host);\n            }\n\n            if (host[0] == ':')\n            {\n                // Only a port\n                return false;\n            }\n\n            var i = 0;\n            for (; i < host.Length; i++)\n            {\n                if (!IsValidHostChar(host[i]))\n                {\n                    break;\n                }\n            }\n            return TryValidateHostPort(host, i);\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private static bool IsValidHostChar(char ch)\n        {\n            return ch < HostCharValidity.Length && HostCharValidity[ch];\n        }\n\n        // The lead '[' was already checked\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private bool TryValidateIPv6Host(string hostText)\n        {\n            for (var i = 1; i < hostText.Length; i++)\n            {\n                var ch = hostText[i];\n                if (ch == ']')\n                {\n                    // [::1] is the shortest valid IPv6 host\n                    if (i < 4)\n                    {\n                        return false;\n                    }\n                    return TryValidateHostPort(hostText, i + 1);\n                }\n\n                if (!IsHex(ch) && ch != ':' && ch != '.')\n                {\n                    return false;\n                }\n            }\n\n            // Must contain a ']'\n            return false;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private bool TryValidateHostPort(string hostText, int offset)\n        {\n            if (offset == hostText.Length)\n            {\n                // No port\n                return true;\n            }\n\n            if (hostText[offset] != ':' || hostText.Length == offset + 1)\n            {\n                // Must have at least one number after the colon if present.\n                return false;\n            }\n\n            for (var i = offset + 1; i < hostText.Length; i++)\n            {\n                if (!IsNumeric(hostText[i]))\n                {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private bool IsNumeric(char ch)\n        {\n            return '0' <= ch && ch <= '9';\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        private bool IsHex(char ch)\n        {\n            return IsNumeric(ch)\n                || ('a' <= ch && ch <= 'f')\n                || ('A' <= ch && ch <= 'F');\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/ForwardedHeadersOptions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.Net;\nusing Microsoft.AspNetCore.HttpOverrides;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    public class ForwardedHeadersOptions\n    {\n        /// <summary>\n        /// Use this header instead of <see cref=\"ForwardedHeadersDefaults.XForwardedForHeaderName\"/>\n        /// </summary>\n        /// <seealso cref=\"Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersDefaults\"/>\n        public string ForwardedForHeaderName { get; set; } = ForwardedHeadersDefaults.XForwardedForHeaderName;\n\n        /// <summary>\n        /// Use this header instead of <see cref=\"ForwardedHeadersDefaults.XForwardedHostHeaderName\"/>\n        /// </summary>\n        /// <seealso cref=\"ForwardedHeadersDefaults\"/>\n        public string ForwardedHostHeaderName { get; set; } = ForwardedHeadersDefaults.XForwardedHostHeaderName;\n\n        /// <summary>\n        /// Use this header instead of <see cref=\"ForwardedHeadersDefaults.XForwardedProtoHeaderName\"/>\n        /// </summary>\n        /// <seealso cref=\"ForwardedHeadersDefaults\"/>\n        public string ForwardedProtoHeaderName { get; set; } = ForwardedHeadersDefaults.XForwardedProtoHeaderName;\n\n        /// <summary>\n        /// Use this header instead of <see cref=\"ForwardedHeadersDefaults.XOriginalForHeaderName\"/>\n        /// </summary>\n        /// <seealso cref=\"ForwardedHeadersDefaults\"/>\n        public string OriginalForHeaderName { get; set; } = ForwardedHeadersDefaults.XOriginalForHeaderName;\n\n        /// <summary>\n        /// Use this header instead of <see cref=\"ForwardedHeadersDefaults.XOriginalHostHeaderName\"/>\n        /// </summary>\n        /// <seealso cref=\"ForwardedHeadersDefaults\"/>\n        public string OriginalHostHeaderName { get; set; } = ForwardedHeadersDefaults.XOriginalHostHeaderName;\n\n        /// <summary>\n        /// Use this header instead of <see cref=\"ForwardedHeadersDefaults.XOriginalProtoHeaderName\"/>\n        /// </summary>\n        /// <seealso cref=\"ForwardedHeadersDefaults\"/>\n        public string OriginalProtoHeaderName { get; set; } = ForwardedHeadersDefaults.XOriginalProtoHeaderName;\n\n        /// <summary>\n        /// Identifies which forwarders should be processed.\n        /// </summary>\n        public ForwardedHeaders ForwardedHeaders { get; set; }\n\n        /// <summary>\n        /// Limits the number of entries in the headers that will be processed. The default value is 1.\n        /// Set to null to disable the limit, but this should only be done if\n        /// KnownProxies or KnownNetworks are configured.\n        /// </summary>\n        public int? ForwardLimit { get; set; } = 1;\n\n        /// <summary>\n        /// Addresses of known proxies to accept forwarded headers from.\n        /// </summary>\n        public IList<IPAddress> KnownProxies { get; } = new List<IPAddress>() { IPAddress.IPv6Loopback };\n\n        /// <summary>\n        /// Address ranges of known proxies to accept forwarded headers from.\n        /// </summary>\n        public IList<IPNetwork> KnownNetworks { get; } = new List<IPNetwork>() { new IPNetwork(IPAddress.Loopback, 8) };\n\n        /// <summary>\n        /// The allowed values from x-forwarded-host. If the list is empty then all hosts are allowed.\n        /// Failing to restrict this these values may allow an attacker to spoof links generated by your service. \n        /// </summary>\n        /// <remarks>\n        /// <list type=\"bullet\">\n        /// <item><description>Port numbers must be excluded.</description></item>\n        /// <item><description>A top level wildcard \"*\" allows all non-empty hosts.</description></item>\n        /// <item><description>Subdomain wildcards are permitted. E.g. \"*.example.com\" matches subdomains like foo.example.com,\n        ///    but not the parent domain example.com.</description></item>\n        /// <item><description>Unicode host names are allowed but will be converted to punycode for matching.</description></item>\n        /// <item><description>IPv6 addresses must include their bounding brackets and be in their normalized form.</description></item>\n        /// </list>\n        /// </remarks>\n        public IList<string> AllowedHosts { get; set;  } = new List<string>();\n\n        /// <summary>\n        /// Require the number of header values to be in sync between the different headers being processed.\n        /// The default is 'false'.\n        /// </summary>\n        public bool RequireHeaderSymmetry { get; set; } = false;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/HttpMethodOverrideExtensions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.HttpOverrides;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    public static class HttpMethodOverrideExtensions\n    {\n        /// <summary>\n        /// Allows incoming POST request to override method type with type specified in header.\n        /// </summary>\n        /// <param name=\"builder\">The <see cref=\"IApplicationBuilder\"/> instance this method extends.</param>\n        public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder)\n        {\n            if (builder == null)\n            {\n                throw new ArgumentNullException(nameof(builder));\n            }\n\n            return builder.UseMiddleware<HttpMethodOverrideMiddleware>();\n        }\n\n        /// <summary>\n        /// Allows incoming POST request to override method type with type specified in form.\n        /// </summary>\n        /// <param name=\"builder\">The <see cref=\"IApplicationBuilder\"/> instance this method extends.</param>\n        /// <param name=\"options\">The <see cref=\"HttpMethodOverrideOptions\"/>.</param>\n        public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder, HttpMethodOverrideOptions options)\n        {\n            if (builder == null)\n            {\n                throw new ArgumentNullException(nameof(builder));\n            }\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            return builder.UseMiddleware<HttpMethodOverrideMiddleware>(Options.Create(options));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/HttpMethodOverrideMiddleware.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.HttpOverrides\n{\n    public class HttpMethodOverrideMiddleware\n    {\n        private const string xHttpMethodOverride = \"X-Http-Method-Override\";\n        private readonly RequestDelegate _next;\n        private readonly HttpMethodOverrideOptions _options;\n\n        public HttpMethodOverrideMiddleware(RequestDelegate next, IOptions<HttpMethodOverrideOptions> options)\n        {\n            if (next == null)\n            {\n                throw new ArgumentNullException(nameof(next));\n            }\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n            _next = next;\n            _options = options.Value;\n        }\n\n        public async Task Invoke(HttpContext context)\n        {\n            if (string.Equals(context.Request.Method, \"POST\", StringComparison.OrdinalIgnoreCase))\n            {\n                if (_options.FormFieldName != null)\n                {\n                    if (context.Request.HasFormContentType)\n                    {\n                        var form = await context.Request.ReadFormAsync();\n                        var methodType = form[_options.FormFieldName];\n                        if (!string.IsNullOrEmpty(methodType))\n                        {\n                            context.Request.Method = methodType;\n                        }\n                    }\n                }\n                else\n                {\n                    var xHttpMethodOverrideValue = context.Request.Headers[xHttpMethodOverride];\n                    if (!string.IsNullOrEmpty(xHttpMethodOverrideValue))\n                    {\n                        context.Request.Method = xHttpMethodOverrideValue;\n                    }\n                }\n            }\n            await _next(context);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/HttpMethodOverrideOptions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    public class HttpMethodOverrideOptions\n    {\n        /// <summary>\n        /// Denotes the form element that contains the name of the resulting method type.\n        /// If not set the X-Http-Method-Override header will be used.\n        /// </summary>\n        public string FormFieldName { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/IPNetwork.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Net;\n\nnamespace Microsoft.AspNetCore.HttpOverrides\n{\n    public class IPNetwork\n    {\n        public IPNetwork(IPAddress prefix, int prefixLength)\n        {\n            Prefix = prefix;\n            PrefixLength = prefixLength;\n            PrefixBytes = Prefix.GetAddressBytes();\n            Mask = CreateMask();\n        }\n\n        public IPAddress Prefix { get; }\n\n        private byte[] PrefixBytes { get; }\n\n        /// <summary>\n        /// The CIDR notation of the subnet mask \n        /// </summary>\n        public int PrefixLength { get; }\n\n        private byte[] Mask { get; }\n\n        public bool Contains(IPAddress address)\n        {\n            if (Prefix.AddressFamily != address.AddressFamily)\n            {\n                return false;\n            }\n\n            var addressBytes = address.GetAddressBytes();\n            for (int i = 0; i < PrefixBytes.Length && Mask[i] != 0; i++)\n            {\n                if (PrefixBytes[i] != (addressBytes[i] & Mask[i]))\n                {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        private byte[] CreateMask()\n        {\n            var mask = new byte[PrefixBytes.Length];\n            int remainingBits = PrefixLength;\n            int i = 0;\n            while (remainingBits >= 8)\n            {\n                mask[i] = 0xFF;\n                i++;\n                remainingBits -= 8;\n            }\n            if (remainingBits > 0)\n            {\n                mask[i] = (byte)(0xFF << (8 - remainingBits));\n            }\n\n            return mask;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/Internal/IPEndPointParser.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Globalization;\nusing System.Net;\n\nnamespace Microsoft.AspNetCore.HttpOverrides.Internal\n{\n    public static class IPEndPointParser\n    {\n        public static bool TryParse(string addressWithPort, out IPEndPoint endpoint)\n        {\n            string addressPart = null;\n            string portPart = null;\n            IPAddress address;\n            endpoint = null;\n\n            if (string.IsNullOrEmpty(addressWithPort))\n            {\n                return false;\n            }\n\n            var lastColonIndex = addressWithPort.LastIndexOf(':');\n            if (lastColonIndex > 0)\n            {\n                // IPv4 with port or IPv6\n                var closingIndex = addressWithPort.LastIndexOf(']');\n                if (closingIndex > 0)\n                {\n                    // IPv6 with brackets\n                    addressPart = addressWithPort.Substring(1, closingIndex - 1);\n                    if (closingIndex < lastColonIndex)\n                    {\n                        // IPv6 with port [::1]:80\n                        portPart = addressWithPort.Substring(lastColonIndex + 1);\n                    }\n                }\n                else\n                {\n                    // IPv6 without port or IPv4\n                    var firstColonIndex = addressWithPort.IndexOf(':');\n                    if (firstColonIndex != lastColonIndex)\n                    {\n                        // IPv6 ::1\n                        addressPart = addressWithPort;\n                    }\n                    else\n                    {\n                        // IPv4 with port 127.0.0.1:123\n                        addressPart = addressWithPort.Substring(0, firstColonIndex);\n                        portPart = addressWithPort.Substring(firstColonIndex + 1);\n                    }\n                }\n            }\n            else\n            {\n                // IPv4 without port\n                addressPart = addressWithPort;\n            }\n\n            if (IPAddress.TryParse(addressPart, out address))\n            {\n                if (portPart != null)\n                {\n                    int port;\n                    if (int.TryParse(portPart, NumberStyles.None, CultureInfo.InvariantCulture, out port))\n                    {\n                        endpoint = new IPEndPoint(address, port);\n                        return true;\n                    }\n                    return false;\n                }\n                endpoint = new IPEndPoint(address, 0);\n                return true;\n            }\n            return false;\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/Microsoft.AspNetCore.HttpOverrides.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <Description>ASP.NET Core basic middleware for supporting HTTP method overrides. Includes:\n* X-Forwarded-* headers to forward headers from a proxy.\n* HTTP method override header.</Description>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <NoWarn>$(NoWarn);CS1591</NoWarn>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <PackageTags>aspnetcore;proxy;headers;xforwarded</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Http.Extensions\" Version=\"$(MicrosoftAspNetCoreHttpExtensionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Abstractions\" Version=\"$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Options\" Version=\"$(MicrosoftExtensionsOptionsPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/baseline.net45.json",
    "content": "{\n  \"AssemblyIdentity\": \"Microsoft.AspNetCore.HttpOverrides, Version=1.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60\",\n  \"Types\": [\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.ForwardedHeadersExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseForwardedHeaders\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseForwardedHeaders\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.ForwardedHeadersOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.ForwardedHeadersOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_ForwardedHeaders\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_ForwardedHeaders\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_ForwardLimit\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Nullable<System.Int32>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_ForwardLimit\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Nullable<System.Int32>\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_KnownProxies\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IList<System.Net.IPAddress>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_KnownNetworks\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IList<Microsoft.AspNetCore.HttpOverrides.IPNetwork>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_RequireHeaderSymmetry\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_RequireHeaderSymmetry\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HttpMethodOverrideExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseHttpMethodOverride\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseHttpMethodOverride\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.HttpMethodOverrideOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HttpMethodOverrideOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_FormFieldName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_FormFieldName\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Enumeration\",\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"None\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"0\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"XForwardedFor\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"1\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"XForwardedHost\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"2\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"XForwardedProto\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"4\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"All\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"7\"\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"ApplyForwarders\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"loggerFactory\",\n              \"Type\": \"Microsoft.Extensions.Logging.ILoggerFactory\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.ForwardedHeadersOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.HttpMethodOverrideMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.HttpMethodOverrideOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.IPNetwork\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Prefix\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Net.IPAddress\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_PrefixLength\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Int32\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Contains\",\n          \"Parameters\": [\n            {\n              \"Name\": \"address\",\n              \"Type\": \"System.Net.IPAddress\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"prefix\",\n              \"Type\": \"System.Net.IPAddress\"\n            },\n            {\n              \"Name\": \"prefixLength\",\n              \"Type\": \"System.Int32\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.Internal.IPEndPointParser\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"TryParse\",\n          \"Parameters\": [\n            {\n              \"Name\": \"addressWithPort\",\n              \"Type\": \"System.String\"\n            },\n            {\n              \"Name\": \"endpoint\",\n              \"Type\": \"System.Net.IPEndPoint\",\n              \"Direction\": \"Out\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"Static\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    }\n  ]\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpOverrides/baseline.netcore.json",
    "content": "{\n  \"AssemblyIdentity\": \"Microsoft.AspNetCore.HttpOverrides, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60\",\n  \"Types\": [\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.ForwardedHeadersExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseForwardedHeaders\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseForwardedHeaders\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.ForwardedHeadersOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.ForwardedHeadersOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_ForwardedForHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_ForwardedForHeaderName\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_ForwardedHostHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_ForwardedHostHeaderName\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_ForwardedProtoHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_ForwardedProtoHeaderName\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_OriginalForHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_OriginalForHeaderName\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_OriginalHostHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_OriginalHostHeaderName\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_OriginalProtoHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_OriginalProtoHeaderName\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_ForwardedHeaders\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_ForwardedHeaders\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_ForwardLimit\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Nullable<System.Int32>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_ForwardLimit\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Nullable<System.Int32>\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_KnownProxies\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IList<System.Net.IPAddress>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_KnownNetworks\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IList<Microsoft.AspNetCore.HttpOverrides.IPNetwork>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_AllowedHosts\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IList<System.String>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_AllowedHosts\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Collections.Generic.IList<System.String>\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_RequireHeaderSymmetry\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_RequireHeaderSymmetry\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HttpMethodOverrideExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseHttpMethodOverride\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseHttpMethodOverride\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.HttpMethodOverrideOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HttpMethodOverrideOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_FormFieldName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_FormFieldName\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Enumeration\",\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"None\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"0\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"XForwardedFor\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"1\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"XForwardedHost\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"2\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"XForwardedProto\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"4\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"All\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"7\"\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersDefaults\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_XForwardedForHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Static\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_XForwardedHostHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Static\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_XForwardedProtoHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Static\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_XOriginalForHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Static\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_XOriginalHostHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Static\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_XOriginalProtoHeaderName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Static\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"ApplyForwarders\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"loggerFactory\",\n              \"Type\": \"Microsoft.Extensions.Logging.ILoggerFactory\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.ForwardedHeadersOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.HttpMethodOverrideMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Builder.HttpMethodOverrideOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpOverrides.IPNetwork\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Prefix\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Net.IPAddress\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_PrefixLength\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Int32\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Contains\",\n          \"Parameters\": [\n            {\n              \"Name\": \"address\",\n              \"Type\": \"System.Net.IPAddress\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"prefix\",\n              \"Type\": \"System.Net.IPAddress\"\n            },\n            {\n              \"Name\": \"prefixLength\",\n              \"Type\": \"System.Int32\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    }\n  ]\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/HstsBuilderExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.HttpsPolicy;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the HSTS middleware.\n    /// </summary>\n    public static class HstsBuilderExtensions\n    {\n        /// <summary>\n        /// Adds middleware for using HSTS, which adds the Strict-Transport-Security header.\n        /// </summary>\n        /// <param name=\"app\">The <see cref=\"IApplicationBuilder\"/> instance this method extends.</param>\n        public static IApplicationBuilder UseHsts(this IApplicationBuilder app)\n        {\n            if (app == null)\n            {\n                throw new ArgumentNullException(nameof(app));\n            }\n\n            return app.UseMiddleware<HstsMiddleware>();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/HstsMiddleware.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.HttpsPolicy.Internal;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Logging.Abstractions;\nusing Microsoft.Extensions.Options;\nusing Microsoft.Extensions.Primitives;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy\n{\n    /// <summary>\n    /// Enables HTTP Strict Transport Security (HSTS)\n    /// See https://tools.ietf.org/html/rfc6797.\n    /// </summary>\n    public class HstsMiddleware\n    {\n        private const string IncludeSubDomains = \"; includeSubDomains\";\n        private const string Preload = \"; preload\";\n\n        private readonly RequestDelegate _next;\n        private readonly StringValues _strictTransportSecurityValue;\n        private readonly IList<string> _excludedHosts;\n        private readonly ILogger _logger;\n\n        /// <summary>\n        /// Initialize the HSTS middleware.\n        /// </summary>\n        /// <param name=\"next\"></param>\n        /// <param name=\"options\"></param>\n        /// <param name=\"loggerFactory\"></param>\n        public HstsMiddleware(RequestDelegate next, IOptions<HstsOptions> options, ILoggerFactory loggerFactory)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            _next = next ?? throw new ArgumentNullException(nameof(next));\n\n            var hstsOptions = options.Value;\n            var maxAge = Convert.ToInt64(Math.Floor(hstsOptions.MaxAge.TotalSeconds))\n                            .ToString(CultureInfo.InvariantCulture);\n            var includeSubdomains = hstsOptions.IncludeSubDomains ? IncludeSubDomains : StringSegment.Empty;\n            var preload = hstsOptions.Preload ? Preload : StringSegment.Empty;\n            _strictTransportSecurityValue = new StringValues($\"max-age={maxAge}{includeSubdomains}{preload}\");\n            _excludedHosts = hstsOptions.ExcludedHosts;\n            _logger = loggerFactory.CreateLogger<HstsMiddleware>();\n        }\n\n        /// <summary>\n        /// Initialize the HSTS middleware.\n        /// </summary>\n        /// <param name=\"next\"></param>\n        /// <param name=\"options\"></param>\n        public HstsMiddleware(RequestDelegate next, IOptions<HstsOptions> options)\n            : this(next, options, NullLoggerFactory.Instance) { }\n\n        /// <summary>\n        /// Invoke the middleware.\n        /// </summary>\n        /// <param name=\"context\">The <see cref=\"HttpContext\"/>.</param>\n        /// <returns></returns>\n        public Task Invoke(HttpContext context)\n        {\n            if (!context.Request.IsHttps)\n            {\n                _logger.SkippingInsecure();\n                return _next(context);\n            }\n\n            if (IsHostExcluded(context.Request.Host.Host))\n            {\n                _logger.SkippingExcludedHost(context.Request.Host.Host);\n                return _next(context);\n            }\n\n            context.Response.Headers[HeaderNames.StrictTransportSecurity] = _strictTransportSecurityValue;\n            _logger.AddingHstsHeader();\n\n            return _next(context);\n        }\n\n        private bool IsHostExcluded(string host)\n        {\n            if (_excludedHosts == null)\n            {\n                return false;\n            }\n\n            for (var i = 0; i < _excludedHosts.Count; i++)\n            {\n                if (string.Equals(host, _excludedHosts[i], StringComparison.OrdinalIgnoreCase))\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/HstsOptions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy\n{\n    /// <summary>\n    /// Options for the Hsts Middleware\n    /// </summary>\n    public class HstsOptions\n    {\n        /// <summary>\n        /// Sets the max-age parameter of the Strict-Transport-Security header.\n        /// </summary>\n        /// <remarks>\n        /// Max-age is required; defaults to 30 days.\n        /// See: https://tools.ietf.org/html/rfc6797#section-6.1.1\n        /// </remarks>\n        public TimeSpan MaxAge { get; set; } = TimeSpan.FromDays(30);\n\n        /// <summary>\n        /// Enables includeSubDomain parameter of the Strict-Transport-Security header.\n        /// </summary>\n        /// <remarks>\n        /// See: https://tools.ietf.org/html/rfc6797#section-6.1.2\n        /// </remarks>\n        public bool IncludeSubDomains { get; set; }\n\n        /// <summary>\n        /// Sets the preload parameter of the Strict-Transport-Security header.\n        /// </summary>\n        /// <remarks>\n        /// Preload is not part of the RFC specification, but is supported by web browsers\n        /// to preload HSTS sites on fresh install. See https://hstspreload.org/.\n        /// </remarks>\n        public bool Preload { get; set; }\n\n        /// <summary>\n        /// A list of host names that will not add the HSTS header.\n        /// </summary>\n        public IList<string> ExcludedHosts { get; } = new List<string>\n        {\n            \"localhost\",\n            \"127.0.0.1\", // ipv4\n            \"[::1]\" // ipv6\n        };\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/HstsServicesExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.HttpsPolicy;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the HSTS middleware.\n    /// </summary>\n    public static class HstsServicesExtensions\n    {\n        /// <summary>\n        /// Adds HSTS services.\n        /// </summary>\n        /// <param name=\"services\">The <see cref=\"IServiceCollection\"/> for adding services.</param>\n        /// <param name=\"configureOptions\">A delegate to configure the <see cref=\"HstsOptions\"/>.</param>\n        /// <returns></returns>\n        public static IServiceCollection AddHsts(this IServiceCollection services, Action<HstsOptions> configureOptions)\n        {\n            if (services == null)\n            {\n                throw new ArgumentNullException(nameof(services));\n            }\n            if (configureOptions == null)\n            {\n                throw new ArgumentNullException(nameof(configureOptions));\n            }\n\n            services.Configure(configureOptions);\n            return services;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/HttpsRedirectionBuilderExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Hosting.Server.Features;\nusing Microsoft.AspNetCore.HttpsPolicy;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the HttpsRedirection middleware.\n    /// </summary>\n    public static class HttpsPolicyBuilderExtensions\n    {\n        /// <summary>\n        /// Adds middleware for redirecting HTTP Requests to HTTPS.\n        /// </summary>\n        /// <param name=\"app\">The <see cref=\"IApplicationBuilder\"/> instance this method extends.</param>\n        /// <returns>The <see cref=\"IApplicationBuilder\"/> for HttpsRedirection.</returns>\n        public static IApplicationBuilder UseHttpsRedirection(this IApplicationBuilder app)\n        {\n            if (app == null)\n            {\n                throw new ArgumentNullException(nameof(app));\n            }\n\n            var serverAddressFeature = app.ServerFeatures.Get<IServerAddressesFeature>();\n            if (serverAddressFeature != null)\n            {\n                app.UseMiddleware<HttpsRedirectionMiddleware>(serverAddressFeature);\n            }\n            else\n            {\n                app.UseMiddleware<HttpsRedirectionMiddleware>();\n            }\n            return app;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/HttpsRedirectionMiddleware.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Hosting.Server.Features;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Extensions;\nusing Microsoft.AspNetCore.Http.Internal;\nusing Microsoft.AspNetCore.HttpsPolicy.Internal;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy\n{\n    public class HttpsRedirectionMiddleware\n    {\n        private readonly RequestDelegate _next;\n        private bool _portEvaluated = false;\n        private int? _httpsPort;\n        private readonly int _statusCode;\n\n        private readonly IServerAddressesFeature _serverAddressesFeature;\n        private readonly IConfiguration _config;\n        private readonly ILogger _logger;\n\n        /// <summary>\n        /// Initializes the HttpsRedirectionMiddleware\n        /// </summary>\n        /// <param name=\"next\"></param>\n        /// <param name=\"options\"></param>\n        /// <param name=\"config\"></param>\n        /// <param name=\"loggerFactory\"></param>\n        public HttpsRedirectionMiddleware(RequestDelegate next, IOptions<HttpsRedirectionOptions> options, IConfiguration config, ILoggerFactory loggerFactory)\n\n        {\n            _next = next ?? throw new ArgumentNullException(nameof(next));\n            _config = config ?? throw new ArgumentNullException(nameof(config));\n\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n            var httpsRedirectionOptions = options.Value;\n            _httpsPort = httpsRedirectionOptions.HttpsPort;\n            _portEvaluated = _httpsPort.HasValue;\n            _statusCode = httpsRedirectionOptions.RedirectStatusCode;\n            _logger = loggerFactory.CreateLogger<HttpsRedirectionMiddleware>();\n        }\n\n        /// <summary>\n        /// Initializes the HttpsRedirectionMiddleware\n        /// </summary>\n        /// <param name=\"next\"></param>\n        /// <param name=\"options\"></param>\n        /// <param name=\"config\"></param>\n        /// <param name=\"loggerFactory\"></param>\n        /// <param name=\"serverAddressesFeature\">The</param>\n        public HttpsRedirectionMiddleware(RequestDelegate next, IOptions<HttpsRedirectionOptions> options, IConfiguration config, ILoggerFactory loggerFactory,\n            IServerAddressesFeature serverAddressesFeature)\n            : this(next, options, config, loggerFactory)\n        {\n            _serverAddressesFeature = serverAddressesFeature ?? throw new ArgumentNullException(nameof(serverAddressesFeature));\n        }\n\n        /// <summary>\n        /// Invokes the HttpsRedirectionMiddleware\n        /// </summary>\n        /// <param name=\"context\"></param>\n        /// <returns></returns>\n        public Task Invoke(HttpContext context)\n        {\n            if (context.Request.IsHttps || !TryGetHttpsPort(out var port))\n            {\n                return _next(context);\n            }\n\n            var host = context.Request.Host;\n            if (port != 443)\n            {\n                host = new HostString(host.Host, port);\n            }\n            else\n            {\n                host = new HostString(host.Host);\n            }\n\n            var request = context.Request;\n            var redirectUrl = UriHelper.BuildAbsolute(\n                \"https\", \n                host,\n                request.PathBase,\n                request.Path,\n                request.QueryString);\n\n            context.Response.StatusCode = _statusCode;\n            context.Response.Headers[HeaderNames.Location] = redirectUrl;\n\n            _logger.RedirectingToHttps(redirectUrl);\n\n            return Task.CompletedTask;\n        }\n\n        private bool TryGetHttpsPort(out int port)\n        {\n            // The IServerAddressesFeature will not be ready until the middleware is Invoked,\n            // Order for finding the HTTPS port:\n            // 1. Set in the HttpsRedirectionOptions\n            // 2. HTTPS_PORT environment variable\n            // 3. IServerAddressesFeature\n            // 4. Fail if not set\n\n            port = -1;\n\n            if (_portEvaluated)\n            {\n                port = _httpsPort ?? port;\n                return _httpsPort.HasValue;\n            }\n            _portEvaluated = true;\n\n            _httpsPort = _config.GetValue<int?>(\"HTTPS_PORT\");\n            if (_httpsPort.HasValue)\n            {\n                port = _httpsPort.Value;\n                _logger.PortLoadedFromConfig(port);\n                return true;\n            }\n\n            if (_serverAddressesFeature == null)\n            {\n                _logger.FailedToDeterminePort();\n                return false;\n            }\n\n            int? httpsPort = null;\n            foreach (var address in _serverAddressesFeature.Addresses)\n            {\n                var bindingAddress = BindingAddress.Parse(address);\n                if (bindingAddress.Scheme.Equals(\"https\", StringComparison.OrdinalIgnoreCase))\n                {\n                    // If we find multiple different https ports specified, throw\n                    if (httpsPort.HasValue && httpsPort != bindingAddress.Port)\n                    {\n                        _logger.FailedMultiplePorts();\n                        return false;\n                    }\n                    else\n                    {\n                        httpsPort = bindingAddress.Port;\n                    }\n                }\n            }\n\n            if (httpsPort.HasValue)\n            {\n                _httpsPort = httpsPort;\n                port = _httpsPort.Value;\n                _logger.PortFromServer(port);\n                return true;\n            }\n\n            _logger.FailedToDeterminePort();\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/HttpsRedirectionOptions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy\n{\n    /// <summary>\n    /// Options for the HttpsRedirection middleware\n    /// </summary>\n    public class HttpsRedirectionOptions\n    {\n        /// <summary>\n        /// The status code used for the redirect response. The default is 307.\n        /// </summary>\n        public int RedirectStatusCode { get; set; } = StatusCodes.Status307TemporaryRedirect;\n\n        /// <summary>\n        /// The HTTPS port to be added to the redirected URL.\n        /// </summary>\n        /// <remarks>\n        /// If the HttpsPort is not set, we will try to get the HttpsPort from the following:\n        /// 1. HTTPS_PORT environment variable\n        /// 2. IServerAddressesFeature\n        /// If that fails then the middleware will log a warning and turn off.\n        /// </remarks>\n        public int? HttpsPort { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/HttpsRedirectionServicesExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.HttpsPolicy;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the HttpsRedirection middleware.\n    /// </summary>\n    public static class HttpsRedirectionServicesExtensions\n    {\n        /// <summary>\n        /// Adds HTTPS redirection services.\n        /// </summary>\n        /// <param name=\"services\">The <see cref=\"IServiceCollection\"/> for adding services.</param>\n        /// <param name=\"configureOptions\">A delegate to configure the <see cref=\"HttpsRedirectionOptions\"/>.</param>\n        /// <returns></returns>\n        public static IServiceCollection AddHttpsRedirection(this IServiceCollection services, Action<HttpsRedirectionOptions> configureOptions)\n        {\n            if (services == null)\n            {\n                throw new ArgumentNullException(nameof(services));\n            }\n            if (configureOptions == null)\n            {\n                throw new ArgumentNullException(nameof(configureOptions));\n            }\n            services.Configure(configureOptions);\n            return services;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/Microsoft.AspNetCore.HttpsPolicy.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <Description>\n      ASP.NET Core basic middleware for supporting HTTPS Redirection and HTTP Strict-Transport-Security.\n    </Description>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <NoWarn>$(NoWarn);CS1591</NoWarn>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <PackageTags>aspnetcore;https;hsts</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Http\" Version=\"$(MicrosoftAspNetCoreHttpAbstractionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Http.Extensions\" Version=\"$(MicrosoftAspNetCoreHttpExtensionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Configuration.Binder\" Version=\"$(MicrosoftExtensionsConfigurationBinderPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Options\" Version=\"$(MicrosoftExtensionsOptionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Hosting.Abstractions\" Version=\"$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)\" /> \n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/baseline.netcore.json",
    "content": "{\n  \"AssemblyIdentity\": \"Microsoft.AspNetCore.HttpsPolicy, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60\",\n  \"Types\": [\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpsPolicy.HstsMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.HttpsPolicy.HstsOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpsPolicy.HstsOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_MaxAge\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.TimeSpan\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_MaxAge\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.TimeSpan\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_IncludeSubDomains\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_IncludeSubDomains\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Preload\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_Preload\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_ExcludedHosts\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IList<System.String>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionOptions>\"\n            },\n            {\n              \"Name\": \"config\",\n              \"Type\": \"Microsoft.Extensions.Configuration.IConfiguration\"\n            },\n            {\n              \"Name\": \"loggerFactory\",\n              \"Type\": \"Microsoft.Extensions.Logging.ILoggerFactory\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionOptions>\"\n            },\n            {\n              \"Name\": \"config\",\n              \"Type\": \"Microsoft.Extensions.Configuration.IConfiguration\"\n            },\n            {\n              \"Name\": \"loggerFactory\",\n              \"Type\": \"Microsoft.Extensions.Logging.ILoggerFactory\"\n            },\n            {\n              \"Name\": \"serverAddressesFeature\",\n              \"Type\": \"Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_RedirectStatusCode\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Int32\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_RedirectStatusCode\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Int32\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_HttpsPort\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Nullable<System.Int32>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_HttpsPort\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Nullable<System.Int32>\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HstsBuilderExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseHsts\",\n          \"Parameters\": [\n            {\n              \"Name\": \"app\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HstsServicesExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddHsts\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\"\n            },\n            {\n              \"Name\": \"configureOptions\",\n              \"Type\": \"System.Action<Microsoft.AspNetCore.HttpsPolicy.HstsOptions>\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HttpsPolicyBuilderExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseHttpsRedirection\",\n          \"Parameters\": [\n            {\n              \"Name\": \"app\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.HttpsRedirectionServicesExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddHttpsRedirection\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\"\n            },\n            {\n              \"Name\": \"configureOptions\",\n              \"Type\": \"System.Action<Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionOptions>\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    }\n  ]\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/internal/HstsLoggingExtensions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.Extensions.Logging;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy.Internal\n{\n    internal static class HstsLoggingExtensions\n    {\n        private static readonly Action<ILogger, Exception> _notSecure;\n        private static readonly Action<ILogger, string, Exception> _excludedHost;\n        private static readonly Action<ILogger, Exception> _addingHstsHeader;\n\n        static HstsLoggingExtensions()\n        {\n            _notSecure = LoggerMessage.Define(LogLevel.Debug, 1, \"The request is insecure. Skipping HSTS header.\");\n            _excludedHost = LoggerMessage.Define<string>(LogLevel.Debug, 2, \"The host '{host}' is excluded. Skipping HSTS header.\");\n            _addingHstsHeader = LoggerMessage.Define(LogLevel.Trace, 3, \"Adding HSTS header to response.\");\n        }\n\n        public static void SkippingInsecure(this ILogger logger)\n        {\n            _notSecure(logger, null);\n        }\n\n        public static void SkippingExcludedHost(this ILogger logger, string host)\n        {\n            _excludedHost(logger, host, null);\n        }\n\n        public static void AddingHstsHeader(this ILogger logger)\n        {\n            _addingHstsHeader(logger, null);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.HttpsPolicy/internal/HttpsLoggingExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.Extensions.Logging;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy.Internal\n{\n    internal static class HttpsLoggingExtensions\n    {\n        private static readonly Action<ILogger, string, Exception> _redirectingToHttps;\n        private static readonly Action<ILogger, int, Exception> _portLoadedFromConfig;\n        private static readonly Action<ILogger, Exception> _failedToDeterminePort;\n        private static readonly Action<ILogger, Exception> _failedMultiplePorts;\n        private static readonly Action<ILogger, int, Exception> _portFromServer;\n\n        static HttpsLoggingExtensions()\n        {\n            _redirectingToHttps = LoggerMessage.Define<string>(LogLevel.Debug, 1, \"Redirecting to '{redirect}'.\");\n            _portLoadedFromConfig = LoggerMessage.Define<int>(LogLevel.Debug, 2, \"Https port '{port}' loaded from configuration.\");\n            _failedToDeterminePort = LoggerMessage.Define(LogLevel.Warning, 3, \"Failed to determine the https port for redirect.\");\n            _failedMultiplePorts = LoggerMessage.Define(LogLevel.Warning, 4,\n                \"Cannot determine the https port from IServerAddressesFeature, multiple values were found. \" +\n                \"Please set the desired port explicitly on HttpsRedirectionOptions.HttpsPort.\");\n            _portFromServer = LoggerMessage.Define<int>(LogLevel.Debug, 5, \"Https port '{httpsPort}' discovered from server endpoints.\");\n        }\n\n        public static void RedirectingToHttps(this ILogger logger, string redirect)\n        {\n            _redirectingToHttps(logger, redirect, null);\n        }\n\n        public static void PortLoadedFromConfig(this ILogger logger, int port)\n        {\n            _portLoadedFromConfig(logger, port, null);\n        }\n\n        public static void FailedToDeterminePort(this ILogger logger)\n        {\n            _failedToDeterminePort(logger, null);\n        }\n\n        public static void FailedMultiplePorts(this ILogger logger)\n        {\n            _failedMultiplePorts(logger, null);\n        }\n\n        public static void PortFromServer(this ILogger logger, int port)\n        {\n            _portFromServer(logger, port, null);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/BodyWrapperStream.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Extensions;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Stream wrapper that create specific compression stream only if necessary.\n    /// </summary>\n    internal class BodyWrapperStream : Stream, IHttpBufferingFeature, IHttpSendFileFeature\n    {\n        private readonly HttpContext _context;\n        private readonly Stream _bodyOriginalStream;\n        private readonly IResponseCompressionProvider _provider;\n        private readonly IHttpBufferingFeature _innerBufferFeature;\n        private readonly IHttpSendFileFeature _innerSendFileFeature;\n\n        private ICompressionProvider _compressionProvider = null;\n        private bool _compressionChecked = false;\n        private Stream _compressionStream = null;\n        private bool _providerCreated = false;\n        private bool _autoFlush = false;\n\n        internal BodyWrapperStream(HttpContext context, Stream bodyOriginalStream, IResponseCompressionProvider provider,\n            IHttpBufferingFeature innerBufferFeature, IHttpSendFileFeature innerSendFileFeature)\n        {\n            _context = context;\n            _bodyOriginalStream = bodyOriginalStream;\n            _provider = provider;\n            _innerBufferFeature = innerBufferFeature;\n            _innerSendFileFeature = innerSendFileFeature;\n        }\n\n        protected override void Dispose(bool disposing)\n        {\n            if (_compressionStream != null)\n            {\n                _compressionStream.Dispose();\n                _compressionStream = null;\n            }\n        }\n\n        public override bool CanRead => false;\n\n        public override bool CanSeek => false;\n\n        public override bool CanWrite => _bodyOriginalStream.CanWrite;\n\n        public override long Length\n        {\n            get { throw new NotSupportedException(); }\n        }\n\n        public override long Position\n        {\n            get { throw new NotSupportedException(); }\n            set { throw new NotSupportedException(); }\n        }\n\n        public override void Flush()\n        {\n            if (!_compressionChecked)\n            {\n                OnWrite();\n                // Flush the original stream to send the headers. Flushing the compression stream won't\n                // flush the original stream if no data has been written yet.\n                _bodyOriginalStream.Flush();\n                return;\n            }\n\n            if (_compressionStream != null)\n            {\n                _compressionStream.Flush();\n            }\n            else\n            {\n                _bodyOriginalStream.Flush();\n            }\n        }\n\n        public override Task FlushAsync(CancellationToken cancellationToken)\n        {\n            if (!_compressionChecked)\n            {\n                OnWrite();\n                // Flush the original stream to send the headers. Flushing the compression stream won't\n                // flush the original stream if no data has been written yet.\n                return _bodyOriginalStream.FlushAsync(cancellationToken);\n            }\n\n            if (_compressionStream != null)\n            {\n                return _compressionStream.FlushAsync(cancellationToken);\n            }\n\n            return _bodyOriginalStream.FlushAsync(cancellationToken);\n        }\n\n        public override int Read(byte[] buffer, int offset, int count)\n        {\n            throw new NotSupportedException();\n        }\n\n        public override long Seek(long offset, SeekOrigin origin)\n        {\n            throw new NotSupportedException();\n        }\n\n        public override void SetLength(long value)\n        {\n            throw new NotSupportedException();\n        }\n\n        public override void Write(byte[] buffer, int offset, int count)\n        {\n            OnWrite();\n\n            if (_compressionStream != null)\n            {\n                _compressionStream.Write(buffer, offset, count);\n                if (_autoFlush)\n                {\n                    _compressionStream.Flush();\n                }\n            }\n            else\n            {\n                _bodyOriginalStream.Write(buffer, offset, count);\n            }\n        }\n\n        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)\n        {\n            var tcs = new TaskCompletionSource<object>(state);\n            InternalWriteAsync(buffer, offset, count, callback, tcs);\n            return tcs.Task;\n        }\n\n        private async void InternalWriteAsync(byte[] buffer, int offset, int count, AsyncCallback callback, TaskCompletionSource<object> tcs)\n        {\n            try\n            {\n                await WriteAsync(buffer, offset, count);\n                tcs.TrySetResult(null);\n            }\n            catch (Exception ex)\n            {\n                tcs.TrySetException(ex);\n            }\n\n            if (callback != null)\n            {\n                // Offload callbacks to avoid stack dives on sync completions.\n                var ignored = Task.Run(() =>\n                {\n                    try\n                    {\n                        callback(tcs.Task);\n                    }\n                    catch (Exception)\n                    {\n                        // Suppress exceptions on background threads.\n                    }\n                });\n            }\n        }\n\n        public override void EndWrite(IAsyncResult asyncResult)\n        {\n            if (asyncResult == null)\n            {\n                throw new ArgumentNullException(nameof(asyncResult));\n            }\n\n            var task = (Task)asyncResult;\n            task.GetAwaiter().GetResult();\n        }\n\n        public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)\n        {\n            OnWrite();\n\n            if (_compressionStream != null)\n            {\n                await _compressionStream.WriteAsync(buffer, offset, count, cancellationToken);\n                if (_autoFlush)\n                {\n                    await _compressionStream.FlushAsync(cancellationToken);\n                }\n            }\n            else\n            {\n                await _bodyOriginalStream.WriteAsync(buffer, offset, count, cancellationToken);\n            }\n        }\n\n        private void OnWrite()\n        {\n            if (!_compressionChecked)\n            {\n                _compressionChecked = true;\n                if (_provider.ShouldCompressResponse(_context))\n                {\n                    // If the MIME type indicates that the response could be compressed, caches will need to vary by the Accept-Encoding header\n                    var varyValues = _context.Response.Headers.GetCommaSeparatedValues(HeaderNames.Vary);\n                    var varyByAcceptEncoding = false;\n\n                    for (var i = 0; i < varyValues.Length; i++)\n                    {\n                        if (string.Equals(varyValues[i], HeaderNames.AcceptEncoding, StringComparison.OrdinalIgnoreCase))\n                        {\n                            varyByAcceptEncoding = true;\n                            break;\n                        }\n                    }\n\n                    if (!varyByAcceptEncoding)\n                    {\n                        _context.Response.Headers.Append(HeaderNames.Vary, HeaderNames.AcceptEncoding);\n                    }\n\n                    var compressionProvider = ResolveCompressionProvider();\n                    if (compressionProvider != null)\n                    {\n                        _context.Response.Headers.Append(HeaderNames.ContentEncoding, compressionProvider.EncodingName);\n                        _context.Response.Headers.Remove(HeaderNames.ContentMD5); // Reset the MD5 because the content changed.\n                        _context.Response.Headers.Remove(HeaderNames.ContentLength);\n\n                        _compressionStream = compressionProvider.CreateStream(_bodyOriginalStream);\n                    }\n                }\n            }\n        }\n\n        private ICompressionProvider ResolveCompressionProvider()\n        {\n            if (!_providerCreated)\n            {\n                _providerCreated = true;\n                _compressionProvider = _provider.GetCompressionProvider(_context);\n            }\n\n            return _compressionProvider;\n        }\n\n        public void DisableRequestBuffering()\n        {\n            // Unrelated\n            _innerBufferFeature?.DisableRequestBuffering();\n        }\n\n        // For this to be effective it needs to be called before the first write.\n        public void DisableResponseBuffering()\n        {\n            if (ResolveCompressionProvider()?.SupportsFlush == false)\n            {\n                // Don't compress, some of the providers don't implement Flush (e.g. .NET 4.5.1 GZip/Deflate stream)\n                // which would block real-time responses like SignalR.\n                _compressionChecked = true;\n            }\n            else\n            {\n                _autoFlush = true;\n            }\n            _innerBufferFeature?.DisableResponseBuffering();\n        }\n\n        // The IHttpSendFileFeature feature will only be registered if _innerSendFileFeature exists.\n        public Task SendFileAsync(string path, long offset, long? count, CancellationToken cancellation)\n        {\n            OnWrite();\n\n            if (_compressionStream != null)\n            {\n                return InnerSendFileAsync(path, offset, count, cancellation);\n            }\n\n            return _innerSendFileFeature.SendFileAsync(path, offset, count, cancellation);\n        }\n\n        private async Task InnerSendFileAsync(string path, long offset, long? count, CancellationToken cancellation)\n        {\n            cancellation.ThrowIfCancellationRequested();\n\n            var fileInfo = new FileInfo(path);\n            if (offset < 0 || offset > fileInfo.Length)\n            {\n                throw new ArgumentOutOfRangeException(nameof(offset), offset, string.Empty);\n            }\n            if (count.HasValue &&\n                (count.Value < 0 || count.Value > fileInfo.Length - offset))\n            {\n                throw new ArgumentOutOfRangeException(nameof(count), count, string.Empty);\n            }\n\n            int bufferSize = 1024 * 16;\n\n            var fileStream = new FileStream(\n                path,\n                FileMode.Open,\n                FileAccess.Read,\n                FileShare.ReadWrite,\n                bufferSize: bufferSize,\n                options: FileOptions.Asynchronous | FileOptions.SequentialScan);\n\n            using (fileStream)\n            {\n                fileStream.Seek(offset, SeekOrigin.Begin);\n                await StreamCopyOperation.CopyToAsync(fileStream, _compressionStream, count, cancellation);\n\n                if (_autoFlush)\n                {\n                    await _compressionStream.FlushAsync(cancellation);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/BrotliCompressionProvider.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.IO.Compression;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Brotli compression provider.\n    /// </summary>\n    public class BrotliCompressionProvider : ICompressionProvider\n    {\n        /// <summary>\n        /// Creates a new instance of <see cref=\"BrotliCompressionProvider\"/> with options.\n        /// </summary>\n        /// <param name=\"options\"></param>\n        public BrotliCompressionProvider(IOptions<BrotliCompressionProviderOptions> options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            Options = options.Value;\n        }\n\n        private BrotliCompressionProviderOptions Options { get; }\n\n        /// <inheritdoc />\n        public string EncodingName => \"br\";\n\n        /// <inheritdoc />\n        public bool SupportsFlush => true;\n\n        /// <inheritdoc />\n        public Stream CreateStream(Stream outputStream)\n        {\n#if NETCOREAPP2_1\n            return new BrotliStream(outputStream, Options.Level, leaveOpen: true);\n#elif NET461 || NETSTANDARD2_0\n            // Brotli is only supported in .NET Core 2.1+\n            throw new PlatformNotSupportedException();\n#else\n#error Target frameworks need to be updated.\n#endif\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/BrotliCompressionProviderOptions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO.Compression;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Options for the <see cref=\"BrotliCompressionProvider\"/>\n    /// </summary>\n    public class BrotliCompressionProviderOptions : IOptions<BrotliCompressionProviderOptions>\n    {\n        /// <summary>\n        /// What level of compression to use for the stream. The default is <see cref=\"CompressionLevel.Fastest\"/>.\n        /// </summary>\n        public CompressionLevel Level { get; set; } = CompressionLevel.Fastest;\n\n        /// <inheritdoc />\n        BrotliCompressionProviderOptions IOptions<BrotliCompressionProviderOptions>.Value => this;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/CompressionProviderCollection.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.ObjectModel;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// A Collection of ICompressionProvider's that also allows them to be instantiated from an <see cref=\"IServiceProvider\" />.\n    /// </summary>\n    public class CompressionProviderCollection : Collection<ICompressionProvider>\n    {\n        /// <summary>\n        /// Adds a type representing an <see cref=\"ICompressionProvider\"/>.\n        /// </summary>\n        /// <remarks>\n        /// Provider instances will be created using an <see cref=\"IServiceProvider\" />.\n        /// </remarks>\n        public void Add<TCompressionProvider>() where TCompressionProvider : ICompressionProvider\n        {\n            Add(typeof(TCompressionProvider));\n        }\n\n        /// <summary>\n        /// Adds a type representing an <see cref=\"ICompressionProvider\"/>.\n        /// </summary>\n        /// <param name=\"providerType\">Type representing an <see cref=\"ICompressionProvider\"/>.</param>\n        /// <remarks>\n        /// Provider instances will be created using an <see cref=\"IServiceProvider\" />.\n        /// </remarks>\n        public void Add(Type providerType)\n        {\n            if (providerType == null)\n            {\n                throw new ArgumentNullException(nameof(providerType));\n            }\n\n            if (!typeof(ICompressionProvider).IsAssignableFrom(providerType))\n            {\n                throw new ArgumentException($\"The provider must implement {nameof(ICompressionProvider)}.\", nameof(providerType));\n            }\n\n            var factory = new CompressionProviderFactory(providerType);\n            Add(factory);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/CompressionProviderFactory.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// This is a placeholder for the CompressionProviderCollection that allows creating the given type via\n    /// an <see cref=\"IServiceProvider\" />.\n    /// </summary>\n    internal class CompressionProviderFactory : ICompressionProvider\n    {\n        public CompressionProviderFactory(Type providerType)\n        {\n            ProviderType = providerType;\n        }\n\n        private Type ProviderType { get; }\n\n        public ICompressionProvider CreateInstance(IServiceProvider serviceProvider)\n        {\n            if (serviceProvider == null)\n            {\n                throw new ArgumentNullException(nameof(serviceProvider));\n            }\n\n            return (ICompressionProvider)ActivatorUtilities.CreateInstance(serviceProvider, ProviderType, Type.EmptyTypes);\n        }\n\n        string ICompressionProvider.EncodingName\n        {\n            get { throw new NotSupportedException(); }\n        }\n\n        bool ICompressionProvider.SupportsFlush\n        {\n            get { throw new NotSupportedException(); }\n        }\n\n        Stream ICompressionProvider.CreateStream(Stream outputStream)\n        {\n            throw new NotSupportedException();\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/GzipCompressionProvider.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.IO.Compression;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// GZIP compression provider.\n    /// </summary>\n    public class GzipCompressionProvider : ICompressionProvider\n    {\n        /// <summary>\n        /// Creates a new instance of GzipCompressionProvider with options.\n        /// </summary>\n        /// <param name=\"options\"></param>\n        public GzipCompressionProvider(IOptions<GzipCompressionProviderOptions> options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            Options = options.Value;\n        }\n\n        private GzipCompressionProviderOptions Options { get; }\n\n        /// <inheritdoc />\n        public string EncodingName => \"gzip\";\n\n        /// <inheritdoc />\n        public bool SupportsFlush\n        {\n            get\n            {\n#if NET461\n                return false;\n#elif NETSTANDARD2_0 || NETCOREAPP2_1\n                return true;\n#else\n#error target frameworks need to be updated\n#endif\n            }\n        }\n\n        /// <inheritdoc />\n        public Stream CreateStream(Stream outputStream)\n        {\n            return new GZipStream(outputStream, Options.Level, leaveOpen: true);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/GzipCompressionProviderOptions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO.Compression;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Options for the GzipCompressionProvider\n    /// </summary>\n    public class GzipCompressionProviderOptions : IOptions<GzipCompressionProviderOptions>\n    {\n        /// <summary>\n        /// What level of compression to use for the stream. The default is Fastest.\n        /// </summary>\n        public CompressionLevel Level { get; set; } = CompressionLevel.Fastest;\n\n        /// <inheritdoc />\n        GzipCompressionProviderOptions IOptions<GzipCompressionProviderOptions>.Value => this;\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/ICompressionProvider.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Provides a specific compression implementation to compress HTTP responses.\n    /// </summary>\n    public interface ICompressionProvider\n    {\n        /// <summary>\n        /// The encoding name used in the 'Accept-Encoding' request header and 'Content-Encoding' response header.\n        /// </summary>\n        string EncodingName { get; }\n\n        /// <summary>\n        /// Indicates if the given provider supports Flush and FlushAsync. If not, compression may be disabled in some scenarios.\n        /// </summary>\n        bool SupportsFlush { get; }\n\n        /// <summary>\n        /// Create a new compression stream.\n        /// </summary>\n        /// <param name=\"outputStream\">The stream where the compressed data have to be written.</param>\n        /// <returns>The compression stream.</returns>\n        Stream CreateStream(Stream outputStream);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/IResponseCompressionProvider.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Used to examine requests and responses to see if compression should be enabled.\n    /// </summary>\n    public interface IResponseCompressionProvider\n    {\n        /// <summary>\n        /// Examines the request and selects an acceptable compression provider, if any.\n        /// </summary>\n        /// <param name=\"context\"></param>\n        /// <returns>A compression provider or null if compression should not be used.</returns>\n        ICompressionProvider GetCompressionProvider(HttpContext context);\n\n        /// <summary>\n        /// Examines the response on first write to see if compression should be used.\n        /// </summary>\n        /// <param name=\"context\"></param>\n        /// <returns></returns>\n        bool ShouldCompressResponse(HttpContext context);\n\n        /// <summary>\n        /// Examines the request to see if compression should be used for response.\n        /// </summary>\n        /// <param name=\"context\"></param>\n        /// <returns></returns>\n        bool CheckRequestAcceptsCompression(HttpContext context);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/Microsoft.AspNetCore.ResponseCompression.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <Description>ASP.NET Core middleware for HTTP Response compression.</Description>\n    <TargetFrameworks>net461;netstandard2.0;netcoreapp2.1</TargetFrameworks>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <PackageTags>aspnetcore</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Http.Extensions\" Version=\"$(MicrosoftAspNetCoreHttpExtensionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Abstractions\" Version=\"$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Options\" Version=\"$(MicrosoftExtensionsOptionsPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/Properties/AssemblyInfo.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"Microsoft.AspNetCore.ResponseCompression.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb\")]\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionBuilderExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.ResponseCompression;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection.Extensions;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the ResponseCompression middleware.\n    /// </summary>\n    public static class ResponseCompressionBuilderExtensions\n    {\n        /// <summary>\n        /// Adds middleware for dynamically compressing HTTP Responses.\n        /// </summary>\n        /// <param name=\"builder\">The <see cref=\"IApplicationBuilder\"/> instance this method extends.</param>\n        public static IApplicationBuilder UseResponseCompression(this IApplicationBuilder builder)\n        {\n            if (builder == null)\n            {\n                throw new ArgumentNullException(nameof(builder));\n            }\n\n            return builder.UseMiddleware<ResponseCompressionMiddleware>();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionDefaults.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Defaults for the ResponseCompressionMiddleware\n    /// </summary>\n    public class ResponseCompressionDefaults\n    {\n        /// <summary>\n        /// Default MIME types to compress responses for.\n        /// </summary>\n        // This list is not intended to be exhaustive, it's a baseline for the 90% case.\n        public static readonly IEnumerable<string> MimeTypes = new[]\n        {\n            // General\n            \"text/plain\",\n            // Static files\n            \"text/css\",\n            \"application/javascript\",\n            // MVC\n            \"text/html\",\n            \"application/xml\",\n            \"text/xml\",\n            \"application/json\",\n            \"text/json\",\n            // WebAssembly\n            \"application/wasm\",\n        };\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionMiddleware.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Enable HTTP response compression.\n    /// </summary>\n    public class ResponseCompressionMiddleware\n    {\n        private readonly RequestDelegate _next;\n\n        private readonly IResponseCompressionProvider _provider;\n\n\n        /// <summary>\n        /// Initialize the Response Compression middleware.\n        /// </summary>\n        /// <param name=\"next\"></param>\n        /// <param name=\"provider\"></param>\n        public ResponseCompressionMiddleware(RequestDelegate next, IResponseCompressionProvider provider)\n        {\n            if (next == null)\n            {\n                throw new ArgumentNullException(nameof(next));\n            }\n            if (provider == null)\n            {\n                throw new ArgumentNullException(nameof(provider));\n            }\n\n            _next = next;\n            _provider = provider;\n        }\n\n        /// <summary>\n        /// Invoke the middleware.\n        /// </summary>\n        /// <param name=\"context\"></param>\n        /// <returns></returns>\n        public async Task Invoke(HttpContext context)\n        {\n            if (!_provider.CheckRequestAcceptsCompression(context))\n            {\n                await _next(context);\n                return;\n            }\n\n            var bodyStream = context.Response.Body;\n            var originalBufferFeature = context.Features.Get<IHttpBufferingFeature>();\n            var originalSendFileFeature = context.Features.Get<IHttpSendFileFeature>();\n\n            var bodyWrapperStream = new BodyWrapperStream(context, bodyStream, _provider,\n                originalBufferFeature, originalSendFileFeature);\n            context.Response.Body = bodyWrapperStream;\n            context.Features.Set<IHttpBufferingFeature>(bodyWrapperStream);\n            if (originalSendFileFeature != null)\n            {\n                context.Features.Set<IHttpSendFileFeature>(bodyWrapperStream);\n            }\n\n            try\n            {\n                await _next(context);\n                // This is not disposed via a using statement because we don't want to flush the compression buffer for unhandled exceptions,\n                // that may cause secondary exceptions.\n                bodyWrapperStream.Dispose();\n            }\n            finally\n            {\n                context.Response.Body = bodyStream;\n                context.Features.Set(originalBufferFeature);\n                if (originalSendFileFeature != null)\n                {\n                    context.Features.Set(originalSendFileFeature);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionOptions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <summary>\n    /// Options for the HTTP response compression middleware.\n    /// </summary>\n    public class ResponseCompressionOptions\n    {\n        /// <summary>\n        /// Response Content-Type MIME types to compress.\n        /// </summary>\n        public IEnumerable<string> MimeTypes { get; set; }\n\n        /// <summary>\n        /// Response Content-Type MIME types to not compress.\n        /// </summary>\n        public IEnumerable<string> ExcludedMimeTypes { get; set; }\n\n        /// <summary>\n        /// Indicates if responses over HTTPS connections should be compressed. The default is 'false'.\n        /// Enabling compression on HTTPS connections may expose security problems.\n        /// </summary>\n        public bool EnableForHttps { get; set; } = false;\n\n        /// <summary>\n        /// The <see cref=\"ICompressionProvider\"/> types to use for responses.\n        /// Providers are prioritized based on the order they are added.\n        /// </summary>\n        public CompressionProviderCollection Providers { get; } = new CompressionProviderCollection();\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionProvider.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.ResponseCompression.Internal;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\nusing Microsoft.Extensions.Primitives;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.ResponseCompression\n{\n    /// <inheritdoc />\n    public class ResponseCompressionProvider : IResponseCompressionProvider\n    {\n        private readonly ICompressionProvider[] _providers;\n        private readonly HashSet<string> _mimeTypes;\n        private readonly HashSet<string> _excludedMimeTypes;\n        private readonly bool _enableForHttps;\n        private readonly ILogger _logger;\n\n        /// <summary>\n        /// If no compression providers are specified then GZip is used by default.\n        /// </summary>\n        /// <param name=\"services\">Services to use when instantiating compression providers.</param>\n        /// <param name=\"options\"></param>\n        public ResponseCompressionProvider(IServiceProvider services, IOptions<ResponseCompressionOptions> options)\n        {\n            if (services == null)\n            {\n                throw new ArgumentNullException(nameof(services));\n            }\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            var responseCompressionOptions = options.Value;\n\n            _providers = responseCompressionOptions.Providers.ToArray();\n            if (_providers.Length == 0)\n            {\n                // Use the factory so it can resolve IOptions<GzipCompressionProviderOptions> from DI.\n                _providers = new ICompressionProvider[]\n                {\n#if NETCOREAPP2_1\n                    new CompressionProviderFactory(typeof(BrotliCompressionProvider)),\n#elif NET461 || NETSTANDARD2_0\n                    // Brotli is only supported in .NET Core 2.1+\n#else\n#error Target frameworks need to be updated.\n#endif\n                    new CompressionProviderFactory(typeof(GzipCompressionProvider)),\n                };\n            }\n            for (var i = 0; i < _providers.Length; i++)\n            {\n                var factory = _providers[i] as CompressionProviderFactory;\n                if (factory != null)\n                {\n                    _providers[i] = factory.CreateInstance(services);\n                }\n            }\n\n            var mimeTypes = responseCompressionOptions.MimeTypes;\n            if (mimeTypes == null || !mimeTypes.Any())\n            {\n                mimeTypes = ResponseCompressionDefaults.MimeTypes;\n            }\n\n            _mimeTypes = new HashSet<string>(mimeTypes, StringComparer.OrdinalIgnoreCase);\n\n            _excludedMimeTypes = new HashSet<string>(\n                responseCompressionOptions.ExcludedMimeTypes ?? Enumerable.Empty<string>(),\n                StringComparer.OrdinalIgnoreCase\n            );\n\n            _enableForHttps = responseCompressionOptions.EnableForHttps;\n\n            _logger = services.GetRequiredService<ILogger<ResponseCompressionProvider>>();\n        }\n\n        /// <inheritdoc />\n        public virtual ICompressionProvider GetCompressionProvider(HttpContext context)\n        {\n            // e.g. Accept-Encoding: gzip, deflate, sdch\n            var accept = context.Request.Headers[HeaderNames.AcceptEncoding];\n\n            // Note this is already checked in CheckRequestAcceptsCompression which _should_ prevent any of these other methods from being called.\n            if (StringValues.IsNullOrEmpty(accept))\n            {\n                Debug.Assert(false, \"Duplicate check failed.\");\n                _logger.NoAcceptEncoding();\n                return null;\n            }\n\n            if (!StringWithQualityHeaderValue.TryParseList(accept, out var encodings) || !encodings.Any())\n            {\n                _logger.NoAcceptEncoding();\n                return null;\n            }\n\n            var candidates = new HashSet<ProviderCandidate>();\n\n            foreach (var encoding in encodings)\n            {\n                var encodingName = encoding.Value;\n                var quality = encoding.Quality.GetValueOrDefault(1);\n\n                if (quality < double.Epsilon)\n                {\n                    continue;\n                }\n\n                for (int i = 0; i < _providers.Length; i++)\n                {\n                    var provider = _providers[i];\n\n                    if (StringSegment.Equals(provider.EncodingName, encodingName, StringComparison.OrdinalIgnoreCase))\n                    {\n                        candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider));\n                    }\n                }\n\n                // Uncommon but valid options\n                if (StringSegment.Equals(\"*\", encodingName, StringComparison.Ordinal))\n                {\n                    for (int i = 0; i < _providers.Length; i++)\n                    {\n                        var provider = _providers[i];\n\n                        // Any provider is a candidate.\n                        candidates.Add(new ProviderCandidate(provider.EncodingName, quality, i, provider));\n                    }\n\n                    break;\n                }\n\n                if (StringSegment.Equals(\"identity\", encodingName, StringComparison.OrdinalIgnoreCase))\n                {\n                    // We add 'identity' to the list of \"candidates\" with a very low priority and no provider.\n                    // This will allow it to be ordered based on its quality (and priority) later in the method.\n                    candidates.Add(new ProviderCandidate(encodingName.Value, quality, priority: int.MaxValue, provider: null));\n                }\n            }\n\n            ICompressionProvider selectedProvider = null;\n            if (candidates.Count <= 1)\n            {\n                selectedProvider = candidates.FirstOrDefault().Provider;\n            }\n            else\n            {\n                selectedProvider = candidates\n                    .OrderByDescending(x => x.Quality)\n                    .ThenBy(x => x.Priority)\n                    .First().Provider;\n            }\n\n            if (selectedProvider == null)\n            {\n                // \"identity\" would match as a candidate but not have a provider implementation\n                _logger.NoCompressionProvider();\n                return null;\n            }\n\n            _logger.CompressingWith(selectedProvider.EncodingName);\n            return selectedProvider;\n        }\n\n        /// <inheritdoc />\n        public virtual bool ShouldCompressResponse(HttpContext context)\n        {\n            if (context.Response.Headers.ContainsKey(HeaderNames.ContentRange))\n            {\n                _logger.NoCompressionDueToHeader(HeaderNames.ContentRange);\n                return false;\n            }\n\n            if (context.Response.Headers.ContainsKey(HeaderNames.ContentEncoding))\n            {\n                _logger.NoCompressionDueToHeader(HeaderNames.ContentEncoding);\n                return false;\n            }\n\n            var mimeType = context.Response.ContentType;\n\n            if (string.IsNullOrEmpty(mimeType))\n            {\n                _logger.NoCompressionForContentType(mimeType);\n                return false;\n            }\n\n            var separator = mimeType.IndexOf(';');\n            if (separator >= 0)\n            {\n                // Remove the content-type optional parameters\n                mimeType = mimeType.Substring(0, separator);\n                mimeType = mimeType.Trim();\n            }\n\n            var shouldCompress = ShouldCompressExact(mimeType) //check exact match type/subtype\n                ?? ShouldCompressPartial(mimeType) //check partial match type/*\n                ?? _mimeTypes.Contains(\"*/*\"); //check wildcard */*\n\n            if (shouldCompress)\n            {\n                _logger.ShouldCompressResponse();  // Trace, there will be more logs\n                return true;\n            }\n\n            _logger.NoCompressionForContentType(mimeType);\n            return false;\n        }\n\n        /// <inheritdoc />\n        public bool CheckRequestAcceptsCompression(HttpContext context)\n        {\n            if (context.Request.IsHttps && !_enableForHttps)\n            {\n                _logger.NoCompressionForHttps();\n                return false;\n            }\n\n            if (string.IsNullOrEmpty(context.Request.Headers[HeaderNames.AcceptEncoding]))\n            {\n                _logger.NoAcceptEncoding();\n                return false;\n            }\n\n            _logger.RequestAcceptsCompression(); // Trace, there will be more logs\n            return true;\n        }\n\n        private bool? ShouldCompressExact(string mimeType)\n        {\n            //Check excluded MIME types first, then included\n            if (_excludedMimeTypes.Contains(mimeType))\n            {\n                return false;\n            }\n\n            if (_mimeTypes.Contains(mimeType))\n            {\n                return true;\n            }\n\n            return null;\n        }\n\n        private bool? ShouldCompressPartial(string mimeType)\n        {\n            int? slashPos = mimeType?.IndexOf('/');\n\n            if (slashPos >= 0)\n            {\n                string partialMimeType = mimeType.Substring(0, slashPos.Value) + \"/*\";\n                return ShouldCompressExact(partialMimeType);\n            }\n\n            return null;\n        }\n\n        private readonly struct ProviderCandidate : IEquatable<ProviderCandidate>\n        {\n            public ProviderCandidate(string encodingName, double quality, int priority, ICompressionProvider provider)\n            {\n                EncodingName = encodingName;\n                Quality = quality;\n                Priority = priority;\n                Provider = provider;\n            }\n\n            public string EncodingName { get; }\n\n            public double Quality { get; }\n\n            public int Priority { get; }\n\n            public ICompressionProvider Provider { get; }\n\n            public bool Equals(ProviderCandidate other)\n            {\n                return string.Equals(EncodingName, other.EncodingName, StringComparison.OrdinalIgnoreCase);\n            }\n\n            public override bool Equals(object obj)\n            {\n                return obj is ProviderCandidate candidate && Equals(candidate);\n            }\n\n            public override int GetHashCode()\n            {\n                return StringComparer.OrdinalIgnoreCase.GetHashCode(EncodingName);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionServicesExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.ResponseCompression;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection.Extensions;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the ResponseCompression middleware.\n    /// </summary>\n    public static class ResponseCompressionServicesExtensions\n    {\n        /// <summary>\n        /// Add response compression services.\n        /// </summary>\n        /// <param name=\"services\">The <see cref=\"IServiceCollection\"/> for adding services.</param>\n        /// <returns></returns>\n        public static IServiceCollection AddResponseCompression(this IServiceCollection services)\n        {\n            if (services == null)\n            {\n                throw new ArgumentNullException(nameof(services));\n            }\n\n            services.TryAddSingleton<IResponseCompressionProvider, ResponseCompressionProvider>();\n            return services;\n        }\n\n        /// <summary>\n        /// Add response compression services and configure the related options.\n        /// </summary>\n        /// <param name=\"services\">The <see cref=\"IServiceCollection\"/> for adding services.</param>\n        /// <param name=\"configureOptions\">A delegate to configure the <see cref=\"ResponseCompressionOptions\"/>.</param>\n        /// <returns></returns>\n        public static IServiceCollection AddResponseCompression(this IServiceCollection services, Action<ResponseCompressionOptions> configureOptions)\n        {\n            if (services == null)\n            {\n                throw new ArgumentNullException(nameof(services));\n            }\n            if (configureOptions == null)\n            {\n                throw new ArgumentNullException(nameof(configureOptions));\n            }\n\n            services.Configure(configureOptions);\n            services.TryAddSingleton<IResponseCompressionProvider, ResponseCompressionProvider>();\n            return services;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/baseline.netcore.json",
    "content": "{\n  \"AssemblyIdentity\": \"Microsoft.AspNetCore.ResponseCompression, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60\",\n  \"Types\": [\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.ResponseCompressionBuilderExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseResponseCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.ResponseCompressionServicesExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddResponseCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddResponseCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\"\n            },\n            {\n              \"Name\": \"configureOptions\",\n              \"Type\": \"System.Action<Microsoft.AspNetCore.ResponseCompression.ResponseCompressionOptions>\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.CompressionProviderCollection\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"BaseType\": \"System.Collections.ObjectModel.Collection<Microsoft.AspNetCore.ResponseCompression.ICompressionProvider>\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Add<T0>\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": [\n            {\n              \"ParameterName\": \"TCompressionProvider\",\n              \"ParameterPosition\": 0,\n              \"BaseTypeOrInterfaces\": [\n                \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\"\n              ]\n            }\n          ]\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Add\",\n          \"Parameters\": [\n            {\n              \"Name\": \"providerType\",\n              \"Type\": \"System.Type\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.GzipCompressionProvider\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [\n        \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\"\n      ],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_EncodingName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Sealed\": true,\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_SupportsFlush\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Sealed\": true,\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"CreateStream\",\n          \"Parameters\": [\n            {\n              \"Name\": \"outputStream\",\n              \"Type\": \"System.IO.Stream\"\n            }\n          ],\n          \"ReturnType\": \"System.IO.Stream\",\n          \"Sealed\": true,\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.ResponseCompression.GzipCompressionProviderOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.GzipCompressionProviderOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [\n        \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.ResponseCompression.GzipCompressionProviderOptions>\"\n      ],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Level\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.IO.Compression.CompressionLevel\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_Level\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.IO.Compression.CompressionLevel\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Interface\",\n      \"Abstract\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_EncodingName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_SupportsFlush\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"CreateStream\",\n          \"Parameters\": [\n            {\n              \"Name\": \"outputStream\",\n              \"Type\": \"System.IO.Stream\"\n            }\n          ],\n          \"ReturnType\": \"System.IO.Stream\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Interface\",\n      \"Abstract\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"GetCompressionProvider\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"ShouldCompressResponse\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"CheckRequestAcceptsCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ResponseCompressionDefaults\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"MimeTypes\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IEnumerable<System.String>\",\n          \"Static\": true,\n          \"ReadOnly\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"provider\",\n              \"Type\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ResponseCompressionOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_MimeTypes\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IEnumerable<System.String>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_MimeTypes\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Collections.Generic.IEnumerable<System.String>\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_EnableForHttps\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_EnableForHttps\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Providers\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.AspNetCore.ResponseCompression.CompressionProviderCollection\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ResponseCompressionProvider\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [\n        \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\"\n      ],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"GetCompressionProvider\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"ShouldCompressResponse\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"CheckRequestAcceptsCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"Sealed\": true,\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"System.IServiceProvider\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.ResponseCompression.ResponseCompressionOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    }\n  ]\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/baseline.netframework.json",
    "content": "{\n  \"AssemblyIdentity\": \"Microsoft.AspNetCore.ResponseCompression, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60\",\n  \"Types\": [\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.ResponseCompressionBuilderExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseResponseCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"builder\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.ResponseCompressionServicesExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddResponseCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddResponseCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\"\n            },\n            {\n              \"Name\": \"configureOptions\",\n              \"Type\": \"System.Action<Microsoft.AspNetCore.ResponseCompression.ResponseCompressionOptions>\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.Extensions.DependencyInjection.IServiceCollection\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.CompressionProviderCollection\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"BaseType\": \"System.Collections.ObjectModel.Collection<Microsoft.AspNetCore.ResponseCompression.ICompressionProvider>\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Add<T0>\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": [\n            {\n              \"ParameterName\": \"TCompressionProvider\",\n              \"ParameterPosition\": 0,\n              \"BaseTypeOrInterfaces\": [\n                \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\"\n              ]\n            }\n          ]\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Add\",\n          \"Parameters\": [\n            {\n              \"Name\": \"providerType\",\n              \"Type\": \"System.Type\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.GzipCompressionProvider\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [\n        \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\"\n      ],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_EncodingName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"Sealed\": true,\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_SupportsFlush\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Sealed\": true,\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"CreateStream\",\n          \"Parameters\": [\n            {\n              \"Name\": \"outputStream\",\n              \"Type\": \"System.IO.Stream\"\n            }\n          ],\n          \"ReturnType\": \"System.IO.Stream\",\n          \"Sealed\": true,\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.ResponseCompression.GzipCompressionProviderOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.GzipCompressionProviderOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [\n        \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.ResponseCompression.GzipCompressionProviderOptions>\"\n      ],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Level\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.IO.Compression.CompressionLevel\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_Level\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.IO.Compression.CompressionLevel\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Interface\",\n      \"Abstract\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_EncodingName\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.String\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_SupportsFlush\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"CreateStream\",\n          \"Parameters\": [\n            {\n              \"Name\": \"outputStream\",\n              \"Type\": \"System.IO.Stream\"\n            }\n          ],\n          \"ReturnType\": \"System.IO.Stream\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Interface\",\n      \"Abstract\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"GetCompressionProvider\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"ShouldCompressResponse\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"CheckRequestAcceptsCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ResponseCompressionDefaults\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"MimeTypes\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IEnumerable<System.String>\",\n          \"Static\": true,\n          \"ReadOnly\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"provider\",\n              \"Type\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ResponseCompressionOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_MimeTypes\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IEnumerable<System.String>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_MimeTypes\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Collections.Generic.IEnumerable<System.String>\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_EnableForHttps\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Boolean\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_EnableForHttps\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Providers\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.AspNetCore.ResponseCompression.CompressionProviderCollection\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.ResponseCompression.ResponseCompressionProvider\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [\n        \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\"\n      ],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"GetCompressionProvider\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.ResponseCompression.ICompressionProvider\",\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"ShouldCompressResponse\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"CheckRequestAcceptsCompression\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Boolean\",\n          \"Sealed\": true,\n          \"Virtual\": true,\n          \"ImplementedInterface\": \"Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"services\",\n              \"Type\": \"System.IServiceProvider\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.ResponseCompression.ResponseCompressionOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    }\n  ]\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.ResponseCompression/internal/ResponseCompressionLoggingExtensions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.Extensions.Logging;\n\nnamespace Microsoft.AspNetCore.ResponseCompression.Internal\n{\n    internal static class ResponseCompressionLoggingExtensions\n    {\n        private static readonly Action<ILogger, Exception> _noAcceptEncoding;\n        private static readonly Action<ILogger, Exception> _noCompressionForHttps;\n        private static readonly Action<ILogger, Exception> _requestAcceptsCompression;\n        private static readonly Action<ILogger, string, Exception> _noCompressionDueToHeader;\n        private static readonly Action<ILogger, string, Exception> _noCompressionForContentType;\n        private static readonly Action<ILogger, Exception> _shouldCompressResponse;\n        private static readonly Action<ILogger, Exception> _noCompressionProvider;\n        private static readonly Action<ILogger, string, Exception> _compressWith;\n\n        static ResponseCompressionLoggingExtensions()\n        {\n            _noAcceptEncoding = LoggerMessage.Define(LogLevel.Debug, 1, \"No response compression available, the Accept-Encoding header is missing or invalid.\");\n            _noCompressionForHttps = LoggerMessage.Define(LogLevel.Debug, 2, \"No response compression available for HTTPS requests. See ResponseCompressionOptions.EnableForHttps.\");\n            _requestAcceptsCompression = LoggerMessage.Define(LogLevel.Trace, 3, \"This request accepts compression.\");\n            _noCompressionDueToHeader = LoggerMessage.Define<string>(LogLevel.Debug, 4, \"Response compression disabled due to the {header} header.\");\n            _noCompressionForContentType = LoggerMessage.Define<string>(LogLevel.Debug, 5, \"Response compression is not enabled for the Content-Type '{header}'.\");\n            _shouldCompressResponse = LoggerMessage.Define(LogLevel.Trace, 6, \"Response compression is available for this Content-Type.\");\n            _noCompressionProvider = LoggerMessage.Define(LogLevel.Debug, 7, \"No matching response compression provider found.\");\n            _compressWith = LoggerMessage.Define<string>(LogLevel.Debug, 8, \"The response will be compressed with '{provider}'.\");\n        }\n\n        public static void NoAcceptEncoding(this ILogger logger)\n        {\n            _noAcceptEncoding(logger, null);\n        }\n\n        public static void NoCompressionForHttps(this ILogger logger)\n        {\n            _noCompressionForHttps(logger, null);\n        }\n\n        public static void RequestAcceptsCompression(this ILogger logger)\n        {\n            _requestAcceptsCompression(logger, null);\n        }\n\n        public static void NoCompressionDueToHeader(this ILogger logger, string header)\n        {\n            _noCompressionDueToHeader(logger, header, null);\n        }\n\n        public static void NoCompressionForContentType(this ILogger logger, string header)\n        {\n            _noCompressionForContentType(logger, header, null);\n        }\n\n        public static void ShouldCompressResponse(this ILogger logger)\n        {\n            _shouldCompressResponse(logger, null);\n        }\n\n        public static void NoCompressionProvider(this ILogger logger)\n        {\n            _noCompressionProvider(logger, null);\n        }\n\n        public static void CompressingWith(this ILogger logger, string provider)\n        {\n            _compressWith(logger, provider, null);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/ApacheModRewriteOptionsExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Microsoft.Extensions.FileProviders;\n\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    /// <summary>\n    /// Extensions for adding Apache mod_rewrite rules to <see cref=\"RewriteOptions\"/>\n    /// </summary>\n    public static class ApacheModRewriteOptionsExtensions\n    {\n        /// <summary>\n        /// Add rules from an Apache mod_rewrite file\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/></param>\n        /// <param name=\"fileProvider\">The <see cref=\"IFileProvider\"/> </param>\n        /// <param name=\"filePath\">The path to the file containing mod_rewrite rules.</param>\n        public static RewriteOptions AddApacheModRewrite(this RewriteOptions options, IFileProvider fileProvider, string filePath)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            if (fileProvider == null)\n            {\n                throw new ArgumentNullException(nameof(fileProvider));\n            }\n\n            var fileInfo = fileProvider.GetFileInfo(filePath);\n            using (var stream = fileInfo.CreateReadStream())\n            {\n                return options.AddApacheModRewrite(new StreamReader(stream));\n            }\n        }\n\n        /// <summary>\n        /// Add rules from an Apache mod_rewrite file\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/></param>\n        /// <param name=\"reader\">A stream of mod_rewrite rules.</param>\n        public static RewriteOptions AddApacheModRewrite(this RewriteOptions options, TextReader reader)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            if (reader == null)\n            {\n                throw new ArgumentNullException(nameof(reader));\n            }\n            var rules = new FileParser().Parse(reader);\n\n            foreach (var rule in rules)\n            {\n                options.Rules.Add(rule);\n            }\n            return options;\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Extensions/RewriteMiddlewareLoggingExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.Extensions.Logging;\n\nnamespace Microsoft.AspNetCore.Rewrite.Logging\n{\n    internal static class RewriteMiddlewareLoggingExtensions\n    {\n        private static readonly Action<ILogger, string, Exception> _requestContinueResults;\n        private static readonly Action<ILogger, string, int, Exception> _requestResponseComplete;\n        private static readonly Action<ILogger, string, Exception> _requestStopRules;\n        private static readonly Action<ILogger, string, Exception> _urlRewriteDidNotMatchRule;\n        private static readonly Action<ILogger, string, Exception> _urlRewriteMatchedRule;\n        private static readonly Action<ILogger, Exception> _modRewriteDidNotMatchRule;\n        private static readonly Action<ILogger, Exception> _modRewriteMatchedRule;\n        private static readonly Action<ILogger, Exception> _redirectedToHttps;\n        private static readonly Action<ILogger, Exception> _redirectedToWww;\n        private static readonly Action<ILogger, string, Exception> _redirectSummary;\n        private static readonly Action<ILogger, string, Exception> _rewriteSummary;\n        private static readonly Action<ILogger, string, Exception> _abortedRequest;\n        private static readonly Action<ILogger, string, Exception> _customResponse;\n\n        static RewriteMiddlewareLoggingExtensions()\n        {\n            _requestContinueResults = LoggerMessage.Define<string>(\n                            LogLevel.Debug,\n                            1,\n                            \"Request is continuing in applying rules. Current url is {currentUrl}\");\n\n            _requestResponseComplete = LoggerMessage.Define<string, int>(\n                            LogLevel.Debug,\n                            2,\n                            \"Request is done processing. Location header '{Location}' with status code '{StatusCode}'.\");\n\n            _requestStopRules = LoggerMessage.Define<string>(\n                            LogLevel.Debug,\n                            3,\n                            \"Request is done applying rules. Url was rewritten to {rewrittenUrl}\");\n\n            _urlRewriteDidNotMatchRule = LoggerMessage.Define<string>(\n                            LogLevel.Debug,\n                            4,\n                            \"Request did not match current rule '{Name}'.\");\n\n            _urlRewriteMatchedRule = LoggerMessage.Define<string>(\n                            LogLevel.Debug,\n                            5,\n                            \"Request matched current UrlRewriteRule '{Name}'.\");\n\n            _modRewriteDidNotMatchRule = LoggerMessage.Define(\n                            LogLevel.Debug,\n                            6,\n                            \"Request matched current ModRewriteRule.\");\n\n            _modRewriteMatchedRule = LoggerMessage.Define(\n                            LogLevel.Debug,\n                            7,\n                            \"Request matched current ModRewriteRule.\");\n\n            _redirectedToHttps = LoggerMessage.Define(\n                            LogLevel.Information,\n                            8,\n                            \"Request redirected to HTTPS\");\n\n            _redirectSummary = LoggerMessage.Define<string>(\n                            LogLevel.Information,\n                            9,\n                            \"Request was redirected to {redirectedUrl}\");\n\n            _rewriteSummary = LoggerMessage.Define<string>(\n                            LogLevel.Information,\n                            10,\n                            \"Request was rewritten to {rewrittenUrl}\");\n\n            _abortedRequest = LoggerMessage.Define<string>(\n                            LogLevel.Debug,\n                            11,\n                            \"Request to {requestedUrl} was aborted\");\n\n            _customResponse = LoggerMessage.Define<string>(\n                            LogLevel.Debug,\n                            12,\n                            \"Request to {requestedUrl} was ended\");\n\n            _redirectedToWww = LoggerMessage.Define(\n                            LogLevel.Information,\n                            13,\n                            \"Request redirected to www\");\n        }\n\n        public static void RewriteMiddlewareRequestContinueResults(this ILogger logger, string currentUrl)\n        {\n            _requestContinueResults(logger, currentUrl, null);\n        }\n\n        public static void RewriteMiddlewareRequestResponseComplete(this ILogger logger, string location, int statusCode)\n        {\n            _requestResponseComplete(logger, location, statusCode, null);\n        }\n\n        public static void RewriteMiddlewareRequestStopRules(this ILogger logger, string rewrittenUrl)\n        {\n            _requestStopRules(logger, rewrittenUrl, null);\n        }\n\n        public static void UrlRewriteDidNotMatchRule(this ILogger logger, string name)\n        {\n            _urlRewriteDidNotMatchRule(logger, name, null);\n        }\n\n        public static void UrlRewriteMatchedRule(this ILogger logger, string name)\n        {\n            _urlRewriteMatchedRule(logger, name, null);\n        }\n\n        public static void ModRewriteDidNotMatchRule(this ILogger logger)\n        {\n            _modRewriteDidNotMatchRule(logger, null);\n        }\n\n        public static void ModRewriteMatchedRule(this ILogger logger)\n        {\n            _modRewriteMatchedRule(logger, null);\n        }\n\n        public static void RedirectedToHttps(this ILogger logger)\n        {\n            _redirectedToHttps(logger, null);\n        }\n\n        public static void RedirectedToWww(this ILogger logger)\n        {\n            _redirectedToWww(logger, null);\n        }\n\n        public static void RedirectedSummary(this ILogger logger, string redirectedUrl)\n        {\n            _redirectSummary(logger, redirectedUrl, null);\n        }\n\n        public static void RewriteSummary(this ILogger logger, string rewrittenUrl)\n        {\n            _rewriteSummary(logger, rewrittenUrl, null);\n        }\n\n        public static void AbortedRequest(this ILogger logger, string requestedUrl)\n        {\n            _abortedRequest(logger, requestedUrl, null);\n        }\n\n        public static void CustomResponse(this ILogger logger, string requestedUrl)\n        {\n            _customResponse(logger, requestedUrl, null);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/IISUrlRewriteOptionsExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Microsoft.Extensions.FileProviders;\n\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    /// <summary>\n    /// Extensions for adding IIS Url Rewrite rules to <see cref=\"RewriteOptions\"/>\n    /// </summary>\n    public static class IISUrlRewriteOptionsExtensions\n    {\n        /// <summary>\n        /// Add rules from a IIS config file containing Url Rewrite rules\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/></param>\n        /// <param name=\"fileProvider\">The <see cref=\"IFileProvider\"/> </param>\n        /// <param name=\"filePath\">The path to the file containing UrlRewrite rules.</param>\n        public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, IFileProvider fileProvider, string filePath)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            if (fileProvider == null)\n            {\n                throw new ArgumentNullException(nameof(fileProvider));\n            }\n\n            var file = fileProvider.GetFileInfo(filePath);\n\n            using (var stream = file.CreateReadStream())\n            {\n                return AddIISUrlRewrite(options, new StreamReader(stream));\n            }\n        }\n\n        /// <summary>\n        /// Add rules from a IIS config file containing Url Rewrite rules\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/></param>\n        /// <param name=\"reader\">The text reader stream.</param>\n        public static RewriteOptions AddIISUrlRewrite(this RewriteOptions options, TextReader reader)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            if (reader == null)\n            {\n                throw new ArgumentException(nameof(reader));\n            }\n\n            var rules = new UrlRewriteFileParser().Parse(reader);\n\n            foreach (var rule in rules)\n            {\n                options.Rules.Add(rule);\n            }\n\n            return options;\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/IRule.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    /// <summary>\n    /// Represents a rule.\n    /// </summary>\n    public interface IRule\n    {\n        /// <summary>\n        /// Applies the rule.\n        /// Implementations of ApplyRule should set the value for <see cref=\"RewriteContext.Result\"/>\n        /// (defaults to RuleResult.ContinueRules)\n        /// </summary>\n        /// <param name=\"context\"></param>\n        void ApplyRule(RewriteContext context);\n    }\n}\n\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ApacheModRewriteRule.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Rewrite.Logging;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public class ApacheModRewriteRule : IRule\n    {\n        public UrlMatch InitialMatch { get; }\n        public IList<Condition> Conditions { get; }\n        public IList<UrlAction> Actions { get; }\n\n        public ApacheModRewriteRule(UrlMatch initialMatch, IList<Condition> conditions, IList<UrlAction> urlActions)\n        {\n            Conditions = conditions;\n            InitialMatch = initialMatch;\n            Actions = urlActions;\n        }\n\n        public virtual void ApplyRule(RewriteContext context)\n        {\n            // 1. Figure out which section of the string to match for the initial rule.\n            var initMatchRes = InitialMatch.Evaluate(context.HttpContext.Request.Path, context);\n\n            if (!initMatchRes.Success)\n            {\n                context.Logger?.ModRewriteDidNotMatchRule();\n                return;\n            }\n\n            BackReferenceCollection condBackReferences = null;\n            if (Conditions != null)\n            {\n                var condResult = ConditionEvaluator.Evaluate(Conditions, context, initMatchRes.BackReferences);\n                if (!condResult.Success)\n                {\n                    context.Logger?.ModRewriteDidNotMatchRule();\n                    return;\n                }\n            }\n\n            // At this point, we know our rule passed, first apply pre conditions,\n            // which can modify things like the cookie or env, and then apply the action\n            context.Logger?.ModRewriteMatchedRule();\n\n            foreach (var action in Actions)\n            {\n                action.ApplyAction(context, initMatchRes?.BackReferences, condBackReferences);\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/Condition.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public class Condition\n    {\n        public Pattern Input { get; set; }\n        public UrlMatch Match { get; set; }\n        public bool OrNext { get; set; }\n\n        public MatchResults Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            var pattern = Input.Evaluate(context, ruleBackReferences, conditionBackReferences);\n            return Match.Evaluate(pattern, context);\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ConditionEvaluator.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public static class ConditionEvaluator\n    {\n        public static MatchResults Evaluate(IEnumerable<Condition> conditions, RewriteContext context, BackReferenceCollection backReferences)\n        {\n            return Evaluate(conditions, context, backReferences, trackAllCaptures: false);\n        }\n\n        public static MatchResults Evaluate(IEnumerable<Condition> conditions, RewriteContext context, BackReferenceCollection backReferences, bool trackAllCaptures)\n        {\n            BackReferenceCollection prevBackReferences = null;\n            MatchResults condResult = null;\n            var orSucceeded = false;\n            foreach (var condition in conditions)\n            {\n                if (orSucceeded && condition.OrNext)\n                {\n                    continue;\n                }\n                else if (orSucceeded)\n                {\n                    orSucceeded = false;\n                    continue;\n                }\n\n                condResult = condition.Evaluate(context, backReferences, prevBackReferences);\n                var currentBackReferences = condResult.BackReferences;\n                if (condition.OrNext)\n                {\n                    orSucceeded = condResult.Success;\n                }\n                else if (!condResult.Success)\n                {\n                    return condResult;\n                }\n\n                if (condResult.Success && trackAllCaptures && prevBackReferences != null)\n                {\n                    prevBackReferences.Add(currentBackReferences);\n                    currentBackReferences = prevBackReferences;\n                }\n\n                prevBackReferences = currentBackReferences;\n            }\n\n            return new MatchResults { BackReferences = prevBackReferences, Success = condResult.Success };\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ConditionPatternParser.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Globalization;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    /// <summary>\n    /// Parses the \"CondPattern\" portion of the RewriteCond. \n    /// RewriteCond TestString CondPattern\n    /// </summary>\n    public class ConditionPatternParser\n    {\n        private const char Not = '!';\n        private const char Dash = '-';\n        private const char Less = '<';\n        private const char Greater = '>';\n        private const char EqualSign = '=';\n\n        /// <summary>\n        /// Given a CondPattern, create a ParsedConditionExpression, containing the type of operation\n        /// and value.\n        /// ParsedConditionExpression is an intermediary object, which will be made into a ConditionExpression\n        /// once the flags are parsed.\n        /// </summary>\n        /// <param name=\"condition\">The CondPattern portion of a mod_rewrite RewriteCond.</param>\n        /// <returns>A new parsed condition.</returns>\n        public ParsedModRewriteInput ParseActionCondition(string condition)\n        {\n            if (condition == null)\n            {\n                condition = string.Empty;\n            }\n            var context = new ParserContext(condition);\n            var results = new ParsedModRewriteInput();\n            if (!context.Next())\n            {\n                throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(condition, context.Index));\n            }\n\n            // If we hit a !, invert the condition\n            if (context.Current == Not)\n            {\n                results.Invert = true;\n                if (!context.Next())\n                {\n                    // Dangling !\n                    throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(condition, context.Index));\n                }\n            }\n\n            // Control Block for strings. Set the operation and type fields based on the sign \n            // Switch on current character\n            switch (context.Current)\n            {\n                case Greater:\n                    if (!context.Next())\n                    {\n                        // Dangling \">\"\n                        throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(condition, context.Index));\n                    }\n                    if (context.Current == EqualSign)\n                    {\n                        if (!context.Next())\n                        {\n                            // Dangling \">=\"\n                            throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(condition, context.Index));\n                        }\n                        results.OperationType = OperationType.GreaterEqual;\n                        results.ConditionType = ConditionType.StringComp;\n                    }\n                    else\n                    {\n                        results.OperationType = OperationType.Greater;\n                        results.ConditionType = ConditionType.StringComp;\n                    }\n                    break;\n                case Less:\n                    if (!context.Next())\n                    {\n                        // Dangling \"<\"\n                        throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(condition, context.Index));\n                    }\n                    if (context.Current == EqualSign)\n                    {\n                        if (!context.Next())\n                        {\n                            // Dangling \"<=\"\n                            throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(condition, context.Index));\n                        }\n                        results.OperationType = OperationType.LessEqual;\n                        results.ConditionType = ConditionType.StringComp;\n                    }\n                    else\n                    {\n                        results.OperationType = OperationType.Less;\n                        results.ConditionType = ConditionType.StringComp;\n                    }\n                    break;\n                case EqualSign:\n                    if (!context.Next())\n                    {\n                        // Dangling \"=\"\n                        throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(condition, context.Index));\n                    }\n                    results.OperationType = OperationType.Equal;\n                    results.ConditionType = ConditionType.StringComp;\n                    break;\n                case Dash:\n                    results = ParseProperty(context, results.Invert);\n                    if (results.ConditionType == ConditionType.PropertyTest)\n                    {\n                        return results;\n                    }\n                    context.Next();\n                    break;\n                default:\n                    results.ConditionType = ConditionType.Regex;\n                    break;\n            }\n\n            // Capture the rest of the string guarantee validity.\n            results.Operand = condition.Substring(context.GetIndex());\n            if (IsValidActionCondition(results))\n            {\n                return results;\n            }\n            else\n            {\n                throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(condition, context.Index));\n            }\n        }\n\n        /// <summary>\n        /// Given that the current index is a property (ex checks for directory or regular files), create a\n        /// new ParsedConditionExpression with the appropriate property operation.\n        /// </summary>\n        /// <param name=\"context\"></param>\n        /// <param name=\"invert\"></param>\n        /// <returns></returns>\n        private static ParsedModRewriteInput ParseProperty(ParserContext context, bool invert)\n        {\n            if (!context.Next())\n            {\n                throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));\n            }\n\n            switch (context.Current)\n            {\n                case 'd':\n                    return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.Directory, operand: null);\n                case 'f':\n                    return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.RegularFile, operand: null);\n                case 'F':\n                    return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.ExistingFile, operand: null);\n                case 'h':\n                case 'L':\n                    return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.SymbolicLink, operand: null);\n                case 's':\n                    return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.Size, operand: null);\n                case 'U':\n                    return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.ExistingUrl, operand: null);\n                case 'x':\n                    return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.Executable, operand: null);\n                case 'e':\n                    if (!context.Next() || context.Current != 'q')\n                    {\n                        // Illegal statement.\n                        throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));\n                    }\n                    return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.Equal, operand: null);\n                case 'g':\n                    if (!context.Next())\n                    {\n                        throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));\n                    }\n                    switch (context.Current)\n                    {\n                        case 't':\n                            return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.Greater, operand: null);\n                        case 'e':\n                            return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.GreaterEqual, operand: null);\n                        default:\n                            throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));\n                    }\n                case 'l':\n                    // name conflict with -l and -lt/-le, so the assumption is if there is no \n                    // charcters after -l, we assume it a symbolic link\n                    if (!context.Next())\n                    {\n                        return new ParsedModRewriteInput(invert, ConditionType.PropertyTest, OperationType.SymbolicLink, operand: null);\n                    }\n                    switch (context.Current)\n                    {\n                        case 't':\n                            return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.Less, operand: null);\n                        case 'e':\n                            return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.LessEqual, operand: null);\n                        default:\n                            throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));\n                    }\n                case 'n':\n                    if (!context.Next() || context.Current != 'e')\n                    {\n                        throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));\n                    }\n                    return new ParsedModRewriteInput(invert, ConditionType.IntComp, OperationType.NotEqual, operand: null);\n                default:\n                    throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(context.Template, context.Index));\n            }\n        }\n\n        private static bool IsValidActionCondition(ParsedModRewriteInput results)\n        {\n            if (results.ConditionType == ConditionType.IntComp)\n            {\n                // If the type is an integer, verify operand is actually an int\n                int res;\n                if (!int.TryParse(results.Operand, NumberStyles.None, CultureInfo.InvariantCulture, out res))\n                {\n                    return false;\n                }\n            }\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ConditionType.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public enum ConditionType\n    {\n        Regex,\n        PropertyTest,\n        StringComp,\n        IntComp\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/CookieActionFactory.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Globalization;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public class CookieActionFactory\n    {\n        /// <summary>\n        ///  Creates a <see cref=\"ChangeCookieAction\" /> <see href=\"https://httpd.apache.org/docs/current/rewrite/flags.html#flag_co\" /> for details.\n        /// </summary>\n        /// <param name=\"flagValue\">The flag</param>\n        /// <returns>The action</returns>\n        public ChangeCookieAction Create(string flagValue)\n        {\n            if (string.IsNullOrEmpty(flagValue))\n            {\n                throw new ArgumentException(nameof(flagValue));\n            }\n\n            var i = 0;\n            var separator = ':';\n            if (flagValue[0] == ';')\n            {\n                separator = ';';\n                i++;\n            }\n\n            ChangeCookieAction action = null;\n            var currentField = Fields.Name;\n            var start = i;\n            for (; i < flagValue.Length; i++)\n            {\n                if (flagValue[i] == separator)\n                {\n                    var length = i - start;\n                    SetActionOption(flagValue.Substring(start, length).Trim(), currentField, ref action);\n\n                    currentField++;\n                    start = i + 1;\n                }\n            }\n\n            if (i != start)\n            {\n                SetActionOption(flagValue.Substring(start).Trim(new[] { ' ', separator }), currentField, ref action);\n            }\n\n            if (currentField < Fields.Domain)\n            {\n                throw new FormatException(Resources.FormatError_InvalidChangeCookieFlag(flagValue));\n            }\n\n            return action;\n        }\n\n        private static void SetActionOption(string value, Fields tokenType, ref ChangeCookieAction action)\n        {\n            switch (tokenType)\n            {\n                case Fields.Name:\n                    action = new ChangeCookieAction(value);\n                    break;\n                case Fields.Value:\n                    action.Value = value;\n                    break;\n                case Fields.Domain:\n                    // despite what spec says, an empty domain field is allowed in mod_rewrite\n                    // by specifying NAME:VALUE:;\n                    action.Domain = string.IsNullOrEmpty(value) || value == \";\"\n                        ? null\n                        : value;\n                    break;\n                case Fields.Lifetime:\n                    if (string.IsNullOrEmpty(value))\n                    {\n                        break;\n                    }\n\n                    uint minutes;\n                    if (!uint.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out minutes))\n                    {\n                        throw new FormatException(Resources.FormatError_CouldNotParseInteger(value));\n                    }\n\n                    action.Lifetime = TimeSpan.FromMinutes(minutes);\n                    break;\n                case Fields.Path:\n                    action.Path = value;\n                    break;\n                case Fields.Secure:\n                    action.Secure = \"secure\".Equals(value, StringComparison.OrdinalIgnoreCase)\n                        || \"true\".Equals(value, StringComparison.OrdinalIgnoreCase)\n                        || value == \"1\";\n                    break;\n                case Fields.HttpOnly:\n                    action.HttpOnly = \"httponly\".Equals(value, StringComparison.OrdinalIgnoreCase)\n                        || \"true\".Equals(value, StringComparison.OrdinalIgnoreCase)\n                        || value == \"1\";\n                    break;\n            }\n        }\n\n        // order matters\n        // see https://httpd.apache.org/docs/current/rewrite/flags.html#flag_co\n        private enum Fields\n        {\n            Name,\n            Value,\n            Domain,\n            Lifetime,\n            Path,\n            Secure,\n            HttpOnly\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/FileParser.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public class FileParser\n    {\n        public IList<IRule> Parse(TextReader input)\n        {\n            string line;\n            var rules = new List<IRule>();\n            var builder = new RuleBuilder();\n            var lineNum = 0;\n\n            // parsers\n            var testStringParser = new TestStringParser();\n            var conditionParser = new ConditionPatternParser();\n            var regexParser = new RuleRegexParser();\n            var flagsParser = new FlagParser();\n            var tokenizer = new Tokenizer();\n\n            while ((line = input.ReadLine()) != null)\n            {\n                lineNum++;\n                if (string.IsNullOrEmpty(line))\n                {\n                    continue;\n                }\n                if (line.StartsWith(\"#\"))\n                {\n                    continue;\n                }\n                var tokens = tokenizer.Tokenize(line);\n                if (tokens.Count > 4)\n                {\n                    // This means the line didn't have an appropriate format, throw format exception\n                    throw new FormatException(Resources.FormatError_ModRewriteParseError(\"Too many tokens on line\", lineNum));\n                }\n\n                switch (tokens[0])\n                {\n                    case \"RewriteBase\":\n                        // the notion of the path base spans across all rules, not just mod_rewrite\n                        // So not implemented for now\n                        throw new NotImplementedException(\"RewriteBase is not implemented\");\n                    case \"RewriteCond\":\n                        try\n                        {\n                            var pattern = testStringParser.Parse(tokens[1]);\n                            var condActionParsed = conditionParser.ParseActionCondition(tokens[2]);\n\n                            var flags = new Flags();\n                            if (tokens.Count == 4)\n                            {\n                                flags = flagsParser.Parse(tokens[3]);\n                            }\n\n                            builder.AddConditionFromParts(pattern, condActionParsed, flags);\n                        }\n                        catch (FormatException formatException)\n                        {\n                            throw new FormatException(Resources.FormatError_ModRewriteGeneralParseError(lineNum), formatException);\n                        }\n                        break;\n                    case \"RewriteRule\":\n                        try\n                        {\n                            var regex = regexParser.ParseRuleRegex(tokens[1]);\n                            var pattern = testStringParser.Parse(tokens[2]);\n\n                            Flags flags;\n                            if (tokens.Count == 4)\n                            {\n                                flags = flagsParser.Parse(tokens[3]);\n                            }\n                            else\n                            {\n                                flags = new Flags();\n                            }\n\n                            builder.AddMatch(regex, flags);\n                            builder.AddAction(pattern, flags);\n                            rules.Add(builder.Build());\n                            builder = new RuleBuilder();\n                        }\n                        catch (FormatException formatException)\n                        {\n                            throw new FormatException(Resources.FormatError_ModRewriteGeneralParseError(lineNum), formatException);\n                        }\n                        break;\n                    case \"RewriteMap\":\n                        // Lack of use\n                        throw new NotImplementedException(\"RewriteMap are not implemented\");\n                    case \"RewriteEngine\":\n                        // Explicitly do nothing here, no notion of turning on regex engine.\n                        break;\n                    default:\n                        throw new FormatException(Resources.FormatError_ModRewriteParseError(\"Unrecognized keyword: \" + tokens[0], lineNum));\n                }\n            }\n            return rules;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/FlagParser.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public class FlagParser\n    {\n        private readonly IDictionary<string, FlagType> _ruleFlagLookup = new Dictionary<string, FlagType>(StringComparer.OrdinalIgnoreCase) {\n            { \"b\", FlagType.EscapeBackreference},\n            { \"c\", FlagType.Chain },\n            { \"chain\", FlagType.Chain},\n            { \"co\", FlagType.Cookie },\n            { \"cookie\", FlagType.Cookie },\n            { \"dpi\", FlagType.DiscardPath },\n            { \"discardpath\", FlagType.DiscardPath },\n            { \"e\", FlagType.Env},\n            { \"env\", FlagType.Env},\n            { \"end\", FlagType.End },\n            { \"f\", FlagType.Forbidden },\n            { \"forbidden\", FlagType.Forbidden },\n            { \"g\", FlagType.Gone },\n            { \"gone\", FlagType.Gone },\n            { \"h\", FlagType.Handler },\n            { \"handler\", FlagType.Handler },\n            { \"l\", FlagType.Last },\n            { \"last\", FlagType.Last },\n            { \"n\", FlagType.Next },\n            { \"next\", FlagType.Next },\n            { \"nc\", FlagType.NoCase },\n            { \"nocase\", FlagType.NoCase },\n            { \"ne\", FlagType.NoEscape },\n            { \"noescape\", FlagType.NoEscape },\n            { \"ns\", FlagType.NoSubReq },\n            { \"nosubreq\", FlagType.NoSubReq },\n            { \"or\", FlagType.Or },\n            { \"ornext\", FlagType.Or },\n            { \"p\", FlagType.Proxy },\n            { \"proxy\", FlagType.Proxy },\n            { \"pt\", FlagType.PassThrough },\n            { \"passthrough\", FlagType.PassThrough },\n            { \"qsa\", FlagType.QSAppend },\n            { \"qsappend\", FlagType.QSAppend },\n            { \"qsd\", FlagType.QSDiscard },\n            { \"qsdiscard\", FlagType.QSDiscard },\n            { \"qsl\", FlagType.QSLast },\n            { \"qslast\", FlagType.QSLast },\n            { \"r\", FlagType.Redirect },\n            { \"redirect\", FlagType.Redirect },\n            { \"s\", FlagType.Skip },\n            { \"skip\", FlagType.Skip },\n            { \"t\", FlagType.Type },\n            { \"type\", FlagType.Type },\n        };\n\n        public Flags Parse(string flagString)\n        {\n            if (string.IsNullOrEmpty(flagString))\n            {\n                throw new ArgumentException(nameof(flagString));\n            }\n\n            // Check that flags are contained within []\n            // Guaranteed to have a length of at least 1 here, so this will never throw for indexing.\n            if (!(flagString[0] == '[' && flagString[flagString.Length - 1] == ']'))\n            {\n                throw new FormatException(\"Flags should start and end with square brackets: [flags]\");\n            }\n\n            // Lexing esque step to split all flags.\n            // Invalid syntax to have any spaces.\n            var tokens = flagString.Substring(1, flagString.Length - 2).Split(',');\n            var flags = new Flags();\n            foreach (var token in tokens)\n            {\n                var hasPayload = token.Split('=');\n\n                FlagType flag;\n                if (!_ruleFlagLookup.TryGetValue(hasPayload[0], out flag))\n                {\n                    throw new FormatException($\"Unrecognized flag: '{hasPayload[0]}'\");\n                }\n\n                if (hasPayload.Length == 2)\n                {\n                    flags.SetFlag(flag, hasPayload[1]);\n                }\n                else\n                {\n                    flags.SetFlag(flag, string.Empty);\n                }\n            }\n            return flags;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/FlagType.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public enum FlagType\n    {\n        EscapeBackreference,\n        Chain,\n        Cookie,\n        DiscardPath,\n        Env,\n        End,\n        Forbidden,\n        Gone,\n        Handler,\n        Last,\n        Next,\n        NoCase,\n        NoEscape,\n        NoSubReq,\n        NoVary,\n        Or,\n        Proxy,\n        PassThrough,\n        QSAppend,\n        QSDiscard,\n        QSLast,\n        Redirect,\n        Skip,\n        Type\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/Flags.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    // For more information of flags, and what flags we currently support:\n    // https://github.com/aspnet/BasicMiddleware/issues/66\n    // http://httpd.apache.org/docs/current/expr.html#vars\n    public class Flags\n    {\n        public IDictionary<FlagType, string> FlagDictionary { get; }\n\n        public Flags(IDictionary<FlagType, string> flags)\n        {\n            FlagDictionary = flags;\n        }\n\n        public Flags()\n        {\n            FlagDictionary = new Dictionary<FlagType, string>();\n        }\n\n        public void SetFlag(FlagType flag, string value)\n        {\n            if (value == null)\n            {\n                value = string.Empty;\n            }\n            FlagDictionary[flag] = value;\n        }\n\n        public bool GetValue(FlagType flag, out string value)\n        {\n            string res;\n            if (!FlagDictionary.TryGetValue(flag, out res))\n            {\n                value = null;\n                return false;\n            }\n            value = res;\n            return true;\n        }\n\n        public string this[FlagType flag]\n        {\n            get\n            {\n                string res;\n                if (!FlagDictionary.TryGetValue(flag, out res))\n                {\n                    return null;\n                }\n                return res;\n            }\n            set\n            {\n                FlagDictionary[flag] = value ?? string.Empty;\n            }\n        }\n\n        public bool HasFlag(FlagType flag)\n        {\n            string res;\n            return FlagDictionary.TryGetValue(flag, out res);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/OperationType.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public enum OperationType\n    {\n        None,\n        Equal,\n        Greater,\n        GreaterEqual,\n        Less,\n        LessEqual,\n        NotEqual,\n        Directory,\n        RegularFile,\n        ExistingFile,\n        SymbolicLink,\n        Size,\n        ExistingUrl,\n        Executable\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ParsedModRewriteCondition.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public class ParsedModRewriteInput\n    {\n        public bool Invert { get; set; }\n        public ConditionType ConditionType { get; set; }\n        public OperationType OperationType { get; set; }\n        public string Operand { get; set; }\n\n        public ParsedModRewriteInput() { }\n\n        public ParsedModRewriteInput(bool invert, ConditionType conditionType, OperationType operationType, string operand)\n        {\n            Invert = invert;\n            ConditionType = conditionType;\n            OperationType = operationType;\n            Operand = operand;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/RuleBuilder.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public class RuleBuilder\n    {\n        private IList<Condition> _conditions;\n        internal IList<UrlAction> _actions = new List<UrlAction>();\n        private UrlMatch _match;\n        private CookieActionFactory _cookieActionFactory = new CookieActionFactory();\n\n        private readonly TimeSpan _regexTimeout = TimeSpan.FromSeconds(1);\n\n        public ApacheModRewriteRule Build()\n        {\n            if (_actions.Count == 0 || _match == null)\n            {\n                throw new InvalidOperationException(\"Cannot create ModRewriteRule without action and match\");\n            }\n            return new ApacheModRewriteRule(_match, _conditions, _actions);\n        }\n\n        public void AddRule(string rule)\n        {\n            var tokens = new Tokenizer().Tokenize(rule);\n            var regex = new RuleRegexParser().ParseRuleRegex(tokens[1]);\n            var pattern = new TestStringParser().Parse(tokens[2]);\n\n            Flags flags;\n            if (tokens.Count == 4)\n            {\n                flags = new FlagParser().Parse(tokens[3]);\n            }\n            else\n            {\n                flags = new Flags();\n            }\n            AddMatch(regex, flags);\n            AddAction(pattern, flags);\n        }\n\n        public void AddConditionFromParts(\n            Pattern pattern,\n            ParsedModRewriteInput input,\n            Flags flags)\n        {\n            if (_conditions == null)\n            {\n                _conditions = new List<Condition>();\n            }\n\n            var condition = new Condition();\n\n            condition.OrNext = flags.HasFlag(FlagType.Or);\n            condition.Input = pattern;\n\n            switch (input.ConditionType)\n            {\n                case ConditionType.Regex:\n                    if (flags.HasFlag(FlagType.NoCase))\n                    {\n                        condition.Match = new RegexMatch(new Regex(input.Operand, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, _regexTimeout), input.Invert);\n                    }\n                    else\n                    {\n                        condition.Match = new RegexMatch(new Regex(input.Operand, RegexOptions.CultureInvariant | RegexOptions.Compiled, _regexTimeout), input.Invert);\n                    }\n                    break;\n                case ConditionType.IntComp:\n                    switch (input.OperationType)\n                    {\n                        case OperationType.Equal:\n                            condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Equal);\n                            break;\n                        case OperationType.Greater:\n                            condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Greater);\n                            break;\n                        case OperationType.GreaterEqual:\n                            condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.GreaterEqual);\n                            break;\n                        case OperationType.Less:\n                            condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.Less);\n                            break;\n                        case OperationType.LessEqual:\n                            condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.LessEqual);\n                            break;\n                        case OperationType.NotEqual:\n                            condition.Match = new IntegerMatch(input.Operand, IntegerOperationType.NotEqual);\n                            break;\n                        default:\n                            throw new ArgumentException(\"Invalid operation for integer comparison.\");\n                    }\n                    break;\n                case ConditionType.StringComp:\n                    switch (input.OperationType)\n                    {\n                        case OperationType.Equal:\n                            condition.Match = new StringMatch(input.Operand, StringOperationType.Equal, input.Invert);\n                            break;\n                        case OperationType.Greater:\n                            condition.Match = new StringMatch(input.Operand, StringOperationType.Greater, input.Invert);\n                            break;\n                        case OperationType.GreaterEqual:\n                            condition.Match = new StringMatch(input.Operand, StringOperationType.GreaterEqual, input.Invert);\n                            break;\n                        case OperationType.Less:\n                            condition.Match = new StringMatch(input.Operand, StringOperationType.Less, input.Invert);\n                            break;\n                        case OperationType.LessEqual:\n                            condition.Match = new StringMatch(input.Operand, StringOperationType.LessEqual, input.Invert);\n                            break;\n                        default:\n                            throw new ArgumentException(\"Invalid operation for string comparison.\");\n                    }\n                    break;\n                default:\n                    switch (input.OperationType)\n                    {\n                        case OperationType.Directory:\n                            condition.Match = new IsDirectoryMatch(input.Invert);\n                            break;\n                        case OperationType.RegularFile:\n                            condition.Match = new IsFileMatch(input.Invert);\n                            break;\n                        case OperationType.ExistingFile:\n                            condition.Match = new IsFileMatch(input.Invert);\n                            break;\n                        case OperationType.SymbolicLink:\n                            // TODO see if FileAttributes.ReparsePoint works for this?\n                            throw new NotImplementedException(\"Symbolic links are not supported because \" +\n                                                            \"of cross platform implementation\");\n                        case OperationType.Size:\n                            condition.Match = new FileSizeMatch(input.Invert);\n                            break;\n                        case OperationType.ExistingUrl:\n                            throw new NotSupportedException(\"Existing Url lookups not supported because it requires a subrequest\");\n                        case OperationType.Executable:\n                            throw new NotSupportedException(\"Executable Property is not supported because Windows \" +\n                                                            \"requires a pinvoke to get this property\");\n                        default:\n                            throw new ArgumentException(\"Invalid operation for property comparison\");\n                    }\n                    break;\n            }\n            _conditions.Add(condition);\n        }\n\n        public void AddMatch(\n            ParsedModRewriteInput input,\n            Flags flags)\n        {\n            if (flags.HasFlag(FlagType.NoCase))\n            {\n                _match = new RegexMatch(new Regex(input.Operand, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, _regexTimeout), input.Invert);\n            }\n            else\n            {\n                _match = new RegexMatch(new Regex(input.Operand, RegexOptions.CultureInvariant | RegexOptions.Compiled, _regexTimeout), input.Invert);\n            }\n        }\n\n        public void AddAction(\n            Pattern pattern,\n            Flags flags)\n        {\n            string flag;\n            if (flags.GetValue(FlagType.Cookie, out flag))\n            {\n                var action = _cookieActionFactory.Create(flag);\n                _actions.Add(action);\n            }\n\n            if (flags.GetValue(FlagType.Env, out flag))\n            {\n                throw new NotSupportedException(Resources.Error_ChangeEnvironmentNotSupported);\n            }\n\n            if (flags.HasFlag(FlagType.Forbidden))\n            {\n                _actions.Add(new ForbiddenAction());\n            }\n            else if (flags.HasFlag(FlagType.Gone))\n            {\n                _actions.Add(new GoneAction());\n            }\n            else\n            {\n                var escapeBackReference = flags.HasFlag(FlagType.EscapeBackreference);\n                var queryStringAppend = flags.HasFlag(FlagType.QSAppend);\n                var queryStringDelete = flags.HasFlag(FlagType.QSDiscard);\n\n                // is redirect?\n                string statusCode;\n                if (flags.GetValue(FlagType.Redirect, out statusCode))\n                {\n                    int responseStatusCode;\n                    if (string.IsNullOrEmpty(statusCode))\n                    {\n                        responseStatusCode = StatusCodes.Status302Found;\n                    }\n                    else if (!int.TryParse(statusCode, NumberStyles.None, CultureInfo.InvariantCulture, out responseStatusCode))\n                    {\n                        throw new FormatException(Resources.FormatError_InputParserInvalidInteger(statusCode, -1));\n                    }\n                    _actions.Add(new RedirectAction(responseStatusCode, pattern, queryStringAppend, queryStringDelete, escapeBackReference));\n                }\n                else\n                {\n                    var last = flags.HasFlag(FlagType.End) || flags.HasFlag(FlagType.Last);\n                    var termination = last ? RuleResult.SkipRemainingRules : RuleResult.ContinueRules;\n                    _actions.Add(new RewriteAction(termination, pattern, queryStringAppend, queryStringDelete, escapeBackReference));\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/RuleRegexParser.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public class RuleRegexParser\n    {\n        public ParsedModRewriteInput ParseRuleRegex(string regex)\n        {\n            if (string.IsNullOrEmpty(regex))\n            {\n                throw new FormatException(\"Regex expression is null\");\n            }\n            if (regex[0] == '!')\n            {\n                return new ParsedModRewriteInput { Invert = true, Operand = regex.Substring(1) };\n            }\n            else\n            {\n                return new ParsedModRewriteInput { Invert = false, Operand = regex };\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/SegmentType.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    public enum SegmentType\n    {\n        Literal,\n        ServerParameter,\n        ConditionParameter,\n        RuleParameter\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ServerVariables.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    /// <summary>\n    /// mod_rewrite lookups for specific string constants.\n    /// </summary>\n    public static class ServerVariables\n    {\n\n        /// <summary>\n        /// Translates mod_rewrite server variables strings to an enum of different server variables.\n        /// </summary>\n        /// <param name=\"serverVariable\">The server variable string.</param>\n        /// <param name=\"context\">The Parser context</param>\n        /// <returns>The appropriate enum if the server variable exists, else ServerVariable.None</returns>\n        public static PatternSegment FindServerVariable(string serverVariable, ParserContext context)\n        {\n            switch (serverVariable)\n            {\n                case \"HTTP_ACCEPT\":\n                    return new HeaderSegment(HeaderNames.Accept);\n                case \"HTTP_COOKIE\":\n                    return new HeaderSegment(HeaderNames.Cookie);\n                case \"HTTP_HOST\":\n                    return new HeaderSegment(HeaderNames.Host);\n                case \"HTTP_REFERER\":\n                    return new HeaderSegment(HeaderNames.Referer);\n                case \"HTTP_USER_AGENT\":\n                    return new HeaderSegment(HeaderNames.UserAgent);\n                case \"HTTP_CONNECTION\":\n                    return new HeaderSegment(HeaderNames.Connection);\n                case \"HTTP_FORWARDED\":\n                    return new HeaderSegment(\"Forwarded\");\n                case \"AUTH_TYPE\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"CONN_REMOTE_ADDR\":\n                    return new RemoteAddressSegment();\n                case \"CONTEXT_PREFIX\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"CONTEXT_DOCUMENT_ROOT\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"IPV6\":\n                    return new IsIPV6Segment();\n                case \"PATH_INFO\":\n                    throw new NotImplementedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"QUERY_STRING\":\n                    return new QueryStringSegment();\n                case \"REMOTE_ADDR\":\n                    return new RemoteAddressSegment();\n                case \"REMOTE_HOST\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"REMOTE_IDENT\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"REMOTE_PORT\":\n                    return new RemotePortSegment();\n                case \"REMOTE_USER\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"REQUEST_METHOD\":\n                    return new RequestMethodSegment();\n                case \"SCRIPT_FILENAME\":\n                    return new RequestFileNameSegment();\n                case \"DOCUMENT_ROOT\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"SCRIPT_GROUP\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"SCRIPT_USER\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"SERVER_ADDR\":\n                    return new LocalAddressSegment();\n                case \"SERVER_ADMIN\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"SERVER_NAME\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"SERVER_PORT\":\n                    return new LocalPortSegment();\n                case \"SERVER_PROTOCOL\":\n                    return new ServerProtocolSegment();\n                case \"SERVER_SOFTWARE\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"TIME_YEAR\":\n                    return new DateTimeSegment(serverVariable);\n                case \"TIME_MON\":\n                    return new DateTimeSegment(serverVariable);\n                case \"TIME_DAY\":\n                    return new DateTimeSegment(serverVariable);\n                case \"TIME_HOUR\":\n                    return new DateTimeSegment(serverVariable);\n                case \"TIME_MIN\":\n                    return new DateTimeSegment(serverVariable);\n                case \"TIME_SEC\":\n                    return new DateTimeSegment(serverVariable);\n                case \"TIME_WDAY\":\n                    return new DateTimeSegment(serverVariable);\n                case \"TIME\":\n                    return new DateTimeSegment(serverVariable);\n                case \"API_VERSION\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"HTTPS\":\n                    return new IsHttpsModSegment();\n                case \"HTTP2\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"IS_SUBREQ\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"REQUEST_FILENAME\":\n                    return new RequestFileNameSegment();\n                case \"REQUEST_SCHEME\":\n                    return new SchemeSegment();\n                case \"REQUEST_URI\":\n                    return new UrlSegment();\n                case \"THE_REQUEST\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                default:\n                    throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(serverVariable, context.Index));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/TestStringParser.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    /// <summary>\n    /// Parses the TestString segment of the mod_rewrite condition.\n    /// </summary>\n    public class TestStringParser\n    {\n        private const char Percent = '%';\n        private const char Dollar = '$';\n        private const char Colon = ':';\n        private const char OpenBrace = '{';\n        private const char CloseBrace = '}';\n\n        /// <summary>\n        /// Creates a pattern, which is a template to create a new test string to \n        /// compare to the condition pattern. Can contain server variables, back references, etc.\n        /// </summary>\n        /// <param name=\"testString\">The test string portion of the RewriteCond\n        /// Examples:\n        /// %{REMOTE_ADDR}\n        /// /var/www/%{REQUEST_URI}\n        /// %1\n        /// $1</param>\n        /// <returns>A new <see cref=\"Pattern\"/>, containing a list of <see cref=\"PatternSegment\"/></returns>\n        /// http://httpd.apache.org/docs/current/mod/mod_rewrite.html\n        public Pattern Parse(string testString)\n        {\n            if (testString == null)\n            {\n                testString = string.Empty;\n            }\n            var context = new ParserContext(testString);\n            var results = new List<PatternSegment>();\n            while (context.Next())\n            {\n                switch (context.Current)\n                {\n                    case Percent:\n                        // This is a server parameter, parse for a condition variable\n                        if (!context.Next())\n                        {\n                            throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(testString, context.Index));\n                        }\n                        ParseConditionParameter(context, results);\n                        break;\n                    case Dollar:\n                        // This is a parameter from the rule, verify that it is a number from 0 to 9 directly after it\n                        // and create a new Pattern Segment.\n                        if (!context.Next())\n                        {\n                            throw new FormatException(Resources.FormatError_InputParserNoBackreference(context.Index));\n                        }\n                        context.Mark();\n                        if (context.Current >= '0' && context.Current <= '9')\n                        {\n                            context.Next();\n                            var ruleVariable = context.Capture();\n                            context.Back();\n                            var parsedIndex = int.Parse(ruleVariable);\n\n                            results.Add(new RuleMatchSegment(parsedIndex));\n                        }\n                        else\n                        {\n                            throw new FormatException(Resources.FormatError_InputParserInvalidInteger(testString, context.Index));\n                        }\n                        break;\n                    default:\n                        ParseLiteral(context, results);\n                        break;\n                }\n            }\n            return new Pattern(results);\n        }\n\n        /// <summary>\n        /// Obtains the condition parameter, which could either be a condition variable or a \n        /// server variable. Assumes the current character is immediately after the '%'.\n        /// context, on return will be on the last character of variable captured, such that after \n        /// Next() is called, it will be on the character immediately after the condition parameter.\n        /// </summary>\n        /// <param name=\"context\">The ParserContext</param>\n        /// <param name=\"results\">The List of results which the new condition parameter will be added.</param>\n        /// <returns>true </returns>\n        private static void ParseConditionParameter(ParserContext context, IList<PatternSegment> results)\n        {\n            // Parse { }\n            if (context.Current == OpenBrace)\n            {\n                // Start of a server variable\n                if (!context.Next())\n                {\n                    // Dangling {\n                    throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));\n                }\n                context.Mark();\n                while (context.Current != CloseBrace)\n                {\n                    if (!context.Next())\n                    {\n                        throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));\n                    }\n                    else if (context.Current == Colon)\n                    {\n                        // Have a segmented look up Ex: HTTP:xxxx \n                        // Most of these we can't handle\n                        throw new NotImplementedException(\"Segmented Lookups no implemented\");\n                    }\n                }\n\n                // Need to verify server variable captured exists\n                var rawServerVariable = context.Capture();\n                results.Add(ServerVariables.FindServerVariable(rawServerVariable, context));\n            }\n            else if (context.Current >= '0' && context.Current <= '9')\n            {\n                // means we have a segmented lookup\n                // store information in the testString result to know what to look up.\n                context.Mark();\n                context.Next();\n                var rawConditionParameter = context.Capture();\n\n                // Once we leave this method, the while loop will call next again. Because\n                // capture is exclusive, we need to go one past the end index, capture, and then go back.\n                context.Back();\n                var parsedIndex = int.Parse(rawConditionParameter);\n                results.Add(new ConditionMatchSegment(parsedIndex));\n            }\n            else\n            {\n                // illegal escape of a character\n                throw new FormatException(Resources.FormatError_InputParserInvalidInteger(context.Template, context.Index));\n            }\n        }\n\n        /// <summary>\n        /// Parse a string literal in the test string. Continues capturing until the start of a new variable type.\n        /// </summary>\n        /// <param name=\"context\"></param>\n        /// <param name=\"results\"></param>\n        /// <returns></returns>\n        private static void ParseLiteral(ParserContext context, IList<PatternSegment> results)\n        {\n            context.Mark();\n            string literal;\n            while (true)\n            {\n                if (context.Current == Percent || context.Current == Dollar)\n                {\n                    literal = context.Capture();\n                    context.Back();\n                    break;\n                }\n                if (!context.Next())\n                {\n                    literal = context.Capture();\n                    break;\n                }\n            }\n            // add results\n            results.Add(new LiteralSegment(literal));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/Tokenizer.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite\n{\n    /// <summary>\n    /// Tokenizes a mod_rewrite rule, delimited by spaces.\n    /// </summary>\n    public class Tokenizer\n    {\n        private const char Space = ' ';\n        private const char Escape = '\\\\';\n        private const char Tab = '\\t';\n        private const char Quote = '\"';\n\n        /// <summary>\n        /// Splits a string on whitespace, ignoring spaces, creating into a list of strings.\n        /// </summary>\n        /// <param name=\"rule\">The rule to tokenize.</param>\n        /// <returns>A list of tokens.</returns>\n        public IList<string> Tokenize(string rule)\n        {\n            // TODO make list of strings a reference to the original rule? (run into problems with escaped spaces).\n            // TODO handle \"s and probably replace \\ character with no slash.\n            if (string.IsNullOrEmpty(rule))\n            {\n                return null;\n            }\n            var context = new ParserContext(rule);\n            context.Next();\n\n            var tokens = new List<string>();\n            context.Mark();\n            while (true)\n            {\n                switch (context.Current)\n                {\n                    case Escape:\n                        // Need to progress such that the next character is not evaluated.\n                        if (!context.Next())\n                        {\n                            // Means that a character was not escaped appropriately Ex: \"foo\\\"\n                            throw new FormatException($\"Invalid escaper character in string: {rule}\");\n                        }\n                        break;\n                    case Quote:\n                        // Ignore all characters until the next quote is hit\n                        if (!context.Next())\n                        {\n                            throw new FormatException($\"Mismatched number of quotes: {rule}\");\n                        }\n\n                        while (context.Current != Quote)\n                        {\n                            if (!context.Next())\n                            {\n                                throw new FormatException($\"Mismatched number of quotes: {rule}\");\n                            }\n                        }\n                        break;\n                    case Space:\n                    case Tab:\n                        // time to capture!\n                        var token = context.Capture();\n                        if (!string.IsNullOrEmpty(token))\n                        {\n                            tokens.Add(token);\n                            do\n                            {\n                                if (!context.Next())\n                                {\n                                    // At end of string, we can return at this point.\n                                    RemoveQuotesAndEscapeCharacters(tokens);\n                                    return tokens;\n                                }\n                            } while (context.Current == Space || context.Current == Tab);\n                            context.Mark();\n                            context.Back();\n                        }\n                        break;\n                }\n                if (!context.Next())\n                {\n                    // End of string. Capture.\n                    break;\n                }\n            }\n            var done = context.Capture();\n            if (!string.IsNullOrEmpty(done))\n            {\n                tokens.Add(done);\n            }\n\n            RemoveQuotesAndEscapeCharacters(tokens);\n            return tokens;\n        }\n\n        // Need to remove leading and trailing slashes if they exist.\n        // This is on start-up, so more forgivening towards substrings/ new strings\n        // If this is a perf/memory problem, discuss later.\n        private static void RemoveQuotesAndEscapeCharacters(IList<string> tokens)\n        {\n            for (var i = 0; i < tokens.Count; i++)\n            {\n                var token = tokens[i];\n                var trimmed = token.Trim('\\\"');\n                tokens[i] = Regex.Unescape(trimmed);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/BackReferenceCollection.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public class BackReferenceCollection\n    {\n        private List<string> _backReferences = new List<string>();\n\n        public BackReferenceCollection(GroupCollection references)\n        {\n            if (references != null)\n            {\n                for (var i = 0; i < references.Count; i++)\n                {\n                    _backReferences.Add(references[i].Value);\n                }\n            }\n        }\n\n        public BackReferenceCollection(string reference)\n        {\n            _backReferences.Add(reference);\n        }\n\n        public string this[int index]\n        {\n            get\n            {\n                if (index < _backReferences.Count)\n                {\n                    return _backReferences[index];\n                }\n                else\n                {\n                    throw new IndexOutOfRangeException($\"Cannot access back reference at index {index}. Only {_backReferences.Count} back references were captured.\");\n                }\n            }\n        }\n\n        public void Add(BackReferenceCollection references)\n        {\n            if (references != null)\n            {\n                _backReferences.AddRange(references._backReferences);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/DelegateRule.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public class DelegateRule : IRule\n    {\n        private readonly Action<RewriteContext> _onApplyRule;\n\n        public DelegateRule(Action<RewriteContext> onApplyRule)\n        {\n            _onApplyRule = onApplyRule;\n        }\n        public void ApplyRule(RewriteContext context) => _onApplyRule(context);\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/ActionType.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public enum ActionType\n    {\n        None,\n        Rewrite,\n        Redirect,\n        CustomResponse,\n        AbortRequest\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/Condition.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class Condition\n    {\n        public Pattern Input { get; set; }\n        public UrlMatch Match { get; set; }\n\n        public MatchResults Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            var pattern = Input.Evaluate(context, ruleBackReferences, conditionBackReferences);\n            return Match.Evaluate(pattern, context);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/ConditionCollection.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class ConditionCollection : IEnumerable<Condition>\n    {\n        private readonly List<Condition> _conditions = new List<Condition>();\n\n        public LogicalGrouping Grouping { get; }\n        public bool TrackAllCaptures { get; }\n\n        public ConditionCollection()\n            :this(LogicalGrouping.MatchAll, trackAllCaptures: false)\n        {\n        }\n\n        public ConditionCollection(LogicalGrouping grouping, bool trackAllCaptures)\n        {\n            Grouping = grouping;\n            TrackAllCaptures = trackAllCaptures;\n        }\n\n        public int Count => _conditions.Count;\n\n        public Condition this[int index]\n        {\n            get\n            {\n                if (index < _conditions.Count)\n                {\n                    return _conditions[index];\n                }\n                throw new IndexOutOfRangeException($\"Cannot access condition at index {index}. Only {_conditions.Count} conditions were captured.\");\n            }\n        }\n\n        public void Add(Condition condition)\n        {\n            if (condition != null)\n            {\n                _conditions.Add(condition);\n            }\n        }\n\n        public void AddConditions(IEnumerable<Condition> conditions)\n        {\n            if (conditions != null)\n            {\n                _conditions.AddRange(conditions);\n            }\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return _conditions.GetEnumerator();\n        }\n\n        public IEnumerator<Condition> GetEnumerator()\n        {\n            return _conditions.GetEnumerator();\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/ConditionEvaluator.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public static class ConditionEvaluator\n    {\n        public static MatchResults Evaluate(ConditionCollection conditions, RewriteContext context, BackReferenceCollection backReferences)\n        {\n            BackReferenceCollection prevBackReferences = null;\n            MatchResults condResult = null;\n            var orSucceeded = false;\n            foreach (var condition in conditions)\n            {\n                if (orSucceeded && conditions.Grouping == LogicalGrouping.MatchAny)\n                {\n                    continue;\n                }\n\n                if (orSucceeded)\n                {\n                    orSucceeded = false;\n                    continue;\n                }\n\n                condResult = condition.Evaluate(context, backReferences, prevBackReferences);\n                var currentBackReferences = condResult.BackReferences;\n                if (conditions.Grouping == LogicalGrouping.MatchAny)\n                {\n                    orSucceeded = condResult.Success;\n                }\n                else if (!condResult.Success)\n                {\n                    return condResult;\n                }\n\n                if (condResult.Success && conditions.TrackAllCaptures && prevBackReferences!= null)\n                {\n                    prevBackReferences.Add(currentBackReferences);\n                    currentBackReferences = prevBackReferences;\n                }\n\n                prevBackReferences = currentBackReferences;\n            }\n\n            return new MatchResults { BackReferences = prevBackReferences, Success = condResult.Success };\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/IISRewriteMap.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class IISRewriteMap\n    {\n        private readonly Dictionary<string, string> _map = new Dictionary<string, string>();\n\n        public IISRewriteMap(string name)\n        {\n            if (string.IsNullOrEmpty(name))\n            {\n                throw new ArgumentException(nameof(name));\n            }\n            Name = name;\n        }\n\n        public string Name { get; }\n\n        public string this[string key]\n        {\n            get\n            {\n                string value;\n                return _map.TryGetValue(key, out value) ? value : null;\n            }\n            set\n            {\n                if (string.IsNullOrEmpty(key))\n                {\n                    throw new ArgumentException(nameof(key));\n                }\n                if (string.IsNullOrEmpty(value))\n                {\n                    throw new ArgumentException(nameof(value));\n                }\n                _map[key] = value;\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/IISRewriteMapCollection.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections;\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class IISRewriteMapCollection : IEnumerable<IISRewriteMap>\n    {\n        private readonly Dictionary<string, IISRewriteMap> _rewriteMaps = new Dictionary<string, IISRewriteMap>();\n\n        public void Add(IISRewriteMap rewriteMap)\n        {\n            if (rewriteMap != null)\n            {\n                _rewriteMaps[rewriteMap.Name] = rewriteMap;\n            }\n        }\n\n        public int Count => _rewriteMaps.Count;\n\n        public IISRewriteMap this[string key]\n        {\n            get\n            {\n                IISRewriteMap value;\n                return _rewriteMaps.TryGetValue(key, out value) ? value : null;\n            }\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return _rewriteMaps.Values.GetEnumerator();\n        }\n\n        public IEnumerator<IISRewriteMap> GetEnumerator()\n        {\n            return _rewriteMaps.Values.GetEnumerator();\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/IISUrlRewriteRule.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Logging;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class IISUrlRewriteRule : IRule\n    {\n        public string Name { get; }\n        public UrlMatch InitialMatch { get; }\n        public ConditionCollection Conditions { get; }\n        public UrlAction Action { get; }\n        public bool Global { get; }\n\n        public IISUrlRewriteRule(string name,\n            UrlMatch initialMatch,\n            ConditionCollection conditions,\n            UrlAction action)\n            : this(name, initialMatch, conditions, action, false)\n        {\n        }\n\n        public IISUrlRewriteRule(string name,\n            UrlMatch initialMatch,\n            ConditionCollection conditions,\n            UrlAction action,\n            bool global)\n        {\n            Name = name;\n            InitialMatch = initialMatch;\n            Conditions = conditions;\n            Action = action;\n            Global = global;\n        }\n\n        public virtual void ApplyRule(RewriteContext context)\n        {\n            // Due to the path string always having a leading slash,\n            // remove it from the path before regex comparison\n            var path = context.HttpContext.Request.Path;\n            MatchResults initMatchResults;\n            if (path == PathString.Empty)\n            {\n                initMatchResults = InitialMatch.Evaluate(path.ToString(), context);\n            }\n            else\n            {\n                initMatchResults = InitialMatch.Evaluate(path.ToString().Substring(1), context);\n            }\n\n            if (!initMatchResults.Success)\n            {\n                context.Logger?.UrlRewriteDidNotMatchRule(Name);\n                return;\n            }\n\n            MatchResults condResult = null;\n            if (Conditions != null)\n            {\n                condResult = ConditionEvaluator.Evaluate(Conditions, context, initMatchResults.BackReferences);\n                if (!condResult.Success)\n                {\n                    context.Logger?.UrlRewriteDidNotMatchRule(Name);\n                    return;\n                }\n            }\n\n            context.Logger?.UrlRewriteMatchedRule(Name);\n            // at this point we know the rule passed, evaluate the replacement.\n            Action.ApplyAction(context, initMatchResults?.BackReferences, condResult?.BackReferences);\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/InputParser.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class InputParser\n    {\n        private const char Colon = ':';\n        private const char OpenBrace = '{';\n        private const char CloseBrace = '}';\n        private readonly IISRewriteMapCollection _rewriteMaps;\n\n        public InputParser()\n        {\n        }\n\n        public InputParser(IISRewriteMapCollection rewriteMaps)\n        {\n            _rewriteMaps = rewriteMaps;\n        }\n\n        /// <summary>\n        /// Creates a pattern, which is a template to create a new test string to\n        /// compare to the condition. Can contain server variables, back references, etc.\n        /// </summary>\n        /// <param name=\"testString\"></param>\n        /// <returns>A new <see cref=\"Pattern\"/>, containing a list of <see cref=\"PatternSegment\"/></returns>\n        public Pattern ParseInputString(string testString)\n        {\n            return ParseInputString(testString, UriMatchPart.Path);\n        }\n\n        /// <summary>\n        /// Creates a pattern, which is a template to create a new test string to\n        /// compare to the condition. Can contain server variables, back references, etc.\n        /// </summary>\n        /// <param name=\"testString\"></param>\n        /// <param name=\"uriMatchPart\">When testString evaluates to a URL segment, specify which part of the URI to evaluate.</param>\n        /// <returns>A new <see cref=\"Pattern\"/>, containing a list of <see cref=\"PatternSegment\"/></returns>\n        public Pattern ParseInputString(string testString, UriMatchPart uriMatchPart)\n        {\n            if (testString == null)\n            {\n                testString = string.Empty;\n            }\n\n            var context = new ParserContext(testString);\n            return ParseString(context, uriMatchPart);\n        }\n\n        private Pattern ParseString(ParserContext context, UriMatchPart uriMatchPart)\n        {\n            var results = new List<PatternSegment>();\n            while (context.Next())\n            {\n                if (context.Current == OpenBrace)\n                {\n                    // This is a server parameter, parse for a condition variable\n                    if (!context.Next())\n                    {\n                        // missing {\n                        throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));\n                    }\n                    ParseParameter(context, results, uriMatchPart);\n                }\n                else if (context.Current == CloseBrace)\n                {\n                    return new Pattern(results);\n                }\n                else\n                {\n                    // Parse for literals, which will return on either the end of the test string \n                    // or when it hits a special character\n                    ParseLiteral(context, results);\n                }\n            }\n            return new Pattern(results);\n        }\n\n        private void ParseParameter(ParserContext context, IList<PatternSegment> results, UriMatchPart uriMatchPart)\n        {\n            context.Mark();\n            // Four main cases:\n            // 1. {NAME} - Server Variable, create lambda to get the part of the context\n            // 2. {R:1}  - IRule parameter\n            // 3. {C:1}  - Condition Parameter\n            // 4. {function:xxx} - String function \n            // (unless we support Reload)\n            string parameter;\n            while (context.Next())\n            {\n                if (context.Current == CloseBrace)\n                {\n                    // This is just a server variable, so we do a lookup and verify the server variable exists.\n                    parameter = context.Capture();\n                    results.Add(ServerVariables.FindServerVariable(parameter, context, uriMatchPart));\n                    return;\n                }\n                else if (context.Current == Colon)\n                {\n                    parameter = context.Capture();\n\n                    // Only 5 strings to expect here. Case sensitive.\n                    switch (parameter)\n                    {\n                        case \"ToLower\":\n                            {\n                                var pattern = ParseString(context, uriMatchPart);\n                                results.Add(new ToLowerSegment(pattern));\n\n                                // at this point, we expect our context to be on the ending closing brace,\n                                // because the ParseString() call will increment the context until it \n                                // has processed the new string.\n                                if (context.Current != CloseBrace)\n                                {\n                                    throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));\n                                }\n                                return;\n                            }\n                        case \"UrlDecode\":\n                            {\n                                throw new NotImplementedException(\"UrlDecode is not implemented because of no great library available\");\n                            }\n                        case \"UrlEncode\":\n                            {\n                                var pattern = ParseString(context, uriMatchPart);\n                                results.Add(new UrlEncodeSegment(pattern));\n\n                                if (context.Current != CloseBrace)\n                                {\n                                    throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));\n                                }\n                                return;\n                            }\n                        case \"R\":\n                            {\n                                var index = GetBackReferenceIndex(context);\n                                results.Add(new RuleMatchSegment(index));\n                                return;\n                            }\n                        case \"C\":\n                            {\n                                var index = GetBackReferenceIndex(context);\n                                results.Add(new ConditionMatchSegment(index));\n                                return;\n                            }\n                        default:\n                            var rewriteMap = _rewriteMaps?[parameter];\n                            if (rewriteMap != null)\n                            {\n                                var pattern = ParseString(context, uriMatchPart);\n                                results.Add(new RewriteMapSegment(rewriteMap, pattern));\n                                return;\n                            }\n                            throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(parameter, context.Index));\n                    }\n                }\n            }\n            throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));\n        }\n\n        private static int GetBackReferenceIndex(ParserContext context)\n        {\n            if (!context.Next())\n            {\n                throw new FormatException(Resources.FormatError_InputParserNoBackreference(context.Index));\n            }\n\n            context.Mark();\n            while (context.Current != CloseBrace)\n            {\n                if (!context.Next())\n                {\n                    throw new FormatException(Resources.FormatError_InputParserMissingCloseBrace(context.Index));\n                }\n            }\n\n            var res = context.Capture();\n            int index;\n            if (!int.TryParse(res, NumberStyles.None, CultureInfo.InvariantCulture, out index))\n            {\n                throw new FormatException(Resources.FormatError_InputParserInvalidInteger(res, context.Index));\n            }\n\n            if (index > 9 || index < 0)\n            {\n                throw new FormatException(Resources.FormatError_InputParserIndexOutOfRange(res, context.Index));\n            }\n            return index;\n        }\n\n        private static void ParseLiteral(ParserContext context, IList<PatternSegment> results)\n        {\n            context.Mark();\n            string literal;\n            while (true)\n            {\n                if (context.Current == OpenBrace || context.Current == CloseBrace)\n                {\n                    literal = context.Capture();\n                    context.Back();\n                    break;\n                }\n\n                if (!context.Next())\n                {\n                    literal = context.Capture();\n                    break;\n                }\n            }\n\n            results.Add(new LiteralSegment(literal));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/InvalidUrlRewriteFormatException.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Xml;\nusing System.Xml.Linq;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class InvalidUrlRewriteFormatException : FormatException\n    {\n        public int LineNumber { get; }\n        public int LinePosition { get; }\n\n        public InvalidUrlRewriteFormatException(XElement element, string message)\n            : base(FormatMessage(element, message))\n        {\n        }\n\n        public InvalidUrlRewriteFormatException(XElement element, string message, Exception innerException)\n            : base(FormatMessage(element, message), innerException)\n        {\n            var xmlLineInfo = (IXmlLineInfo)element;\n            LineNumber = xmlLineInfo.LineNumber;\n            LinePosition = xmlLineInfo.LinePosition;\n        }\n\n        private static string FormatMessage(XElement element, string message)\n        {\n            var xmlLineInfo = (IXmlLineInfo)element;\n            return Resources.FormatError_UrlRewriteParseError(message, xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/LogicalGrouping.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public enum LogicalGrouping\n    {\n        MatchAll,\n        MatchAny\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/MatchType.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public enum MatchType\n    {\n        Pattern,\n        IsFile,\n        IsDirectory\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/PatternSyntax.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public enum PatternSyntax\n    {\n        ECMAScript,\n        Wildcard,\n        ExactMatch\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/RedirectType.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public enum RedirectType\n    {\n        Permanent = StatusCodes.Status301MovedPermanently,\n        Found = StatusCodes.Status302Found,\n        SeeOther = StatusCodes.Status303SeeOther,\n        Temporary = StatusCodes.Status307TemporaryRedirect\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/RewriteMapParser.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Linq;\nusing System.Xml.Linq;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public static class RewriteMapParser\n    {\n        public static IISRewriteMapCollection Parse(XElement xmlRoot)\n        {\n            if (xmlRoot == null)\n            {\n                throw new ArgumentNullException(nameof(xmlRoot));\n            }\n\n            var mapsElement = xmlRoot.Descendants(RewriteTags.RewriteMaps).SingleOrDefault();\n            if (mapsElement == null)\n            {\n                return null;\n            }\n\n            var rewriteMaps = new IISRewriteMapCollection();\n            foreach (var mapElement in mapsElement.Elements(RewriteTags.RewriteMap))\n            {\n                var map = new IISRewriteMap(mapElement.Attribute(RewriteTags.Name)?.Value);\n                foreach (var addElement in mapElement.Elements(RewriteTags.Add))\n                {\n                    map[addElement.Attribute(RewriteTags.Key).Value.ToLowerInvariant()] = addElement.Attribute(RewriteTags.Value).Value;\n                }\n                rewriteMaps.Add(map);\n            }\n\n            return rewriteMaps;\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/RewriteTags.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public static class RewriteTags\n    {\n        public const string Action = \"action\";\n        public const string Add = \"add\";\n        public const string AppendQueryString = \"appendQueryString\";\n        public const string Conditions = \"conditions\";\n        public const string Enabled = \"enabled\";\n        public const string GlobalRules = \"globalRules\";\n        public const string IgnoreCase = \"ignoreCase\";\n        public const string Input = \"input\";\n        public const string Key = \"key\";\n        public const string LogicalGrouping = \"logicalGrouping\";\n        public const string LogRewrittenUrl = \"logRewrittenUrl\";\n        public const string Match = \"match\";\n        public const string MatchPattern = \"matchPattern\";\n        public const string MatchType = \"matchType\";\n        public const string Name = \"name\";\n        public const string Negate = \"negate\";\n        public const string Pattern = \"pattern\";\n        public const string PatternSyntax = \"patternSyntax\";\n        public const string RedirectType = \"redirectType\";\n        public const string Rewrite = \"rewrite\";\n        public const string RewriteMap = \"rewriteMap\";\n        public const string RewriteMaps = \"rewriteMaps\";\n        public const string Rule = \"rule\";\n        public const string Rules = \"rules\";\n        public const string StatusCode = \"statusCode\";\n        public const string SubStatusCode = \"subStatusCode\";\n        public const string StatusDescription = \"statusDescription\";\n        public const string StatusReason = \"statusReason\";\n        public const string StopProcessing = \"stopProcessing\";\n        public const string TrackAllCaptures = \"trackAllCaptures\";\n        public const string Type = \"type\";\n        public const string Url = \"url\";\n        public const string Value = \"value\";\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/ServerVariables.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public static class ServerVariables\n    {\n        /// <summary>\n        /// Returns the matching <see cref=\"PatternSegment\"/> for the given <paramref name=\"serverVariable\"/>\n        /// </summary>\n        /// <param name=\"serverVariable\">The server variable</param>\n        /// <param name=\"context\">The parser context which is utilized when an exception is thrown</param>\n        /// <param name=\"uriMatchPart\">Indicates whether the full URI or the path should be evaluated for URL segments</param>\n        /// <exception cref=\"FormatException\">Thrown when the server variable is unknown</exception>\n        /// <returns>The matching <see cref=\"PatternSegment\"/></returns>\n        public static PatternSegment FindServerVariable(string serverVariable, ParserContext context, UriMatchPart uriMatchPart)\n        {\n            switch (serverVariable)\n            {\n                // TODO Add all server variables here.\n                case \"ALL_RAW\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"APP_POOL_ID\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"CONTENT_LENGTH\":\n                    return new HeaderSegment(HeaderNames.ContentLength);\n                case \"CONTENT_TYPE\":\n                    return new HeaderSegment(HeaderNames.ContentType);\n                case \"HTTP_ACCEPT\":\n                    return new HeaderSegment(HeaderNames.Accept);\n                case \"HTTP_COOKIE\":\n                    return new HeaderSegment(HeaderNames.Cookie);\n                case \"HTTP_HOST\":\n                    return new HeaderSegment(HeaderNames.Host);\n                case \"HTTP_REFERER\":\n                    return new HeaderSegment(HeaderNames.Referer);\n                case \"HTTP_USER_AGENT\":\n                    return new HeaderSegment(HeaderNames.UserAgent);\n                case \"HTTP_CONNECTION\":\n                    return new HeaderSegment(HeaderNames.Connection);\n                case \"HTTP_URL\":\n                    return new UrlSegment(uriMatchPart);\n                case \"HTTPS\":\n                    return new IsHttpsUrlSegment();\n                case \"LOCAL_ADDR\":\n                    return new LocalAddressSegment();\n                case \"HTTP_PROXY_CONNECTION\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"QUERY_STRING\":\n                    return new QueryStringSegment();\n                case \"REMOTE_ADDR\":\n                    return new RemoteAddressSegment();\n                case \"REMOTE_HOST\":\n                    throw new NotSupportedException(Resources.FormatError_UnsupportedServerVariable(serverVariable));\n                case \"REMOTE_PORT\":\n                    return new RemotePortSegment();\n                case \"REQUEST_FILENAME\":\n                    return new RequestFileNameSegment();\n                case \"REQUEST_METHOD\":\n                    return new RequestMethodSegment();\n                case \"REQUEST_URI\":\n                    return new UrlSegment(uriMatchPart);\n                default:\n                    throw new FormatException(Resources.FormatError_InputParserUnrecognizedParameter(serverVariable, context.Index));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/UriMatchCondition.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class UriMatchCondition : Condition\n    {\n        private TimeSpan _regexTimeout = TimeSpan.FromSeconds(1);\n\n        public UriMatchCondition(InputParser inputParser, string input, string pattern, UriMatchPart uriMatchPart, bool ignoreCase, bool negate)\n        {\n            var regexOptions = RegexOptions.CultureInvariant | RegexOptions.Compiled;\n            regexOptions = ignoreCase ? regexOptions | RegexOptions.IgnoreCase : regexOptions;\n            var regex = new Regex(\n                pattern,\n                regexOptions,\n                _regexTimeout\n            );\n            Input = inputParser.ParseInputString(input, uriMatchPart);\n            Match = new RegexMatch(regex, negate);\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/UriMatchPart.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public enum UriMatchPart\n    {\n        Full,\n        Path\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/UrlRewriteFileParser.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Xml.Linq;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class UrlRewriteFileParser\n    {\n        private InputParser _inputParser;\n\n        /// <summary>\n        /// Parse an IIS rewrite section into a list of <see cref=\"IISUrlRewriteRule\"/>s.\n        /// </summary>\n        /// <param name=\"reader\">The reader containing the rewrite XML</param>\n        public IList<IISUrlRewriteRule> Parse(TextReader reader)\n        {\n            var xmlDoc = XDocument.Load(reader, LoadOptions.SetLineInfo);\n            var xmlRoot = xmlDoc.Descendants(RewriteTags.Rewrite).FirstOrDefault();\n\n            if (xmlRoot == null)\n            {\n                return null;\n            }\n\n            _inputParser = new InputParser(RewriteMapParser.Parse(xmlRoot));\n\n            var result = new List<IISUrlRewriteRule>();\n            ParseRules(xmlRoot.Descendants(RewriteTags.GlobalRules).FirstOrDefault(), result, global: true);\n            ParseRules(xmlRoot.Descendants(RewriteTags.Rules).FirstOrDefault(), result, global: false);\n            return result;\n        }\n\n        private void ParseRules(XElement rules, IList<IISUrlRewriteRule> result, bool global)\n        {\n            if (rules == null)\n            {\n                return;\n            }\n\n            foreach (var rule in rules.Elements(RewriteTags.Rule))\n            {\n                var builder = new UrlRewriteRuleBuilder { Global = global };\n                ParseRuleAttributes(rule, builder);\n\n                if (builder.Enabled)\n                {\n                    result.Add(builder.Build());\n                }\n            }\n        }\n\n        private void ParseRuleAttributes(XElement rule, UrlRewriteRuleBuilder builder)\n        {\n            builder.Name = rule.Attribute(RewriteTags.Name)?.Value;\n\n            if (ParseBool(rule, RewriteTags.Enabled, defaultValue: true))\n            {\n                builder.Enabled = true;\n            }\n            else\n            {\n                return;\n            }\n\n            var patternSyntax = ParseEnum(rule, RewriteTags.PatternSyntax, PatternSyntax.ECMAScript);\n            var stopProcessing = ParseBool(rule, RewriteTags.StopProcessing, defaultValue: false);\n\n            var match = rule.Element(RewriteTags.Match);\n            if (match == null)\n            {\n                throw new InvalidUrlRewriteFormatException(rule, \"Condition must have an associated match\");\n            }\n\n            var action = rule.Element(RewriteTags.Action);\n            if (action == null)\n            {\n                throw new InvalidUrlRewriteFormatException(rule, \"Rule does not have an associated action attribute\");\n            }\n\n            ParseMatch(match, builder, patternSyntax);\n            ParseConditions(rule.Element(RewriteTags.Conditions), builder, patternSyntax);\n            ParseUrlAction(action, builder, stopProcessing);\n        }\n\n        private void ParseMatch(XElement match, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)\n        {\n            var parsedInputString = match.Attribute(RewriteTags.Url)?.Value;\n            if (parsedInputString == null)\n            {\n                throw new InvalidUrlRewriteFormatException(match, \"Match must have Url Attribute\");\n            }\n\n            var ignoreCase = ParseBool(match, RewriteTags.IgnoreCase, defaultValue: true);\n            var negate = ParseBool(match, RewriteTags.Negate, defaultValue: false);\n            builder.AddUrlMatch(parsedInputString, ignoreCase, negate, patternSyntax);\n        }\n\n        private void ParseConditions(XElement conditions, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)\n        {\n            if (conditions == null)\n            {\n                return;\n            }\n\n            var grouping = ParseEnum(conditions, RewriteTags.LogicalGrouping, LogicalGrouping.MatchAll);\n            var trackAllCaptures = ParseBool(conditions, RewriteTags.TrackAllCaptures, defaultValue: false);\n            builder.ConfigureConditionBehavior(grouping, trackAllCaptures);\n\n            foreach (var cond in conditions.Elements(RewriteTags.Add))\n            {\n                ParseCondition(cond, builder, patternSyntax);\n            }\n        }\n\n        private void ParseCondition(XElement conditionElement, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)\n        {\n            var ignoreCase = ParseBool(conditionElement, RewriteTags.IgnoreCase, defaultValue: true);\n            var negate = ParseBool(conditionElement, RewriteTags.Negate, defaultValue: false);\n            var matchType = ParseEnum(conditionElement, RewriteTags.MatchType, MatchType.Pattern);\n            var parsedInputString = conditionElement.Attribute(RewriteTags.Input)?.Value;\n\n            if (parsedInputString == null)\n            {\n                throw new InvalidUrlRewriteFormatException(conditionElement, \"Conditions must have an input attribute\");\n            }\n\n            var parsedPatternString = conditionElement.Attribute(RewriteTags.Pattern)?.Value;\n            Condition condition;\n\n            switch (patternSyntax)\n            {\n                case PatternSyntax.ECMAScript:\n                {\n                    switch (matchType)\n                    {\n                        case MatchType.Pattern:\n                        {\n                            if (string.IsNullOrEmpty(parsedPatternString))\n                            {\n                                throw new FormatException(\"Match does not have an associated pattern attribute in condition\");\n                            }\n                            condition = new UriMatchCondition(_inputParser, parsedInputString, parsedPatternString, builder.UriMatchPart, ignoreCase, negate);\n                            break;\n                        }\n                        case MatchType.IsDirectory:\n                        {\n                            condition = new Condition { Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new IsDirectoryMatch(negate) };\n                            break;\n                        }\n                        case MatchType.IsFile:\n                        {\n                            condition = new Condition { Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new IsFileMatch(negate) };\n                            break;\n                        }\n                        default:\n                            throw new FormatException(\"Unrecognized matchType\");\n                    }\n                    break;\n                }\n                case PatternSyntax.Wildcard:\n                    throw new NotSupportedException(\"Wildcard syntax is not supported\");\n                case PatternSyntax.ExactMatch:\n                    if (string.IsNullOrEmpty(parsedPatternString))\n                    {\n                        throw new FormatException(\"Match does not have an associated pattern attribute in condition\");\n                    }\n                    condition = new Condition { Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new ExactMatch(ignoreCase, parsedPatternString, negate) };\n                    break;\n                default:\n                    throw new FormatException(\"Unrecognized pattern syntax\");\n            }\n\n            builder.AddUrlCondition(condition);\n        }\n\n        private void ParseUrlAction(XElement urlAction, UrlRewriteRuleBuilder builder, bool stopProcessing)\n        {\n            var actionType = ParseEnum(urlAction, RewriteTags.Type, ActionType.None);\n            UrlAction action;\n            switch (actionType)\n            {\n                case ActionType.None:\n                    action = new NoneAction(stopProcessing ? RuleResult.SkipRemainingRules : RuleResult.ContinueRules);\n                    break;\n                case ActionType.Rewrite:\n                case ActionType.Redirect:\n                    var url = string.Empty;\n                    if (urlAction.Attribute(RewriteTags.Url) != null)\n                    {\n                        url = urlAction.Attribute(RewriteTags.Url).Value;\n                        if (string.IsNullOrEmpty(url))\n                        {\n                            throw new InvalidUrlRewriteFormatException(urlAction, \"Url attribute cannot contain an empty string\");\n                        }\n                    }\n\n                    var urlPattern = _inputParser.ParseInputString(url, builder.UriMatchPart);\n                    var appendQuery = ParseBool(urlAction, RewriteTags.AppendQueryString, defaultValue: true);\n\n                    if (actionType == ActionType.Rewrite)\n                    {\n                        action = new RewriteAction(stopProcessing ? RuleResult.SkipRemainingRules : RuleResult.ContinueRules, urlPattern, appendQuery);\n                    }\n                    else\n                    {\n                        var redirectType = ParseEnum(urlAction, RewriteTags.RedirectType, RedirectType.Permanent);\n                        action = new RedirectAction((int)redirectType, urlPattern, appendQuery);\n                    }\n                    break;\n                case ActionType.AbortRequest:\n                    action = new AbortAction();\n                    break;\n                case ActionType.CustomResponse:\n                    int statusCode;\n                    if (!int.TryParse(urlAction.Attribute(RewriteTags.StatusCode)?.Value, NumberStyles.None, CultureInfo.InvariantCulture, out statusCode))\n                    {\n                        throw new InvalidUrlRewriteFormatException(urlAction, \"A valid status code is required\");\n                    }\n\n                    if (statusCode < 200 || statusCode > 999)\n                    {\n                        throw new NotSupportedException(\"Status codes must be between 200 and 999 (inclusive)\");\n                    }\n\n                    if (!string.IsNullOrEmpty(urlAction.Attribute(RewriteTags.SubStatusCode)?.Value))\n                    {\n                        throw new NotSupportedException(\"Substatus codes are not supported\");\n                    }\n\n                    var statusReason = urlAction.Attribute(RewriteTags.StatusReason)?.Value;\n                    var statusDescription = urlAction.Attribute(RewriteTags.StatusDescription)?.Value;\n\n                    action = new CustomResponseAction(statusCode) { StatusReason = statusReason, StatusDescription = statusDescription };\n                    break;\n                default:\n                    throw new NotSupportedException($\"The action type {actionType} wasn't recognized\");\n            }\n            builder.AddUrlAction(action);\n        }\n\n        private bool ParseBool(XElement element, string rewriteTag, bool defaultValue)\n        {\n            bool result;\n            var attribute = element.Attribute(rewriteTag);\n            if (attribute == null)\n            {\n                return defaultValue;\n            }\n            else if (!bool.TryParse(attribute.Value, out result))\n            {\n                throw new InvalidUrlRewriteFormatException(element, $\"The {rewriteTag} parameter '{attribute.Value}' was not recognized\");\n            }\n            return result;\n        }\n\n        private TEnum ParseEnum<TEnum>(XElement element, string rewriteTag, TEnum defaultValue)\n            where TEnum : struct\n        {\n            TEnum enumResult = default(TEnum);\n            var attribute = element.Attribute(rewriteTag);\n            if (attribute == null)\n            {\n                return defaultValue;\n            }\n            else if(!Enum.TryParse(attribute.Value, ignoreCase: true, result: out enumResult))\n            {\n                throw new InvalidUrlRewriteFormatException(element, $\"The {rewriteTag} parameter '{attribute.Value}' was not recognized\");\n            }\n            return enumResult;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/UrlRewriteRuleBuilder.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite\n{\n    public class UrlRewriteRuleBuilder\n    {\n        private readonly TimeSpan _regexTimeout = TimeSpan.FromSeconds(1);\n\n        public string Name { get; set; }\n        public bool Enabled { get; set; }\n        public bool Global { get; set; }\n        public UriMatchPart UriMatchPart => Global ? UriMatchPart.Full : UriMatchPart.Path;\n\n        private UrlMatch _initialMatch;\n        private ConditionCollection _conditions;\n        private UrlAction _action;\n\n        public IISUrlRewriteRule Build()\n        {\n            if (_initialMatch == null || _action == null)\n            {\n                throw new InvalidOperationException(\"Cannot create UrlRewriteRule without action and match\");\n            }\n\n            return new IISUrlRewriteRule(Name, _initialMatch, _conditions, _action, Global);\n        }\n\n        public void AddUrlAction(UrlAction action)\n        {\n            if (action == null)\n            {\n                throw new ArgumentNullException(nameof(action), \"Rules must contain an action\");\n            }\n            _action = action;\n        }\n\n        public void AddUrlMatch(string input, bool ignoreCase = true, bool negate = false, PatternSyntax patternSyntax = PatternSyntax.ECMAScript)\n        {\n            switch (patternSyntax)\n            {\n                case PatternSyntax.ECMAScript:\n                    {\n                        if (ignoreCase)\n                        {\n                            var regex = new Regex(input, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, _regexTimeout);\n                            _initialMatch = new RegexMatch(regex, negate);\n                        }\n                        else\n                        {\n                            var regex = new Regex(input, RegexOptions.CultureInvariant | RegexOptions.Compiled, _regexTimeout);\n                            _initialMatch = new RegexMatch(regex, negate);\n                        }\n                        break;\n                    }\n                case PatternSyntax.Wildcard:\n                    throw new NotSupportedException(\"Wildcard syntax is not supported\");\n                case PatternSyntax.ExactMatch:\n                    _initialMatch = new ExactMatch(ignoreCase, input, negate);\n                    break;\n            }\n        }\n\n        public void ConfigureConditionBehavior(LogicalGrouping logicalGrouping, bool trackAllCaptures)\n        {\n            _conditions = new ConditionCollection(logicalGrouping, trackAllCaptures);\n        }\n\n        public void AddUrlCondition(Condition condition)\n        {\n            if (_conditions == null)\n            {\n                throw new InvalidOperationException($\"You must first configure condition behavior by calling {nameof(ConfigureConditionBehavior)}\");\n            }\n            if (condition == null)\n            {\n                throw new ArgumentNullException(nameof(condition));\n            }\n            _conditions.Add(condition);\n        }\n\n        public void AddUrlConditions(IEnumerable<Condition> conditions)\n        {\n            if (_conditions == null)\n            {\n                throw new InvalidOperationException($\"You must first configure condition behavior by calling {nameof(ConfigureConditionBehavior)}\");\n            }\n            _conditions.AddConditions(conditions);\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/MatchResults.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text.RegularExpressions;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public class MatchResults\n    {\n        public static readonly MatchResults EmptySuccess = new MatchResults { Success = true };\n        public static readonly MatchResults EmptyFailure = new MatchResults { Success = false };\n\n        public bool Success { get; set; }\n        public BackReferenceCollection BackReferences { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/ParserContext.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    /// <summary>\n    /// Represents a string iterator, with captures.\n    /// </summary>\n    public class ParserContext\n    {\n        public readonly string Template;\n        public int Index { get; set; }\n        private int? _mark;\n\n        public ParserContext(string condition)\n        {\n            Template = condition;\n            Index = -1;\n        }\n\n        public char Current => (Index < Template.Length && Index >= 0) ? Template[Index] : (char)0;\n\n        public bool Back()\n        {\n            return --Index >= 0;\n        }\n\n        public bool Next()\n        {\n            return ++Index < Template.Length;\n        }\n\n        public bool HasNext()\n        {\n            return (Index + 1) < Template.Length;\n        }\n\n        public void Mark()\n        {\n            _mark = Index;\n        }\n\n        public int GetIndex()\n        {\n            return Index;\n        }\n\n        public string Capture()\n        {\n            // TODO make this return a range rather than a string.\n            if (_mark.HasValue)\n            {\n                var value = Template.Substring(_mark.Value, Index - _mark.Value);\n                _mark = null;\n                return value;\n            }\n            else\n            {\n                return null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/Pattern.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public class Pattern\n    {\n        public IList<PatternSegment> PatternSegments { get; }\n        public Pattern(IList<PatternSegment> patternSegments)\n        {\n            PatternSegments = patternSegments;\n        }\n\n        public string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            foreach (var pattern in PatternSegments)\n            {\n                context.Builder.Append(pattern.Evaluate(context, ruleBackReferences, conditionBackReferences));\n            }\n            var retVal = context.Builder.ToString();\n            context.Builder.Clear();\n            return retVal;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public abstract class PatternSegment\n    {\n        public abstract string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/ConditionMatchSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class ConditionMatchSegment : PatternSegment\n    {\n        private readonly int _index;\n\n        public ConditionMatchSegment(int index)\n        {\n            _index = index;\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return conditionBackReferences?[_index];\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/DateTimeSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Globalization;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class DateTimeSegment : PatternSegment\n    {\n        private readonly DateTimePortion _portion;\n\n        public DateTimeSegment(string segment)\n        {\n            switch (segment)\n            {\n                case \"TIME_YEAR\":\n                    _portion = DateTimePortion.Year;\n                    break;\n                case \"TIME_MON\":\n                    _portion = DateTimePortion.Month;\n                    break;\n                case \"TIME_DAY\":\n                    _portion = DateTimePortion.Day;\n                    break;\n                case \"TIME_HOUR\":\n                    _portion = DateTimePortion.Hour;\n                    break;\n                case \"TIME_MIN\":\n                    _portion = DateTimePortion.Minute;\n                    break;\n                case \"TIME_SEC\":\n                    _portion = DateTimePortion.Second;\n                    break;\n                case \"TIME_WDAY\":\n                    _portion = DateTimePortion.DayOfWeek;\n                    break;\n                case \"TIME\":\n                    _portion = DateTimePortion.Time;\n                    break;\n                default:\n                    throw new FormatException($\"Unsupported segment: '{segment}'\");\n            }\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReference)\n        {\n            switch (_portion)\n            {\n                case DateTimePortion.Year:\n                    return DateTimeOffset.UtcNow.Year.ToString(CultureInfo.InvariantCulture);\n                case DateTimePortion.Month:\n                    return DateTimeOffset.UtcNow.Month.ToString(CultureInfo.InvariantCulture);\n                case DateTimePortion.Day:\n                    return DateTimeOffset.UtcNow.Day.ToString(CultureInfo.InvariantCulture);\n                case DateTimePortion.Hour:\n                    return DateTimeOffset.UtcNow.Hour.ToString(CultureInfo.InvariantCulture);\n                case DateTimePortion.Minute:\n                    return DateTimeOffset.UtcNow.Minute.ToString(CultureInfo.InvariantCulture);\n                case DateTimePortion.Second:\n                    return DateTimeOffset.UtcNow.Second.ToString(CultureInfo.InvariantCulture);\n                case DateTimePortion.DayOfWeek:\n                    return ((int)DateTimeOffset.UtcNow.DayOfWeek).ToString(CultureInfo.InvariantCulture);\n                case DateTimePortion.Time:\n                    return DateTimeOffset.UtcNow.ToString(CultureInfo.InvariantCulture);\n                default:\n                    return string.Empty;\n            }\n        }\n\n        private enum DateTimePortion\n        {\n            Year,\n            Month,\n            Day,\n            Hour,\n            Minute,\n            Second,\n            DayOfWeek,\n            Time\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/HeaderSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class HeaderSegment : PatternSegment\n    {\n        private readonly string _header;\n\n        public HeaderSegment(string header)\n        {\n            _header = header;\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Request.Headers[_header];\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/IsHttpsModSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class IsHttpsModSegment : PatternSegment\n    {\n        // Note: Mod rewrite pattern matches on lower case \"on\" and \"off\"\n        // while IIS looks for capitalized \"ON\" and \"OFF\"\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Request.IsHttps ? \"on\" : \"off\";\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/IsHttpsUrlSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class IsHttpsUrlSegment : PatternSegment\n    {\n        // Note: Mod rewrite pattern matches on lower case \"on\" and \"off\"\n        // while IIS looks for capitalized \"ON\" and \"OFF\"\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Request.IsHttps ? \"ON\" : \"OFF\";\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/IsIPV6Segment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Net.Sockets;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n\n    public class IsIPV6Segment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            if (context.HttpContext.Connection.RemoteIpAddress == null)\n            {\n                return \"off\";\n            }\n            return context.HttpContext.Connection.RemoteIpAddress.AddressFamily == AddressFamily.InterNetworkV6 ? \"on\" : \"off\";\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/LiteralSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class LiteralSegment : PatternSegment\n    {\n        private readonly string _literal;\n\n        public LiteralSegment(string literal)\n        {\n            _literal = literal;\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return _literal;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/LocalAddressSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class LocalAddressSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Connection.LocalIpAddress?.ToString();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/LocalPortSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Globalization;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class LocalPortSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Connection.LocalPort.ToString(CultureInfo.InvariantCulture);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/QueryStringSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class QueryStringSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackRefernces, BackReferenceCollection conditionBackReferences)\n        {\n            var queryString = context.HttpContext.Request.QueryString.ToString();\n\n            if (!string.IsNullOrEmpty(queryString))\n            {\n                return queryString.Substring(1);\n            }\n\n            return queryString;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RemoteAddressSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class RemoteAddressSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Connection.RemoteIpAddress?.ToString();\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RemotePortSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Globalization;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class RemotePortSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Connection.RemotePort.ToString(CultureInfo.InvariantCulture);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RequestFilenameSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class RequestFileNameSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Request.Path;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RequestMethodSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class RequestMethodSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Request.Method;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RewriteMapSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class RewriteMapSegment : PatternSegment\n    {\n        private readonly IISRewriteMap _rewriteMap;\n        private readonly Pattern _pattern;\n\n        public RewriteMapSegment(IISRewriteMap rewriteMap, Pattern pattern)\n        {\n            _rewriteMap = rewriteMap;\n            _pattern = pattern;\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            var key = _pattern.Evaluate(context, ruleBackReferences, conditionBackReferences).ToLowerInvariant();\n            return _rewriteMap[key];\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RuleMatchSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class RuleMatchSegment : PatternSegment\n    {\n        private readonly int _index;\n\n        public RuleMatchSegment(int index)\n        {\n            _index = index;\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return ruleBackReferences[_index];\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/SchemeSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class SchemeSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Request.Scheme;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/ServerProtocolSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http.Features;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class ServerProtocolSegment : PatternSegment\n    {\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return context.HttpContext.Features.Get<IHttpRequestFeature>()?.Protocol;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/ToLowerSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class ToLowerSegment : PatternSegment\n    {\n        private readonly Pattern _pattern;\n\n        public ToLowerSegment(Pattern pattern)\n        {\n            _pattern = pattern;\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            // PERF as we share the string builder across the context, we need to make a new one here to evaluate\n            // lowercase segments.\n            var tempBuilder = context.Builder;\n            context.Builder = new StringBuilder(64);\n            var pattern = _pattern.Evaluate(context, ruleBackReferences, conditionBackReferences);\n            context.Builder = tempBuilder;\n            return pattern.ToLowerInvariant();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/UrlEncodeSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text;\nusing System.Text.Encodings.Web;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class UrlEncodeSegment : PatternSegment\n    {\n        private readonly Pattern _pattern;\n\n        public UrlEncodeSegment(Pattern pattern)\n        {\n            _pattern = pattern;\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            var oldBuilder = context.Builder;\n            // PERF \n            // Because we need to be able to evaluate multiple nested patterns,\n            // we provided a new string builder and evaluate the new pattern,\n            // and restore it after evaluation.\n            context.Builder = new StringBuilder(64);\n            var pattern = _pattern.Evaluate(context, ruleBackReferences, conditionBackReferences);\n            context.Builder = oldBuilder;\n            return UrlEncoder.Default.Encode(pattern);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/UrlSegment.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http.Extensions;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments\n{\n    public class UrlSegment : PatternSegment\n    {\n        private readonly UriMatchPart _uriMatchPart;\n\n        public UrlSegment()\n            : this(UriMatchPart.Path)\n        {\n        }\n\n        public UrlSegment(UriMatchPart uriMatchPart)\n        {\n            _uriMatchPart = uriMatchPart;\n        }\n\n        public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            return _uriMatchPart == UriMatchPart.Full ? context.HttpContext.Request.GetEncodedUrl() : (string)context.HttpContext.Request.Path;\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/RedirectRule.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Net.Http.Headers;\nusing Microsoft.AspNetCore.Rewrite.Logging;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public class RedirectRule : IRule\n    {\n        private readonly TimeSpan _regexTimeout = TimeSpan.FromSeconds(1);\n        public Regex InitialMatch { get; }\n        public string Replacement { get; }\n        public int StatusCode { get; }\n        public RedirectRule(string regex, string replacement, int statusCode)\n        {\n            if (string.IsNullOrEmpty(regex))\n            {\n                throw new ArgumentException(nameof(regex));\n            }\n\n            if (string.IsNullOrEmpty(replacement))\n            {\n                throw new ArgumentException(nameof(replacement));\n            }\n\n            InitialMatch = new Regex(regex, RegexOptions.Compiled | RegexOptions.CultureInvariant, _regexTimeout);\n            Replacement = replacement;\n            StatusCode = statusCode;\n        }\n\n        public virtual void ApplyRule(RewriteContext context)\n        {\n            var path = context.HttpContext.Request.Path;\n            var pathBase = context.HttpContext.Request.PathBase;\n\n            Match initMatchResults;\n            if (path == PathString.Empty)\n            {\n                initMatchResults = InitialMatch.Match(path.ToString());\n            }\n            else\n            {\n                initMatchResults = InitialMatch.Match(path.ToString().Substring(1));\n            }\n\n\n            if (initMatchResults.Success)\n            {\n                var newPath = initMatchResults.Result(Replacement);\n                var response = context.HttpContext.Response;\n\n                response.StatusCode = StatusCode;\n                context.Result = RuleResult.EndResponse;\n\n                if (string.IsNullOrEmpty(newPath))\n                {\n                    response.Headers[HeaderNames.Location] = pathBase.HasValue ? pathBase.Value : \"/\";\n                    return;\n                }\n\n                if (newPath.IndexOf(\"://\", StringComparison.Ordinal) == -1 && newPath[0] != '/')\n                {\n                    newPath = '/' + newPath;\n                }\n\n                var split = newPath.IndexOf('?');\n                if (split >= 0)\n                {\n                    var query = context.HttpContext.Request.QueryString.Add(\n                        QueryString.FromUriComponent(\n                            newPath.Substring(split)));\n                    // not using the HttpContext.Response.redirect here because status codes may be 301, 302, 307, 308\n                    response.Headers[HeaderNames.Location] = pathBase + newPath.Substring(0, split) + query;\n                }\n                else\n                {\n                    response.Headers[HeaderNames.Location] = pathBase + newPath + context.HttpContext.Request.QueryString;\n                }\n\n                context.Logger?.RedirectedSummary(newPath);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/RedirectToHttpsRule.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Logging;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public class RedirectToHttpsRule : IRule\n    {\n        public int? SSLPort { get; set; }\n        public int StatusCode { get; set; }\n\n        public virtual void ApplyRule(RewriteContext context)\n        {\n            if (!context.HttpContext.Request.IsHttps)\n            {\n                var host = context.HttpContext.Request.Host;\n                if (SSLPort.HasValue && SSLPort.Value > 0)\n                {\n                    // a specific SSL port is specified\n                    host = new HostString(host.Host, SSLPort.Value);\n                }\n                else\n                {\n                    // clear the port\n                    host = new HostString(host.Host);\n                }\n\n                var req = context.HttpContext.Request;\n                var newUrl = new StringBuilder().Append(\"https://\").Append(host).Append(req.PathBase).Append(req.Path).Append(req.QueryString);\n                var response = context.HttpContext.Response;\n                response.StatusCode = StatusCode;\n                response.Headers[HeaderNames.Location] = newUrl.ToString();\n                context.Result = RuleResult.EndResponse;\n                context.Logger?.RedirectedToHttps();\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/RedirectToWwwRule.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Extensions;\nusing Microsoft.AspNetCore.Rewrite.Logging;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public class RedirectToWwwRule : IRule\n    {\n        public readonly int _statusCode;\n\n        public RedirectToWwwRule(int statusCode)\n        {\n            _statusCode = statusCode;\n        }\n\n        public virtual void ApplyRule(RewriteContext context)\n        {\n            var req = context.HttpContext.Request;\n            if (req.Host.Host.Equals(\"localhost\", StringComparison.OrdinalIgnoreCase))\n            {\n                context.Result = RuleResult.ContinueRules;\n                return;\n            }\n\n            if (req.Host.Value.StartsWith(\"www.\", StringComparison.OrdinalIgnoreCase))\n            {\n                context.Result = RuleResult.ContinueRules;\n                return;\n            }\n\n            var wwwHost = new HostString($\"www.{req.Host.Value}\");\n            var newUrl = UriHelper.BuildAbsolute(req.Scheme, wwwHost, req.PathBase, req.Path, req.QueryString);\n            var response = context.HttpContext.Response;\n            response.StatusCode = _statusCode;\n            response.Headers[HeaderNames.Location] = newUrl;\n            context.Result = RuleResult.EndResponse;\n            context.Logger?.RedirectedToWww();\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/RewriteRule.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Extensions;\nusing Microsoft.AspNetCore.Rewrite.Logging;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public class RewriteRule : IRule\n    {\n        private readonly TimeSpan _regexTimeout = TimeSpan.FromSeconds(1);\n        public Regex InitialMatch { get; }\n        public string Replacement { get; }\n        public bool StopProcessing { get; }\n        public RewriteRule(string regex, string replacement, bool stopProcessing)\n        {\n            if (string.IsNullOrEmpty(regex))\n            {\n                throw new ArgumentException(nameof(regex));\n            }\n\n            if (string.IsNullOrEmpty(replacement))\n            {\n                throw new ArgumentException(nameof(replacement));\n            }\n\n            InitialMatch = new Regex(regex, RegexOptions.Compiled | RegexOptions.CultureInvariant, _regexTimeout);\n            Replacement = replacement;\n            StopProcessing = stopProcessing;\n        }\n\n        public virtual void ApplyRule(RewriteContext context)\n        {\n            var path = context.HttpContext.Request.Path;\n            Match initMatchResults;\n            if (path == PathString.Empty)\n            {\n                initMatchResults = InitialMatch.Match(path.ToString());\n            }\n            else\n            {\n                initMatchResults = InitialMatch.Match(path.ToString().Substring(1));\n            }\n\n            if (initMatchResults.Success)\n            {\n                var result = initMatchResults.Result(Replacement);\n                var request = context.HttpContext.Request;\n\n                if (StopProcessing)\n                {\n                    context.Result = RuleResult.SkipRemainingRules;\n                }\n\n                if (string.IsNullOrEmpty(result))\n                {\n                    result = \"/\";\n                }\n\n                if (result.IndexOf(\"://\", StringComparison.Ordinal) >= 0)\n                {\n                    string scheme;\n                    HostString host;\n                    PathString pathString;\n                    QueryString query;\n                    FragmentString fragment;\n                    UriHelper.FromAbsolute(result, out scheme, out host, out pathString, out query, out fragment);\n\n                    request.Scheme = scheme;\n                    request.Host = host;\n                    request.Path = pathString;\n                    request.QueryString = query.Add(request.QueryString);\n                }\n                else\n                {\n                    var split = result.IndexOf('?');\n                    if (split >= 0)\n                    {\n                        var newPath = result.Substring(0, split);\n                        if (newPath[0] == '/')\n                        {\n                            request.Path = PathString.FromUriComponent(newPath);\n                        }\n                        else\n                        {\n                            request.Path = PathString.FromUriComponent('/' + newPath);\n                        }\n                        request.QueryString = request.QueryString.Add(\n                            QueryString.FromUriComponent(\n                                result.Substring(split)));\n                    }\n                    else\n                    {\n                        if (result[0] == '/')\n                        {\n                            request.Path = PathString.FromUriComponent(result);\n                        }\n                        else\n                        {\n                            request.Path = PathString.FromUriComponent('/' + result);\n                        }\n                    }\n                }\n\n                context.Logger?.RewriteSummary(result);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public abstract class UrlAction\n    {\n        protected Pattern Url { get; set; }\n        public abstract void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/AbortAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Rewrite.Logging;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions\n{\n    public class AbortAction : UrlAction\n    {\n        public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            context.HttpContext.Abort();\n            context.Result = RuleResult.EndResponse;\n            context.Logger?.AbortedRequest(context.HttpContext.Request.Path + context.HttpContext.Request.QueryString);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/ChangeCookieAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Http;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions\n{\n    public class ChangeCookieAction : UrlAction\n    {\n        private readonly Func<DateTimeOffset> _timeSource;\n        private CookieOptions _cachedOptions;\n\n        public ChangeCookieAction(string name)\n            : this(name, () => DateTimeOffset.UtcNow)\n        {\n        }\n\n        // for testing\n        internal ChangeCookieAction(string name, Func<DateTimeOffset> timeSource)\n        {\n            _timeSource = timeSource;\n\n            if (string.IsNullOrEmpty(name))\n            {\n                throw new ArgumentException(nameof(name));\n            }\n\n            Name = name;\n        }\n\n        public string Name { get; }\n        public string Value { get; set; }\n        public string Domain { get; set; }\n        public TimeSpan Lifetime { get; set; }\n        public string Path { get; set; }\n        public bool Secure { get; set; }\n        public bool HttpOnly { get; set; }\n\n        public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            var options = GetOrCreateOptions();\n            context.HttpContext.Response.Cookies.Append(Name, Value ?? string.Empty, options);\n        }\n\n        private CookieOptions GetOrCreateOptions()\n        {\n            if (Lifetime > TimeSpan.Zero)\n            {\n                var now = _timeSource();\n                return new CookieOptions()\n                {\n                    Domain = Domain,\n                    HttpOnly = HttpOnly,\n                    Secure = Secure,\n                    Path = Path,\n                    Expires = now.Add(Lifetime)\n                };\n            }\n\n            if (_cachedOptions == null)\n            {\n                _cachedOptions = new CookieOptions()\n                {\n                    Domain = Domain,\n                    HttpOnly = HttpOnly,\n                    Secure = Secure,\n                    Path = Path\n                };\n            }\n\n            return _cachedOptions;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/CustomResponseAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text;\nusing Microsoft.AspNetCore.Http.Extensions;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.AspNetCore.Rewrite.Logging;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions\n{\n    public class CustomResponseAction : UrlAction\n    {\n        public int StatusCode { get; }\n        public string StatusReason { get; set; }\n        public string StatusDescription { get; set; }\n\n        public CustomResponseAction(int statusCode)\n        {\n            StatusCode = statusCode;\n        }\n\n        public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            var response = context.HttpContext.Response;\n            response.StatusCode = StatusCode;\n\n            if (!string.IsNullOrEmpty(StatusReason))\n            {\n                context.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = StatusReason;\n            }\n\n            if (!string.IsNullOrEmpty(StatusDescription))\n            {\n                var content = Encoding.UTF8.GetBytes(StatusDescription);\n                response.ContentLength = content.Length;\n                response.ContentType = \"text/plain; charset=utf-8\";\n                response.Body.Write(content, 0, content.Length);\n            }\n\n            context.Result = RuleResult.EndResponse;\n\n            context.Logger?.CustomResponse(context.HttpContext.Request.GetEncodedUrl());\n        }\n    }\n}"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/ForbiddenAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions\n{\n    public class ForbiddenAction : UrlAction\n    {\n        public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden;\n            context.Result = RuleResult.EndResponse;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/GoneAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions\n{\n    public class GoneAction : UrlAction\n    {\n        public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            context.HttpContext.Response.StatusCode = StatusCodes.Status410Gone;\n            context.Result = RuleResult.EndResponse;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/NoneAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions\n{\n    public class NoneAction : UrlAction\n    {\n        public RuleResult Result { get; }\n\n        public NoneAction(RuleResult result)\n        {\n            Result = result;\n        }\n        // Explicitly say that nothing happens\n        public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            context.Result = Result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RedirectAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions\n{\n    public class RedirectAction : UrlAction\n    {\n        public int StatusCode { get; }\n        public bool QueryStringAppend { get; }\n        public bool QueryStringDelete { get; }\n        public bool EscapeBackReferences { get; }\n\n        public RedirectAction(\n            int statusCode,\n            Pattern pattern,\n            bool queryStringAppend,\n            bool queryStringDelete,\n            bool escapeBackReferences)\n        {\n            StatusCode = statusCode;\n            Url = pattern;\n            QueryStringAppend = queryStringAppend;\n            QueryStringDelete = queryStringDelete;\n            EscapeBackReferences = escapeBackReferences;\n        }\n\n        public RedirectAction(\n            int statusCode,\n            Pattern pattern,\n            bool queryStringAppend)\n            : this(\n                statusCode,\n                pattern,\n                queryStringAppend,\n                queryStringDelete: true,\n                escapeBackReferences: false)\n        {\n        }\n\n        public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            var pattern = Url.Evaluate(context, ruleBackReferences, conditionBackReferences);\n            var response = context.HttpContext.Response;\n            var pathBase = context.HttpContext.Request.PathBase;\n            if (EscapeBackReferences)\n            {\n                // because escapebackreferences will be encapsulated by the pattern, just escape the pattern\n                pattern = Uri.EscapeDataString(pattern);\n            }\n\n            if (string.IsNullOrEmpty(pattern))\n            {\n                response.Headers[HeaderNames.Location] = pathBase.HasValue ? pathBase.Value : \"/\";\n                return;\n            }\n\n\n            if (pattern.IndexOf(\"://\", StringComparison.Ordinal) == -1 && pattern[0] != '/')\n            {\n                pattern = '/' + pattern;\n            }\n            response.StatusCode = StatusCode;\n\n            // url can either contain the full url or the path and query\n            // always add to location header.\n            // TODO check for false positives\n            var split = pattern.IndexOf('?');\n            if (split >= 0 && QueryStringAppend)\n            {\n                var query = context.HttpContext.Request.QueryString.Add(\n                    QueryString.FromUriComponent(\n                        pattern.Substring(split)));\n\n                // not using the response.redirect here because status codes may be 301, 302, 307, 308\n                response.Headers[HeaderNames.Location] = pathBase + pattern.Substring(0, split) + query;\n            }\n            else\n            {\n                // If the request url has a query string and the target does not, append the query string\n                // by default.\n                if (QueryStringDelete)\n                {\n                    response.Headers[HeaderNames.Location] = pathBase + pattern;\n                }\n                else\n                {\n                    response.Headers[HeaderNames.Location] = pathBase + pattern + context.HttpContext.Request.QueryString;\n                }\n            }\n            context.Result = RuleResult.EndResponse;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/RewriteAction.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Extensions;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions\n{\n    public class RewriteAction : UrlAction\n    {\n        public RuleResult Result { get; }\n        public bool QueryStringAppend { get; }\n        public bool QueryStringDelete { get; }\n        public bool EscapeBackReferences { get; }\n\n        public RewriteAction(\n            RuleResult result,\n            Pattern pattern,\n            bool queryStringAppend,\n            bool queryStringDelete,\n            bool escapeBackReferences)\n        {\n            // For the replacement, we must have at least\n            // one segment (cannot have an empty replacement)\n            Result = result;\n            Url = pattern;\n            QueryStringAppend = queryStringAppend;\n            QueryStringDelete = queryStringDelete;\n            EscapeBackReferences = escapeBackReferences;\n        }\n\n        public RewriteAction(\n            RuleResult result,\n            Pattern pattern,\n            bool queryStringAppend) :\n            this(result,\n                pattern,\n                queryStringAppend,\n                queryStringDelete: false,\n                escapeBackReferences: false)\n        {\n\n        }\n\n        public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences)\n        {\n            var pattern = Url.Evaluate(context, ruleBackReferences, conditionBackReferences);\n            var request = context.HttpContext.Request;\n\n            if (string.IsNullOrEmpty(pattern))\n            {\n                pattern = \"/\";\n            }\n\n            if (EscapeBackReferences)\n            {\n                // because escapebackreferences will be encapsulated by the pattern, just escape the pattern\n                pattern = Uri.EscapeDataString(pattern);\n            }\n\n\n            // TODO PERF, substrings, object creation, etc.\n            if (pattern.IndexOf(\"://\", StringComparison.Ordinal) >= 0)\n            {\n                string scheme;\n                HostString host;\n                PathString path;\n                QueryString query;\n                FragmentString fragment;\n                UriHelper.FromAbsolute(pattern, out scheme, out host, out path, out query, out fragment);\n\n                if (query.HasValue)\n                {\n                    if (QueryStringAppend)\n                    {\n                        request.QueryString = request.QueryString.Add(query);\n                    }\n                    else\n                    {\n                        request.QueryString = query;\n                    }\n                }\n                else if (QueryStringDelete)\n                {\n                    request.QueryString = QueryString.Empty;\n                }\n\n                request.Scheme = scheme;\n                request.Host = host;\n                request.Path = path;\n            }\n            else\n            {\n                var split = pattern.IndexOf('?');\n                if (split >= 0)\n                {\n                    var path = pattern.Substring(0, split);\n                    if (path[0] == '/')\n                    {\n                        request.Path = PathString.FromUriComponent(path);\n                    }\n                    else\n                    {\n                        request.Path = PathString.FromUriComponent('/' + path);\n                    }\n\n                    if (QueryStringAppend)\n                    {\n                        request.QueryString = request.QueryString.Add(\n                            QueryString.FromUriComponent(\n                                pattern.Substring(split)));\n                    }\n                    else\n                    {\n                        request.QueryString = QueryString.FromUriComponent(\n                            pattern.Substring(split));\n                    }\n                }\n                else\n                {\n                    if (pattern[0] == '/')\n                    {\n                        request.Path = PathString.FromUriComponent(pattern);\n                    }\n                    else\n                    {\n                        request.Path = PathString.FromUriComponent('/' + pattern);\n                    }\n\n                    if (QueryStringDelete)\n                    {\n                        request.QueryString = QueryString.Empty;\n                    }\n                }\n            }\n            context.Result = Result;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatch.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal\n{\n    public abstract class UrlMatch\n    {\n        protected bool Negate { get; set; }\n        public abstract MatchResults Evaluate(string input, RewriteContext context);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/ExactMatch.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public class ExactMatch : UrlMatch\n    {\n        private readonly bool _ignoreCase;\n        private readonly string _stringMatch;\n\n        public ExactMatch(bool ignoreCase, string input, bool negate)\n        {\n            _ignoreCase = ignoreCase;\n            _stringMatch = input;\n            Negate = negate;\n        }\n\n        public override MatchResults Evaluate(string pattern, RewriteContext context)\n        {\n            var pathMatch = string.Compare(pattern, _stringMatch, _ignoreCase);\n            var success = ((pathMatch == 0) != Negate);\n            if (success)\n            {\n                return new MatchResults { Success = success, BackReferences = new BackReferenceCollection(pattern) };\n            }\n            else\n            {\n                return MatchResults.EmptyFailure;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/FileSizeMatch.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public class FileSizeMatch : UrlMatch\n    {\n        public FileSizeMatch(bool negate)\n        {\n            Negate = negate;\n        }\n\n        public override MatchResults Evaluate(string input, RewriteContext context)\n        {\n            var fileInfo = context.StaticFileProvider.GetFileInfo(input);\n            return fileInfo.Exists && fileInfo.Length > 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IntegerMatch.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Globalization;\nusing Microsoft.AspNetCore.Rewrite;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public class IntegerMatch : UrlMatch\n    {\n        private readonly int _value;\n        private readonly IntegerOperationType _operation;\n        public IntegerMatch(int value, IntegerOperationType operation)\n        {\n            _value = value;\n            _operation = operation;\n        }\n\n        public IntegerMatch(string value, IntegerOperationType operation)\n        {\n            int compValue;\n            if (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out compValue))\n            {\n                throw new FormatException(Resources.Error_IntegerMatch_FormatExceptionMessage);\n            }\n            _value = compValue;\n            _operation = operation;\n        }\n\n        public override MatchResults Evaluate(string input, RewriteContext context)\n        {\n            int compValue;\n            if (!int.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out compValue))\n            {\n                return MatchResults.EmptyFailure;\n            }\n\n            switch (_operation)\n            {\n                case IntegerOperationType.Equal:\n                    return compValue == _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case IntegerOperationType.Greater:\n                    return compValue > _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case IntegerOperationType.GreaterEqual:\n                    return compValue >= _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case IntegerOperationType.Less:\n                    return compValue < _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case IntegerOperationType.LessEqual:\n                    return compValue <= _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case IntegerOperationType.NotEqual:\n                    return compValue != _value ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                default:\n                    return null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IntegerOperation.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public enum IntegerOperationType\n    {\n        Equal,\n        Greater,\n        GreaterEqual,\n        Less,\n        LessEqual,\n        NotEqual\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsDirectoryMatch.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public class IsDirectoryMatch : UrlMatch\n    {\n        public IsDirectoryMatch(bool negate)\n        {\n            Negate = negate;\n        }\n\n        public override MatchResults Evaluate(string pattern, RewriteContext context)\n        {\n            var res = context.StaticFileProvider.GetFileInfo(pattern).IsDirectory;\n            return new MatchResults { Success = (res != Negate) };\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsFileMatch.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public class IsFileMatch : UrlMatch\n    {\n        public IsFileMatch(bool negate)\n        {\n            Negate = negate;\n        }\n\n        public override MatchResults Evaluate(string pattern, RewriteContext context)\n        {\n            var res = context.StaticFileProvider.GetFileInfo(pattern).Exists;\n            return new MatchResults { Success = (res != Negate) };\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/RegexMatch.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text.RegularExpressions;\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public class RegexMatch : UrlMatch\n    {\n        private readonly Regex _match;\n\n        public RegexMatch(Regex match, bool negate)\n        {\n            _match = match;\n            Negate = negate;\n        }\n\n        public override MatchResults Evaluate(string pattern, RewriteContext context)\n        {\n            var res = _match.Match(pattern);\n            return new MatchResults { BackReferences = new BackReferenceCollection(res.Groups), Success = (res.Success != Negate) };\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/StringMatch.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public class StringMatch : UrlMatch\n    {\n        private readonly string _value;\n        private readonly StringOperationType _operation;\n        private readonly bool _ignoreCase;\n\n        public StringMatch(string value, StringOperationType operation, bool ignoreCase)\n        {\n            _value = value;\n            _operation = operation;\n            _ignoreCase = ignoreCase;\n        }\n\n        public override MatchResults Evaluate(string input, RewriteContext context)\n        {\n            switch (_operation)\n            {\n                case StringOperationType.Equal:\n                    return string.Compare(input, _value, _ignoreCase) == 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case StringOperationType.Greater:\n                    return string.Compare(input, _value, _ignoreCase) > 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case StringOperationType.GreaterEqual:\n                    return string.Compare(input, _value, _ignoreCase) >= 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case StringOperationType.Less:\n                    return string.Compare(input, _value, _ignoreCase) < 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                case StringOperationType.LessEqual:\n                    return string.Compare(input, _value, _ignoreCase) <= 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure;\n                default:\n                    return null;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/StringOperation.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches\n{\n    public enum StringOperationType\n    {\n        Equal,\n        Greater,\n        GreaterEqual,\n        Less,\n        LessEqual\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Microsoft.AspNetCore.Rewrite.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <Description>ASP.NET Core basic middleware for rewriting URLs. Includes:\n* Support for custom URL rewrite rules\n* Support for running IIS URL Rewrite module rules\n* Support for running Apache mod_rewrite rules.</Description>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <NoWarn>$(NoWarn);CS1591</NoWarn>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <PackageTags>aspnetcore;urlrewrite;mod_rewrite</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Hosting.Abstractions\" Version=\"$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.Http.Extensions\" Version=\"$(MicrosoftAspNetCoreHttpExtensionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Configuration.Abstractions\" Version=\"$(MicrosoftExtensionsConfigurationAbstractionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.FileProviders.Abstractions\" Version=\"$(MicrosoftExtensionsFileProvidersAbstractionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Abstractions\" Version=\"$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Options\" Version=\"$(MicrosoftExtensionsOptionsPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Properties/AssemblyInfo.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"Microsoft.AspNetCore.Rewrite.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb\")]\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Properties/Resources.Designer.cs",
    "content": "// <auto-generated />\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    using System.Globalization;\n    using System.Reflection;\n    using System.Resources;\n\n    internal static class Resources\n    {\n        private static readonly ResourceManager _resourceManager\n            = new ResourceManager(\"Microsoft.AspNetCore.Rewrite.Resources\", typeof(Resources).GetTypeInfo().Assembly);\n\n        /// <summary>\n        /// Error adding a mod_rewrite rule. The change environment flag is not supported.\n        /// </summary>\n        internal static string Error_ChangeEnvironmentNotSupported\n        {\n            get { return GetString(\"Error_ChangeEnvironmentNotSupported\"); }\n        }\n\n        /// <summary>\n        /// Error adding a mod_rewrite rule. The change environment flag is not supported.\n        /// </summary>\n        internal static string FormatError_ChangeEnvironmentNotSupported()\n        {\n            return GetString(\"Error_ChangeEnvironmentNotSupported\");\n        }\n\n        /// <summary>\n        /// Could not parse integer from value '{0}'.\n        /// </summary>\n        internal static string Error_CouldNotParseInteger\n        {\n            get { return GetString(\"Error_CouldNotParseInteger\"); }\n        }\n\n        /// <summary>\n        /// Could not parse integer from value '{0}'.\n        /// </summary>\n        internal static string FormatError_CouldNotParseInteger(object p0)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_CouldNotParseInteger\"), p0);\n        }\n\n        /// <summary>\n        /// Index out of range for backreference: '{0}' at string index: '{1}'\n        /// </summary>\n        internal static string Error_InputParserIndexOutOfRange\n        {\n            get { return GetString(\"Error_InputParserIndexOutOfRange\"); }\n        }\n\n        /// <summary>\n        /// Index out of range for backreference: '{0}' at string index: '{1}'\n        /// </summary>\n        internal static string FormatError_InputParserIndexOutOfRange(object p0, object p1)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_InputParserIndexOutOfRange\"), p0, p1);\n        }\n\n        /// <summary>\n        /// Cannot parse '{0}' to integer at string index: '{1}'\n        /// </summary>\n        internal static string Error_InputParserInvalidInteger\n        {\n            get { return GetString(\"Error_InputParserInvalidInteger\"); }\n        }\n\n        /// <summary>\n        /// Cannot parse '{0}' to integer at string index: '{1}'\n        /// </summary>\n        internal static string FormatError_InputParserInvalidInteger(object p0, object p1)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_InputParserInvalidInteger\"), p0, p1);\n        }\n\n        /// <summary>\n        /// Missing close brace for parameter at string index: '{0}'\n        /// </summary>\n        internal static string Error_InputParserMissingCloseBrace\n        {\n            get { return GetString(\"Error_InputParserMissingCloseBrace\"); }\n        }\n\n        /// <summary>\n        /// Missing close brace for parameter at string index: '{0}'\n        /// </summary>\n        internal static string FormatError_InputParserMissingCloseBrace(object p0)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_InputParserMissingCloseBrace\"), p0);\n        }\n\n        /// <summary>\n        /// Missing backreference for parameter at string index: '{0}'\n        /// </summary>\n        internal static string Error_InputParserNoBackreference\n        {\n            get { return GetString(\"Error_InputParserNoBackreference\"); }\n        }\n\n        /// <summary>\n        /// Missing backreference for parameter at string index: '{0}'\n        /// </summary>\n        internal static string FormatError_InputParserNoBackreference(object p0)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_InputParserNoBackreference\"), p0);\n        }\n\n        /// <summary>\n        /// Unrecognized parameter type: '{0}', terminated at string index: '{1}'\n        /// </summary>\n        internal static string Error_InputParserUnrecognizedParameter\n        {\n            get { return GetString(\"Error_InputParserUnrecognizedParameter\"); }\n        }\n\n        /// <summary>\n        /// Unrecognized parameter type: '{0}', terminated at string index: '{1}'\n        /// </summary>\n        internal static string FormatError_InputParserUnrecognizedParameter(object p0, object p1)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_InputParserUnrecognizedParameter\"), p0, p1);\n        }\n\n        /// <summary>\n        /// Syntax error for integers in comparison.\n        /// </summary>\n        internal static string Error_IntegerMatch_FormatExceptionMessage\n        {\n            get { return GetString(\"Error_IntegerMatch_FormatExceptionMessage\"); }\n        }\n\n        /// <summary>\n        /// Syntax error for integers in comparison.\n        /// </summary>\n        internal static string FormatError_IntegerMatch_FormatExceptionMessage()\n        {\n            return GetString(\"Error_IntegerMatch_FormatExceptionMessage\");\n        }\n\n        /// <summary>\n        /// Error parsing the mod_rewrite rule. The cookie flag (CO) has an incorrect format '{0}'.\n        /// </summary>\n        internal static string Error_InvalidChangeCookieFlag\n        {\n            get { return GetString(\"Error_InvalidChangeCookieFlag\"); }\n        }\n\n        /// <summary>\n        /// Error parsing the mod_rewrite rule. The cookie flag (CO) has an incorrect format '{0}'.\n        /// </summary>\n        internal static string FormatError_InvalidChangeCookieFlag(object p0)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_InvalidChangeCookieFlag\"), p0);\n        }\n\n        /// <summary>\n        /// Could not parse the mod_rewrite file. Message: '{0}'.  Line number '{1}'.\n        /// </summary>\n        internal static string Error_ModRewriteParseError\n        {\n            get { return GetString(\"Error_ModRewriteParseError\"); }\n        }\n\n        /// <summary>\n        /// Could not parse the mod_rewrite file. Message: '{0}'.  Line number '{1}'.\n        /// </summary>\n        internal static string FormatError_ModRewriteParseError(object p0, object p1)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_ModRewriteParseError\"), p0, p1);\n        }\n\n        /// <summary>\n        /// Could not parse the mod_rewrite file.  Line number '{0}'.\n        /// </summary>\n        internal static string Error_ModRewriteGeneralParseError\n        {\n            get { return GetString(\"Error_ModRewriteGeneralParseError\"); }\n        }\n\n        /// <summary>\n        /// Could not parse the mod_rewrite file.  Line number '{0}'.\n        /// </summary>\n        internal static string FormatError_ModRewriteGeneralParseError(object p0)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_ModRewriteGeneralParseError\"), p0);\n        }\n\n        /// <summary>\n        /// Could not parse the UrlRewrite file. Message: '{0}'. Line number '{1}': '{2}'.\n        /// </summary>\n        internal static string Error_UrlRewriteParseError\n        {\n            get { return GetString(\"Error_UrlRewriteParseError\"); }\n        }\n\n        /// <summary>\n        /// Could not parse the UrlRewrite file. Message: '{0}'. Line number '{1}': '{2}'.\n        /// </summary>\n        internal static string FormatError_UrlRewriteParseError(object p0, object p1, object p2)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_UrlRewriteParseError\"), p0, p1, p2);\n        }\n\n        /// <summary>\n        /// Rules using the '{0}' server variable are not supported\n        /// </summary>\n        internal static string Error_UnsupportedServerVariable\n        {\n            get { return GetString(\"Error_UnsupportedServerVariable\"); }\n        }\n\n        /// <summary>\n        /// Rules using the '{0}' server variable are not supported\n        /// </summary>\n        internal static string FormatError_UnsupportedServerVariable(object p0)\n        {\n            return string.Format(CultureInfo.CurrentCulture, GetString(\"Error_UnsupportedServerVariable\"), p0);\n        }\n\n        private static string GetString(string name, params string[] formatterNames)\n        {\n            var value = _resourceManager.GetString(name);\n\n            System.Diagnostics.Debug.Assert(value != null);\n\n            if (formatterNames != null)\n            {\n                for (var i = 0; i < formatterNames.Length; i++)\n                {\n                    value = value.Replace(\"{\" + formatterNames[i] + \"}\", \"{\" + i + \"}\");\n                }\n            }\n\n            return value;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/Resources.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Error_ChangeEnvironmentNotSupported\" xml:space=\"preserve\">\n    <value>Error adding a mod_rewrite rule. The change environment flag is not supported.</value>\n  </data>\n  <data name=\"Error_CouldNotParseInteger\" xml:space=\"preserve\">\n    <value>Could not parse integer from value '{0}'.</value>\n  </data>\n  <data name=\"Error_InputParserIndexOutOfRange\" xml:space=\"preserve\">\n    <value>Index out of range for backreference: '{0}' at string index: '{1}'</value>\n  </data>\n  <data name=\"Error_InputParserInvalidInteger\" xml:space=\"preserve\">\n    <value>Cannot parse '{0}' to integer at string index: '{1}'</value>\n  </data>\n  <data name=\"Error_InputParserMissingCloseBrace\" xml:space=\"preserve\">\n    <value>Missing close brace for parameter at string index: '{0}'</value>\n  </data>\n  <data name=\"Error_InputParserNoBackreference\" xml:space=\"preserve\">\n    <value>Missing backreference for parameter at string index: '{0}'</value>\n  </data>\n  <data name=\"Error_InputParserUnrecognizedParameter\" xml:space=\"preserve\">\n    <value>Unrecognized parameter type: '{0}', terminated at string index: '{1}'</value>\n  </data>\n  <data name=\"Error_IntegerMatch_FormatExceptionMessage\" xml:space=\"preserve\">\n    <value>Syntax error for integers in comparison.</value>\n  </data>\n  <data name=\"Error_InvalidChangeCookieFlag\" xml:space=\"preserve\">\n    <value>Error parsing the mod_rewrite rule. The cookie flag (CO) has an incorrect format '{0}'.</value>\n  </data>\n  <data name=\"Error_ModRewriteParseError\" xml:space=\"preserve\">\n    <value>Could not parse the mod_rewrite file. Message: '{0}'.  Line number '{1}'.</value>\n  </data>\n  <data name=\"Error_ModRewriteGeneralParseError\" xml:space=\"preserve\">\n    <value>Could not parse the mod_rewrite file.  Line number '{0}'.</value>\n  </data>\n  <data name=\"Error_UrlRewriteParseError\" xml:space=\"preserve\">\n    <value>Could not parse the UrlRewrite file. Message: '{0}'. Line number '{1}': '{2}'.</value>\n  </data>\n  <data name=\"Error_UnsupportedServerVariable\" xml:space=\"preserve\">\n    <value>Rules using the '{0}' server variable are not supported</value>\n  </data>\n</root>"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/RewriteBuilderExtensions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Rewrite;\nusing Microsoft.Extensions.Options;\n\nnamespace Microsoft.AspNetCore.Builder\n{\n    /// <summary>\n    /// Extension methods for the <see cref=\"RewriteMiddleware\"/>\n    /// </summary>\n    public static class RewriteBuilderExtensions\n    {\n        /// <summary>\n        /// Checks if a given Url matches rules and conditions, and modifies the HttpContext on match.\n        /// </summary>\n        /// <param name=\"app\">The <see cref=\"IApplicationBuilder\"/></param>\n        /// <returns></returns>\n        public static IApplicationBuilder UseRewriter(this IApplicationBuilder app)\n        {\n            if (app == null)\n            {\n                throw new ArgumentNullException(nameof(app));\n            }\n\n            return app.UseMiddleware<RewriteMiddleware>();\n        }\n\n        /// <summary>\n        /// Checks if a given Url matches rules and conditions, and modifies the HttpContext on match.\n        /// </summary>\n        /// <param name=\"app\">The <see cref=\"IApplicationBuilder\"/></param>\n        /// <param name=\"options\">Options for rewrite.</param>\n        /// <returns></returns>\n        public static IApplicationBuilder UseRewriter(this IApplicationBuilder app, RewriteOptions options)\n        {\n            if (app == null)\n            {\n                throw new ArgumentNullException(nameof(app));\n            }\n\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            // put middleware in pipeline\n            return app.UseMiddleware<RewriteMiddleware>(Options.Create(options));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.FileProviders;\nusing Microsoft.Extensions.Logging;\n\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    /// <summary>\n    /// A context object for <see cref=\"RewriteMiddleware\"/>\n    /// </summary>\n    public class RewriteContext\n    {\n        /// <summary>\n        /// Gets and sets the <see cref=\"HttpContext\"/>\n        /// </summary>\n        public HttpContext HttpContext { get; set; }\n\n        /// <summary>\n        /// Gets and sets the File Provider for file and directory checks.\n        /// </summary>\n        public IFileProvider StaticFileProvider { get; set; }\n\n        /// <summary>\n        /// Gets and sets the logger\n        /// </summary>\n        public ILogger Logger { get; set; }\n\n        /// <summary>\n        /// A shared result that is set appropriately by each rule for the next action that\n        /// should be taken. See <see cref=\"RuleResult\"/>\n        /// </summary>\n        public RuleResult Result { get; set; }\n\n        internal StringBuilder Builder { get; set; } = new StringBuilder(64);\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/RewriteMiddleware.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Extensions;\nusing Microsoft.AspNetCore.Rewrite.Logging;\nusing Microsoft.Extensions.FileProviders;\nusing Microsoft.Extensions.Internal;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Options;\nusing Microsoft.Net.Http.Headers;\n\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    /// <summary>\n    /// Represents a middleware that rewrites urls\n    /// </summary>\n    public class RewriteMiddleware\n    {\n        private readonly RequestDelegate _next;\n        private readonly RewriteOptions _options;\n        private readonly IFileProvider _fileProvider;\n        private readonly ILogger _logger;\n\n        /// <summary>\n        /// Creates a new instance of <see cref=\"RewriteMiddleware\"/>\n        /// </summary>\n        /// <param name=\"next\">The delegate representing the next middleware in the request pipeline.</param>\n        /// <param name=\"hostingEnvironment\">The Hosting Environment.</param>\n        /// <param name=\"loggerFactory\">The Logger Factory.</param>\n        /// <param name=\"options\">The middleware options, containing the rules to apply.</param>\n        public RewriteMiddleware(\n            RequestDelegate next,\n            IHostingEnvironment hostingEnvironment,\n            ILoggerFactory loggerFactory,\n            IOptions<RewriteOptions> options)\n        {\n            if (next == null)\n            {\n                throw new ArgumentNullException(nameof(next));\n            }\n\n            if (options == null)\n            {\n                throw new ArgumentNullException(nameof(options));\n            }\n\n            _next = next;\n            _options = options.Value;\n            _fileProvider = _options.StaticFileProvider ?? hostingEnvironment.WebRootFileProvider;\n            _logger = loggerFactory.CreateLogger<RewriteMiddleware>();\n        }\n\n        /// <summary>\n        /// Executes the middleware.\n        /// </summary>\n        /// <param name=\"context\">The <see cref=\"HttpContext\"/> for the current request.</param>\n        /// <returns>A task that represents the execution of this middleware.</returns>\n        public Task Invoke(HttpContext context)\n        {\n            if (context == null)\n            {\n                throw new ArgumentNullException(nameof(context));\n            }\n\n            var rewriteContext = new RewriteContext\n            {\n                HttpContext = context,\n                StaticFileProvider = _fileProvider,\n                Logger = _logger,\n                Result = RuleResult.ContinueRules\n            };\n\n            foreach (var rule in _options.Rules)\n            {\n                rule.ApplyRule(rewriteContext);\n                switch (rewriteContext.Result)\n                {\n                    case RuleResult.ContinueRules:\n                        _logger.RewriteMiddlewareRequestContinueResults(context.Request.GetEncodedUrl());\n                        break;\n                    case RuleResult.EndResponse:\n                        _logger.RewriteMiddlewareRequestResponseComplete(\n                            context.Response.Headers[HeaderNames.Location],\n                            context.Response.StatusCode);\n                        return Task.CompletedTask;\n                    case RuleResult.SkipRemainingRules:\n                        _logger.RewriteMiddlewareRequestStopRules(context.Request.GetEncodedUrl());\n                        return _next(context);\n                    default:\n                        throw new ArgumentOutOfRangeException($\"Invalid rule termination {rewriteContext.Result}\");\n                }\n            }\n            return _next(context);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing Microsoft.Extensions.FileProviders;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    /// <summary>\n    /// Options for the <see cref=\"RewriteMiddleware\"/>\n    /// </summary>\n    public class RewriteOptions\n    {\n        /// <summary>\n        /// A list of <see cref=\"IRule\"/> that will be applied in order upon a request.\n        /// </summary>\n        public IList<IRule> Rules { get; } = new List<IRule>();\n\n        /// <summary>\n        /// Gets and sets the File Provider for file and directory checks. Defaults to <see cref=\"IHostingEnvironment.WebRootFileProvider\"/>\n        /// </summary>\n        public IFileProvider StaticFileProvider { get; set; }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/RewriteOptionsExtensions.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal;\n\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    /// <summary>\n    /// The builder to a list of rules for <see cref=\"RewriteOptions\"/> and <see cref=\"RewriteMiddleware\"/>\n    /// </summary>\n    public static class RewriteOptionsExtensions\n    {\n        /// <summary>\n        /// Adds a rule to the current rules.\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <param name=\"rule\">A rule to be added to the current rules.</param>\n        /// <returns>The Rewrite options.</returns>\n        public static RewriteOptions Add(this RewriteOptions options, IRule rule)\n        {\n            options.Rules.Add(rule);\n            return options;\n        }\n\n        /// <summary>\n        /// Adds a rule to the current rules.\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <param name=\"applyRule\">A Func that checks and applies the rule.</param>\n        /// <returns></returns>\n        public static RewriteOptions Add(this RewriteOptions options, Action<RewriteContext> applyRule)\n        {\n            options.Rules.Add(new DelegateRule(applyRule));\n            return options;\n        }\n\n        /// <summary>\n        /// Adds a rule that rewrites the path if the regex matches the HttpContext's PathString.\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <param name=\"regex\">The regex string to compare with.</param>\n        /// <param name=\"replacement\">If the regex matches, what to replace the uri with.</param>\n        /// <param name=\"skipRemainingRules\">If the regex matches, conditionally stop processing other rules.</param>\n        /// <returns>The Rewrite options.</returns>\n        public static RewriteOptions AddRewrite(this RewriteOptions options, string regex, string replacement, bool skipRemainingRules)\n        {\n            options.Rules.Add(new RewriteRule(regex, replacement, skipRemainingRules));\n            return options;\n        }\n\n        /// <summary>\n        /// Redirect the request if the regex matches the HttpContext's PathString\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <param name=\"regex\">The regex string to compare with.</param>\n        /// <param name=\"replacement\">If the regex matches, what to replace the uri with.</param>\n        /// <returns>The Rewrite options.</returns>\n        public static RewriteOptions AddRedirect(this RewriteOptions options, string regex, string replacement)\n        {\n            return AddRedirect(options, regex, replacement, statusCode: StatusCodes.Status302Found);\n        }\n\n        /// <summary>\n        /// Redirect the request if the regex matches the HttpContext's PathString\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <param name=\"regex\">The regex string to compare with.</param>\n        /// <param name=\"replacement\">If the regex matches, what to replace the uri with.</param>\n        /// <param name=\"statusCode\">The status code to add to the response.</param>\n        /// <returns>The Rewrite options.</returns>\n        public static RewriteOptions AddRedirect(this RewriteOptions options, string regex, string replacement, int statusCode)\n        {\n            options.Rules.Add(new RedirectRule(regex, replacement, statusCode));\n            return options;\n        }\n\n        /// <summary>\n        /// Redirect a request to https if the incoming request is http, with returning a 301\n        /// status code for permanently redirected.\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <returns></returns>\n        public static RewriteOptions AddRedirectToHttpsPermanent(this RewriteOptions options)\n        {\n            return AddRedirectToHttps(options, statusCode: StatusCodes.Status301MovedPermanently, sslPort: null);\n        }\n\n        /// <summary>\n        /// Redirect a request to https if the incoming request is http\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        public static RewriteOptions AddRedirectToHttps(this RewriteOptions options)\n        {\n            return AddRedirectToHttps(options, statusCode: StatusCodes.Status302Found, sslPort: null);\n        }\n\n        /// <summary>\n        /// Redirect a request to https if the incoming request is http\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <param name=\"statusCode\">The status code to add to the response.</param>\n        public static RewriteOptions AddRedirectToHttps(this RewriteOptions options, int statusCode)\n        {\n            return AddRedirectToHttps(options, statusCode, sslPort: null);\n        }\n\n        /// <summary>\n        /// Redirect a request to https if the incoming request is http\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <param name=\"statusCode\">The status code to add to the response.</param>\n        /// <param name=\"sslPort\">The SSL port to add to the response.</param>\n        public static RewriteOptions AddRedirectToHttps(this RewriteOptions options, int statusCode, int? sslPort)\n        {\n            options.Rules.Add(new RedirectToHttpsRule { StatusCode = statusCode, SSLPort = sslPort });\n            return options;\n        }\n\n        /// <summary>\n        /// Permanently redirects the request to the www subdomain if the request is non-www.\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <returns></returns>\n        public static RewriteOptions AddRedirectToWwwPermanent(this RewriteOptions options)\n        {\n            return AddRedirectToWww(options, statusCode: StatusCodes.Status308PermanentRedirect);\n        }\n\n        /// <summary>\n        /// Redirect the request to the www subdomain if the incoming request is non-www.\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        public static RewriteOptions AddRedirectToWww(this RewriteOptions options)\n        {\n            return AddRedirectToWww(options, statusCode: StatusCodes.Status307TemporaryRedirect);\n        }\n\n        /// <summary>\n        /// Redirect the request to the www subdomain if the incoming request is non-www.\n        /// </summary>\n        /// <param name=\"options\">The <see cref=\"RewriteOptions\"/>.</param>\n        /// <param name=\"statusCode\">The status code to add to the response.</param>\n        public static RewriteOptions AddRedirectToWww(this RewriteOptions options, int statusCode)\n        {\n            options.Rules.Add(new RedirectToWwwRule(statusCode));\n            return options;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/RuleResult.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nnamespace Microsoft.AspNetCore.Rewrite\n{\n    /// <summary>\n    /// An enum representing the result of a rule.\n    /// </summary>\n    public enum RuleResult\n    {\n        /// <summary>\n        /// Default value, continue applying rules.\n        /// </summary>\n        ContinueRules,\n        ///<summary>\n        /// The rule ended the request by providing a response.\n        /// </summary>\n        EndResponse,\n        /// <summary>\n        /// Stop applying rules and send context to the next middleware\n        /// </summary>\n        SkipRemainingRules\n    }\n}\n"
  },
  {
    "path": "src/Microsoft.AspNetCore.Rewrite/baseline.netcore.json",
    "content": "{\n  \"AssemblyIdentity\": \"Microsoft.AspNetCore.Rewrite, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60\",\n  \"Types\": [\n    {\n      \"Name\": \"Microsoft.AspNetCore.Builder.RewriteBuilderExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseRewriter\",\n          \"Parameters\": [\n            {\n              \"Name\": \"app\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"UseRewriter\",\n          \"Parameters\": [\n            {\n              \"Name\": \"app\",\n              \"Type\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Builder.IApplicationBuilder\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Rewrite.ApacheModRewriteOptionsExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddApacheModRewrite\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"fileProvider\",\n              \"Type\": \"Microsoft.Extensions.FileProviders.IFileProvider\"\n            },\n            {\n              \"Name\": \"filePath\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddApacheModRewrite\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"reader\",\n              \"Type\": \"System.IO.TextReader\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Rewrite.IISUrlRewriteOptionsExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddIISUrlRewrite\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"fileProvider\",\n              \"Type\": \"Microsoft.Extensions.FileProviders.IFileProvider\"\n            },\n            {\n              \"Name\": \"filePath\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddIISUrlRewrite\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"reader\",\n              \"Type\": \"System.IO.TextReader\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Rewrite.IRule\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Interface\",\n      \"Abstract\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"ApplyRule\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Rewrite.RewriteContext\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_HttpContext\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.AspNetCore.Http.HttpContext\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_HttpContext\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_StaticFileProvider\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.Extensions.FileProviders.IFileProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_StaticFileProvider\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"Microsoft.Extensions.FileProviders.IFileProvider\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Logger\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.Extensions.Logging.ILogger\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_Logger\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"Microsoft.Extensions.Logging.ILogger\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Result\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RuleResult\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_Result\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RuleResult\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Rewrite.RewriteMiddleware\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Invoke\",\n          \"Parameters\": [\n            {\n              \"Name\": \"context\",\n              \"Type\": \"Microsoft.AspNetCore.Http.HttpContext\"\n            }\n          ],\n          \"ReturnType\": \"System.Threading.Tasks.Task\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [\n            {\n              \"Name\": \"next\",\n              \"Type\": \"Microsoft.AspNetCore.Http.RequestDelegate\"\n            },\n            {\n              \"Name\": \"hostingEnvironment\",\n              \"Type\": \"Microsoft.AspNetCore.Hosting.IHostingEnvironment\"\n            },\n            {\n              \"Name\": \"loggerFactory\",\n              \"Type\": \"Microsoft.Extensions.Logging.ILoggerFactory\"\n            },\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Rewrite.RewriteOptions>\"\n            }\n          ],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_Rules\",\n          \"Parameters\": [],\n          \"ReturnType\": \"System.Collections.Generic.IList<Microsoft.AspNetCore.Rewrite.IRule>\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"get_StaticFileProvider\",\n          \"Parameters\": [],\n          \"ReturnType\": \"Microsoft.Extensions.FileProviders.IFileProvider\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"set_StaticFileProvider\",\n          \"Parameters\": [\n            {\n              \"Name\": \"value\",\n              \"Type\": \"Microsoft.Extensions.FileProviders.IFileProvider\"\n            }\n          ],\n          \"ReturnType\": \"System.Void\",\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Constructor\",\n          \"Name\": \".ctor\",\n          \"Parameters\": [],\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Rewrite.RewriteOptionsExtensions\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Class\",\n      \"Abstract\": true,\n      \"Static\": true,\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Add\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"rule\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.IRule\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"Add\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"applyRule\",\n              \"Type\": \"System.Action<Microsoft.AspNetCore.Rewrite.RewriteContext>\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRewrite\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"regex\",\n              \"Type\": \"System.String\"\n            },\n            {\n              \"Name\": \"replacement\",\n              \"Type\": \"System.String\"\n            },\n            {\n              \"Name\": \"skipRemainingRules\",\n              \"Type\": \"System.Boolean\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirect\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"regex\",\n              \"Type\": \"System.String\"\n            },\n            {\n              \"Name\": \"replacement\",\n              \"Type\": \"System.String\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirect\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"regex\",\n              \"Type\": \"System.String\"\n            },\n            {\n              \"Name\": \"replacement\",\n              \"Type\": \"System.String\"\n            },\n            {\n              \"Name\": \"statusCode\",\n              \"Type\": \"System.Int32\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirectToHttpsPermanent\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirectToHttps\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirectToHttps\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"statusCode\",\n              \"Type\": \"System.Int32\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirectToHttps\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"statusCode\",\n              \"Type\": \"System.Int32\"\n            },\n            {\n              \"Name\": \"sslPort\",\n              \"Type\": \"System.Nullable<System.Int32>\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirectToWwwPermanent\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirectToWww\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        },\n        {\n          \"Kind\": \"Method\",\n          \"Name\": \"AddRedirectToWww\",\n          \"Parameters\": [\n            {\n              \"Name\": \"options\",\n              \"Type\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\"\n            },\n            {\n              \"Name\": \"statusCode\",\n              \"Type\": \"System.Int32\"\n            }\n          ],\n          \"ReturnType\": \"Microsoft.AspNetCore.Rewrite.RewriteOptions\",\n          \"Static\": true,\n          \"Extension\": true,\n          \"Visibility\": \"Public\",\n          \"GenericParameter\": []\n        }\n      ],\n      \"GenericParameters\": []\n    },\n    {\n      \"Name\": \"Microsoft.AspNetCore.Rewrite.RuleResult\",\n      \"Visibility\": \"Public\",\n      \"Kind\": \"Enumeration\",\n      \"Sealed\": true,\n      \"ImplementedInterfaces\": [],\n      \"Members\": [\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"ContinueRules\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"0\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"EndResponse\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"1\"\n        },\n        {\n          \"Kind\": \"Field\",\n          \"Name\": \"SkipRemainingRules\",\n          \"Parameters\": [],\n          \"GenericParameter\": [],\n          \"Literal\": \"2\"\n        }\n      ],\n      \"GenericParameters\": []\n    }\n  ]\n}"
  },
  {
    "path": "test/Directory.Build.props",
    "content": "<Project>\n  <Import Project=\"..\\Directory.Build.props\" />\n\n  <PropertyGroup>\n    <DeveloperBuildTestTfms>netcoreapp2.2</DeveloperBuildTestTfms>\n    <StandardTestTfms>$(DeveloperBuildTestTfms)</StandardTestTfms>\n\n    <StandardTestTfms Condition=\" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' \">$(StandardTestTfms);net461</StandardTestTfms>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Internal.AspNetCore.Sdk\" PrivateAssets=\"All\" Version=\"$(InternalAspNetCoreSdkPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.AspNetCore.TestHost\" Version=\"$(MicrosoftAspNetCoreTestHostPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"$(MicrosoftNETTestSdkPackageVersion)\" />\n    <PackageReference Include=\"xunit.analyzers\" Version=\"$(XunitAnalyzersPackageVersion)\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"$(XunitRunnerVisualStudioPackageVersion)\" />\n    <PackageReference Include=\"xunit\" Version=\"$(XunitPackageVersion)\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Buffering.Tests/Microsoft.AspNetCore.Buffering.Tests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.Buffering\\Microsoft.AspNetCore.Buffering.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Buffering.Tests/ResponseBufferingMiddlewareTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.AspNetCore.TestHost;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Buffering.Tests\n{\n    public class ResponseBufferingMiddlewareTests\n    {\n        [Fact]\n        public async Task BufferResponse_SetsContentLength()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseResponseBuffering();\n                    app.Run(async context =>\n                    {\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n                        await context.Response.WriteAsync(\"Hello World\");\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            response.EnsureSuccessStatusCode();\n            Assert.Equal(\"Hello World\", await response.Content.ReadAsStringAsync());\n\n            // Set automatically by buffer\n            IEnumerable<string> values;\n            Assert.True(response.Content.Headers.TryGetValues(\"Content-Length\", out values));\n            Assert.Equal(\"11\", values.FirstOrDefault());\n        }\n\n        [Fact]\n        public async Task BufferResponseWithManualContentLength_NotReplaced()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseResponseBuffering();\n                    app.Run(async context =>\n                    {\n                        context.Response.ContentLength = 12;\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n                        await context.Response.WriteAsync(\"Hello World\");\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            response.EnsureSuccessStatusCode();\n            Assert.Equal(\"Hello World\", await response.Content.ReadAsStringAsync());\n\n            IEnumerable<string> values;\n            Assert.True(response.Content.Headers.TryGetValues(\"Content-Length\", out values));\n            Assert.Equal(\"12\", values.FirstOrDefault());\n        }\n\n        [Fact]\n        public async Task Seek_AllowsResttingBuffer()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseResponseBuffering();\n                    app.Run(async context =>\n                    {\n                        var body = context.Response.Body;\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(body.CanSeek);\n                        Assert.Equal(0, body.Position);\n                        Assert.Equal(0, body.Length);\n\n                        await context.Response.WriteAsync(\"Hello World\");\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n                        Assert.Equal(11, body.Position);\n                        Assert.Equal(11, body.Length);\n\n                        Assert.Throws<ArgumentOutOfRangeException>(() => body.Seek(1, SeekOrigin.Begin));\n                        Assert.Throws<ArgumentException>(() => body.Seek(0, SeekOrigin.Current));\n                        Assert.Throws<ArgumentException>(() => body.Seek(0, SeekOrigin.End));\n\n                        Assert.Equal(0, body.Seek(0, SeekOrigin.Begin));\n                        Assert.Equal(0, body.Position);\n                        Assert.Equal(0, body.Length);\n\n                        await context.Response.WriteAsync(\"12345\");\n                        Assert.Equal(5, body.Position);\n                        Assert.Equal(5, body.Length);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            response.EnsureSuccessStatusCode();\n            Assert.Equal(\"12345\", await response.Content.ReadAsStringAsync());\n\n            // Set automatically by buffer\n            IEnumerable<string> values;\n            Assert.True(response.Content.Headers.TryGetValues(\"Content-Length\", out values));\n            Assert.Equal(\"5\", values.FirstOrDefault());\n        }\n\n        [Fact]\n        public async Task SetPosition_AllowsResttingBuffer()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseResponseBuffering();\n                    app.Run(async context =>\n                    {\n                        var body = context.Response.Body;\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(body.CanSeek);\n                        Assert.Equal(0, body.Position);\n                        Assert.Equal(0, body.Length);\n\n                        await context.Response.WriteAsync(\"Hello World\");\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n                        Assert.Equal(11, body.Position);\n                        Assert.Equal(11, body.Length);\n\n                        Assert.Throws<ArgumentOutOfRangeException>(() => body.Position = 1);\n\n                        body.Position = 0;\n                        Assert.Equal(0, body.Position);\n                        Assert.Equal(0, body.Length);\n\n                        await context.Response.WriteAsync(\"12345\");\n                        Assert.Equal(5, body.Position);\n                        Assert.Equal(5, body.Length);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            response.EnsureSuccessStatusCode();\n            Assert.Equal(\"12345\", await response.Content.ReadAsStringAsync());\n\n            // Set automatically by buffer\n            IEnumerable<string> values;\n            Assert.True(response.Content.Headers.TryGetValues(\"Content-Length\", out values));\n            Assert.Equal(\"5\", values.FirstOrDefault());\n        }\n\n        [Fact]\n        public async Task SetLength_AllowsResttingBuffer()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseResponseBuffering();\n                    app.Run(async context =>\n                    {\n                        var body = context.Response.Body;\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(body.CanSeek);\n                        Assert.Equal(0, body.Position);\n                        Assert.Equal(0, body.Length);\n\n                        await context.Response.WriteAsync(\"Hello World\");\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n                        Assert.Equal(11, body.Position);\n                        Assert.Equal(11, body.Length);\n\n                        Assert.Throws<ArgumentOutOfRangeException>(() => body.SetLength(1));\n\n                        body.SetLength(0);\n                        Assert.Equal(0, body.Position);\n                        Assert.Equal(0, body.Length);\n\n                        await context.Response.WriteAsync(\"12345\");\n                        Assert.Equal(5, body.Position);\n                        Assert.Equal(5, body.Length);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            response.EnsureSuccessStatusCode();\n            Assert.Equal(\"12345\", await response.Content.ReadAsStringAsync());\n\n            // Set automatically by buffer\n            IEnumerable<string> values;\n            Assert.True(response.Content.Headers.TryGetValues(\"Content-Length\", out values));\n            Assert.Equal(\"5\", values.FirstOrDefault());\n        }\n\n        [Fact]\n        public async Task DisableBufferingViaFeature()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseResponseBuffering();\n                    app.Run(async context =>\n                    {\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n\n                        var bufferingFeature = context.Features.Get<IHttpBufferingFeature>();\n                        Assert.NotNull(bufferingFeature);\n                        bufferingFeature.DisableResponseBuffering();\n\n                        Assert.False(context.Response.HasStarted);\n                        Assert.False(context.Response.Body.CanSeek);\n\n                        await context.Response.WriteAsync(\"Hello World\");\n\n                        Assert.True(context.Response.HasStarted);\n                        Assert.False(context.Response.Body.CanSeek);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            response.EnsureSuccessStatusCode();\n            Assert.Equal(\"Hello World\", await response.Content.ReadAsStringAsync());\n            IEnumerable<string> values;\n            Assert.False(response.Content.Headers.TryGetValues(\"Content-Length\", out values));\n        }\n\n        [Fact]\n        public async Task DisableBufferingViaFeatureAfterFirstWrite_Flushes()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseResponseBuffering();\n                    app.Run(async context =>\n                    {\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n\n                        await context.Response.WriteAsync(\"Hello\");\n\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n\n                        var bufferingFeature = context.Features.Get<IHttpBufferingFeature>();\n                        Assert.NotNull(bufferingFeature);\n                        bufferingFeature.DisableResponseBuffering();\n\n                        Assert.True(context.Response.HasStarted);\n                        Assert.False(context.Response.Body.CanSeek);\n\n                        await context.Response.WriteAsync(\" World\");\n\n                        Assert.True(context.Response.HasStarted);\n                        Assert.False(context.Response.Body.CanSeek);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            response.EnsureSuccessStatusCode();\n            Assert.Equal(\"Hello World\", await response.Content.ReadAsStringAsync());\n            IEnumerable<string> values;\n            Assert.False(response.Content.Headers.TryGetValues(\"Content-Length\", out values));\n        }\n\n        [Fact]\n        public async Task FlushDisablesBuffering()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseResponseBuffering();\n                    app.Run(async context =>\n                    {\n                        Assert.False(context.Response.HasStarted);\n                        Assert.True(context.Response.Body.CanSeek);\n\n                        context.Response.Body.Flush();\n\n                        Assert.True(context.Response.HasStarted);\n                        Assert.False(context.Response.Body.CanSeek);\n\n                        await context.Response.WriteAsync(\"Hello World\");\n\n                        Assert.True(context.Response.HasStarted);\n                        Assert.False(context.Response.Body.CanSeek);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            response.EnsureSuccessStatusCode();\n            Assert.Equal(\"Hello World\", await response.Content.ReadAsStringAsync());\n            IEnumerable<string> values;\n            Assert.False(response.Content.Headers.TryGetValues(\"Content-Length\", out values));\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HostFiltering.Tests/HostFilteringMiddlewareTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.TestHost;\nusing Microsoft.Extensions.Configuration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Options;\nusing Microsoft.Extensions.Primitives;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.HostFiltering\n{\n    public class HostFilteringMiddlewareTests\n    {\n        [Fact]\n        public async Task MissingConfigThrows()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseHostFiltering();\n                });\n            await Assert.ThrowsAsync<InvalidOperationException>(() => new TestServer(builder).SendAsync(_ => { }));\n        }\n\n        [Theory]\n        [InlineData(true, 200)]\n        [InlineData(false, 400)]\n        public async Task AllowsMissingHost(bool allowed, int status)\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddHostFiltering(options =>\n                    {\n                        options.AllowEmptyHosts = allowed;\n                        options.AllowedHosts.Add(\"Localhost\");\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.Use((ctx, next) =>\n                    {\n                        ctx.Request.Headers.Remove(HeaderNames.Host);\n                        return next();\n                    });\n                    app.UseHostFiltering();\n                    app.Run(c =>\n                    {\n                        Assert.False(c.Request.Headers.TryGetValue(HeaderNames.Host, out var host));\n                        return Task.CompletedTask;\n                    });\n                });\n            var server = new TestServer(builder);\n            var response = await server.CreateClient().GetAsync(\"/\");\n            Assert.Equal(status, (int)response.StatusCode);\n        }\n\n        [Theory]\n        [InlineData(true, 200)]\n        [InlineData(false, 400)]\n        public async Task AllowsEmptyHost(bool allowed, int status)\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddHostFiltering(options =>\n                    {\n                        options.AllowEmptyHosts = allowed;\n                        options.AllowedHosts.Add(\"Localhost\");\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.Use((ctx, next) =>\n                    {\n                        ctx.Request.Headers[HeaderNames.Host] = \" \";\n                        return next();\n                    });\n                    app.UseHostFiltering();\n                    app.Run(c =>\n                    {\n                        Assert.True(c.Request.Headers.TryGetValue(HeaderNames.Host, out var host));\n                        Assert.True(StringValues.Equals(\" \", host));\n                        return Task.CompletedTask;\n                    });\n                    app.Run(c => Task.CompletedTask);\n                });\n            var server = new TestServer(builder);\n            var response = await server.CreateClient().GetAsync(\"/\");\n            Assert.Equal(status, (int)response.StatusCode);\n        }\n\n        [Theory]\n        [InlineData(\"localHost\", \"localhost\")]\n        [InlineData(\"localHost\", \"*\")] // Any - Used by HttpSys\n        [InlineData(\"localHost\", \"[::]\")] // IPv6 Any - This is what Kestrel reports when binding to *\n        [InlineData(\"localHost\", \"0.0.0.0\")] // IPv4 Any\n        [InlineData(\"localhost:9090\", \"example.com;localHost\")]\n        [InlineData(\"example.com:443\", \"example.com;localhost\")]\n        [InlineData(\"localHost:80\", \"localhost;\")]\n        [InlineData(\"foo.eXample.com:443\", \"*.exampLe.com\")]\n        [InlineData(\"f.eXample.com:443\", \"*.exampLe.com\")]\n        [InlineData(\"127.0.0.1\", \"127.0.0.1\")]\n        [InlineData(\"127.0.0.1:443\", \"127.0.0.1\")]\n        [InlineData(\"xn--c1yn36f:443\", \"xn--c1yn36f\")]\n        [InlineData(\"xn--c1yn36f:443\", \"點看\")]\n        [InlineData(\"[::ABC]\", \"[::aBc]\")]\n        [InlineData(\"[::1]:80\", \"[::1]\")]\n        public async Task AllowsSpecifiedHost(string host, string allowedHost)\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddHostFiltering(options =>\n                    {\n                        options.AllowedHosts = allowedHost.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.Use((ctx, next) =>\n                    {\n                        // TestHost's ClientHandler doesn't let you set the host header, only the host in the URI\n                        // and that would over-normalize some of our test conditions like casing.\n                        ctx.Request.Headers[HeaderNames.Host] = host;\n                        return next();\n                    });\n                    app.UseHostFiltering();\n                    app.Run(c => Task.CompletedTask);\n                });\n            var server = new TestServer(builder);\n            var response = await server.CreateRequest(\"/\").GetAsync();\n            Assert.Equal(200, (int)response.StatusCode);\n        }\n\n        [Theory]\n        [InlineData(\"example.com\", \"localhost\")]\n        [InlineData(\"localhost:9090\", \"example.com;\")]\n        [InlineData(\";\", \"example.com;localhost\")]\n        [InlineData(\";:80\", \"example.com;localhost\")]\n        [InlineData(\":80\", \"localhost\")]\n        [InlineData(\":\", \"localhost\")]\n        [InlineData(\"example.com:443\", \"*.example.com\")]\n        [InlineData(\".example.com:443\", \"*.example.com\")]\n        [InlineData(\"foo.com:443\", \"*.example.com\")]\n        [InlineData(\"foo.example.com.bar:443\", \"*.example.com\")]\n        [InlineData(\".com:443\", \"*.com\")]\n        // Unicode in the host shouldn't be allowed without punycode anyways. This match fails because the middleware converts\n        // its input to punycode.\n        [InlineData(\"點看\", \"點看\")]\n        [InlineData(\"[::1\", \"[::1]\")]\n        [InlineData(\"[::1:80\", \"[::1]\")]\n        public async Task RejectsMismatchedHosts(string host, string allowedHost)\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddHostFiltering(options =>\n                    {\n                        options.AllowedHosts = allowedHost.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.Use((ctx, next) =>\n                    {\n                        // TestHost's ClientHandler doesn't let you set the host header, only the host in the URI\n                        // and that would reject some of our test conditions.\n                        ctx.Request.Headers[HeaderNames.Host] = host;\n                        return next();\n                    });\n                    app.UseHostFiltering();\n                    app.Run(c => throw new NotImplementedException(\"App\"));\n                });\n            var server = new TestServer(builder);\n            var response = await server.CreateRequest(\"/\").GetAsync();\n            Assert.Equal(400, (int)response.StatusCode);\n        }\n\n        [Fact]\n        public async Task SupportsDynamicOptionsReload()\n        {\n            var config = new ConfigurationBuilder().Add(new ReloadableMemorySource()).Build();\n            config[\"AllowedHosts\"] = \"localhost\";\n            var currentHost = \"otherHost\";\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddHostFiltering(options =>\n                    {\n                        options.AllowedHosts = new[] { config[\"AllowedHosts\"] };\n                    });\n                    services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(new ConfigurationChangeTokenSource<HostFilteringOptions>(config));\n                })\n                .Configure(app =>\n                {\n                    app.Use((ctx, next) =>\n                    {\n                        ctx.Request.Headers[HeaderNames.Host] = currentHost;\n                        return next();\n                    });\n                    app.UseHostFiltering();\n                    app.Run(c => Task.CompletedTask);\n                });\n            var server = new TestServer(builder);\n            var response = await server.CreateRequest(\"/\").GetAsync();\n            Assert.Equal(400, (int)response.StatusCode);\n\n            config[\"AllowedHosts\"] = \"otherHost\";\n\n            response = await server.CreateRequest(\"/\").GetAsync();\n            Assert.Equal(200, (int)response.StatusCode);\n        }\n\n        private class ReloadableMemorySource : IConfigurationSource\n        {\n            public IConfigurationProvider Build(IConfigurationBuilder builder)\n            {\n                return new ReloadableMemoryProvider();\n            }\n        }\n\n        internal class ReloadableMemoryProvider : ConfigurationProvider\n        {\n            public override void Set(string key, string value)\n            {\n                base.Set(key, value);\n                OnReload();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HostFiltering.Tests/Microsoft.AspNetCore.HostFiltering.Tests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.HostFiltering\\Microsoft.AspNetCore.HostFiltering.csproj\" />\n    <PackageReference Include=\"Microsoft.Extensions.Options.ConfigurationExtensions\" Version=\"$(MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpOverrides.Tests/ForwardedHeadersMiddlewareTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Linq;\nusing System.Net;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.TestHost;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.HttpOverrides\n{\n    public class ForwardedHeadersMiddlewareTests\n    {\n        [Fact]\n        public async Task XForwardedForDefaultSettingsChangeRemoteIpAndPort()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedFor\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-For\"] = \"11.111.111.11:9090\";\n            });\n\n            Assert.Equal(\"11.111.111.11\", context.Connection.RemoteIpAddress.ToString());\n            Assert.Equal(9090, context.Connection.RemotePort);\n            // No Original set if RemoteIpAddress started null.\n            Assert.False(context.Request.Headers.ContainsKey(\"X-Original-For\"));\n            // Should have been consumed and removed\n            Assert.False(context.Request.Headers.ContainsKey(\"X-Forwarded-For\"));\n        }\n\n        [Theory]\n        [InlineData(1, \"11.111.111.11.12345\", \"10.0.0.1\", 99)] // Invalid\n        public async Task XForwardedForFirstValueIsInvalid(int limit, string header, string expectedIp, int expectedPort)\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedFor,\n                        ForwardLimit = limit,\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-For\"] = header;\n                c.Connection.RemoteIpAddress = IPAddress.Parse(\"10.0.0.1\");\n                c.Connection.RemotePort = 99;\n            });\n\n            Assert.Equal(expectedIp, context.Connection.RemoteIpAddress.ToString());\n            Assert.Equal(expectedPort, context.Connection.RemotePort);\n            Assert.False(context.Request.Headers.ContainsKey(\"X-Original-For\"));\n            Assert.True(context.Request.Headers.ContainsKey(\"X-Forwarded-For\"));\n            Assert.Equal(header, context.Request.Headers[\"X-Forwarded-For\"]);\n        }\n\n        [Theory]\n        [InlineData(1, \"11.111.111.11:12345\", \"11.111.111.11\", 12345, \"\", false)]\n        [InlineData(1, \"11.111.111.11:12345\", \"11.111.111.11\", 12345, \"\", true)]\n        [InlineData(10, \"11.111.111.11:12345\", \"11.111.111.11\", 12345, \"\", false)]\n        [InlineData(10, \"11.111.111.11:12345\", \"11.111.111.11\", 12345, \"\", true)]\n        [InlineData(1, \"12.112.112.12:23456, 11.111.111.11:12345\", \"11.111.111.11\", 12345, \"12.112.112.12:23456\", false)]\n        [InlineData(1, \"12.112.112.12:23456, 11.111.111.11:12345\", \"11.111.111.11\", 12345, \"12.112.112.12:23456\", true)]\n        [InlineData(2, \"12.112.112.12:23456, 11.111.111.11:12345\", \"12.112.112.12\", 23456, \"\", false)]\n        [InlineData(2, \"12.112.112.12:23456, 11.111.111.11:12345\", \"12.112.112.12\", 23456, \"\", true)]\n        [InlineData(10, \"12.112.112.12:23456, 11.111.111.11:12345\", \"12.112.112.12\", 23456, \"\", false)]\n        [InlineData(10, \"12.112.112.12:23456, 11.111.111.11:12345\", \"12.112.112.12\", 23456, \"\", true)]\n        [InlineData(10, \"12.112.112.12.23456, 11.111.111.11:12345\", \"11.111.111.11\", 12345, \"12.112.112.12.23456\", false)] // Invalid 2nd value\n        [InlineData(10, \"12.112.112.12.23456, 11.111.111.11:12345\", \"11.111.111.11\", 12345, \"12.112.112.12.23456\", true)] // Invalid 2nd value\n        [InlineData(10, \"13.113.113.13:34567, 12.112.112.12.23456, 11.111.111.11:12345\", \"11.111.111.11\", 12345, \"13.113.113.13:34567,12.112.112.12.23456\", false)] // Invalid 2nd value\n        [InlineData(10, \"13.113.113.13:34567, 12.112.112.12.23456, 11.111.111.11:12345\", \"11.111.111.11\", 12345, \"13.113.113.13:34567,12.112.112.12.23456\", true)] // Invalid 2nd value\n        [InlineData(2, \"13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345\", \"12.112.112.12\", 23456, \"13.113.113.13:34567\", false)]\n        [InlineData(2, \"13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345\", \"12.112.112.12\", 23456, \"13.113.113.13:34567\", true)]\n        [InlineData(3, \"13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345\", \"13.113.113.13\", 34567, \"\", false)]\n        [InlineData(3, \"13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345\", \"13.113.113.13\", 34567, \"\", true)]\n        public async Task XForwardedForForwardLimit(int limit, string header, string expectedIp, int expectedPort, string remainingHeader, bool requireSymmetry)\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    var options = new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedFor,\n                        RequireHeaderSymmetry = requireSymmetry,\n                        ForwardLimit = limit,\n                    };\n                    options.KnownProxies.Clear();\n                    options.KnownNetworks.Clear();\n                    app.UseForwardedHeaders(options);\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-For\"] = header;\n                c.Connection.RemoteIpAddress = IPAddress.Parse(\"10.0.0.1\");\n                c.Connection.RemotePort = 99;\n            });\n\n            Assert.Equal(expectedIp, context.Connection.RemoteIpAddress.ToString());\n            Assert.Equal(expectedPort, context.Connection.RemotePort);\n            Assert.Equal(remainingHeader, context.Request.Headers[\"X-Forwarded-For\"].ToString());\n        }\n\n        [Theory]\n        [InlineData(\"11.111.111.11\", false)]\n        [InlineData(\"127.0.0.1\", true)]\n        [InlineData(\"127.0.1.1\", true)]\n        [InlineData(\"::1\", true)]\n        [InlineData(\"::\", false)]\n        public async Task XForwardedForLoopback(string originalIp, bool expectForwarded)\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedFor,\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-For\"] = \"10.0.0.1:1234\";\n                c.Connection.RemoteIpAddress = IPAddress.Parse(originalIp);\n                c.Connection.RemotePort = 99;\n            });\n\n            if (expectForwarded)\n            {\n                Assert.Equal(\"10.0.0.1\", context.Connection.RemoteIpAddress.ToString());\n                Assert.Equal(1234, context.Connection.RemotePort);\n                Assert.True(context.Request.Headers.ContainsKey(\"X-Original-For\"));\n                Assert.Equal(new IPEndPoint(IPAddress.Parse(originalIp), 99).ToString(),\n                    context.Request.Headers[\"X-Original-For\"]);\n            }\n            else\n            {\n                Assert.Equal(originalIp, context.Connection.RemoteIpAddress.ToString());\n                Assert.Equal(99, context.Connection.RemotePort);\n                Assert.False(context.Request.Headers.ContainsKey(\"X-Original-For\"));\n            }\n        }\n\n        [Theory]\n        [InlineData(1, \"11.111.111.11:12345\", \"20.0.0.1\", \"10.0.0.1\", 99, false)]\n        [InlineData(1, \"11.111.111.11:12345\", \"20.0.0.1\", \"10.0.0.1\", 99, true)]\n        [InlineData(1, \"\", \"10.0.0.1\", \"10.0.0.1\", 99, false)]\n        [InlineData(1, \"\", \"10.0.0.1\", \"10.0.0.1\", 99, true)]\n        [InlineData(1, \"11.111.111.11:12345\", \"10.0.0.1\", \"11.111.111.11\", 12345, false)]\n        [InlineData(1, \"11.111.111.11:12345\", \"10.0.0.1\", \"11.111.111.11\", 12345, true)]\n        [InlineData(1, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1\", \"11.111.111.11\", 12345, false)]\n        [InlineData(1, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1\", \"11.111.111.11\", 12345, true)]\n        [InlineData(1, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11\", \"11.111.111.11\", 12345, false)]\n        [InlineData(1, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11\", \"11.111.111.11\", 12345, true)]\n        [InlineData(2, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11\", \"12.112.112.12\", 23456, false)]\n        [InlineData(2, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11\", \"12.112.112.12\", 23456, true)]\n        [InlineData(1, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"11.111.111.11\", 12345, false)]\n        [InlineData(1, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"11.111.111.11\", 12345, true)]\n        [InlineData(2, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"12.112.112.12\", 23456, false)]\n        [InlineData(2, \"12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"12.112.112.12\", 23456, true)]\n        [InlineData(3, \"13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"13.113.113.13\", 34567, false)]\n        [InlineData(3, \"13.113.113.13:34567, 12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"13.113.113.13\", 34567, true)]\n        [InlineData(3, \"13.113.113.13:34567, 12.112.112.12;23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"11.111.111.11\", 12345, false)] // Invalid 2nd IP\n        [InlineData(3, \"13.113.113.13:34567, 12.112.112.12;23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"11.111.111.11\", 12345, true)] // Invalid 2nd IP\n        [InlineData(3, \"13.113.113.13;34567, 12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"12.112.112.12\", 23456, false)] // Invalid 3rd IP\n        [InlineData(3, \"13.113.113.13;34567, 12.112.112.12:23456, 11.111.111.11:12345\", \"10.0.0.1,11.111.111.11,12.112.112.12\", \"12.112.112.12\", 23456, true)] // Invalid 3rd IP\n        public async Task XForwardedForForwardKnownIps(int limit, string header, string knownIPs, string expectedIp, int expectedPort, bool requireSymmetry)\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    var options = new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedFor,\n                        RequireHeaderSymmetry = requireSymmetry,\n                        ForwardLimit = limit,\n                    };\n                    foreach (var ip in knownIPs.Split(',').Select(text => IPAddress.Parse(text)))\n                    {\n                        options.KnownProxies.Add(ip);\n                    }\n                    app.UseForwardedHeaders(options);\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-For\"] = header;\n                c.Connection.RemoteIpAddress = IPAddress.Parse(\"10.0.0.1\");\n                c.Connection.RemotePort = 99;\n            });\n\n            Assert.Equal(expectedIp, context.Connection.RemoteIpAddress.ToString());\n            Assert.Equal(expectedPort, context.Connection.RemotePort);\n        }\n\n        [Fact]\n        public async Task XForwardedForOverrideBadIpDoesntChangeRemoteIp()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedFor\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-For\"] = \"BAD-IP\";\n            });\n\n            Assert.Null(context.Connection.RemoteIpAddress);\n        }\n\n        [Fact]\n        public async Task XForwardedHostOverrideChangesRequestHost()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedHost\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Host\"] = \"testhost\";\n            });\n\n            Assert.Equal(\"testhost\", context.Request.Host.ToString());\n        }\n\n        public static TheoryData<string> HostHeaderData\n        {\n            get\n            {\n                return new TheoryData<string>() {\n                    \"z\",\n                    \"1\",\n                    \"y:1\",\n                    \"1:1\",\n                    \"[ABCdef]\",\n                    \"[abcDEF]:0\",\n                    \"[abcdef:127.2355.1246.114]:0\",\n                    \"[::1]:80\",\n                    \"127.0.0.1:80\",\n                    \"900.900.900.900:9523547852\",\n                    \"foo\",\n                    \"foo:234\",\n                    \"foo.bar.baz\",\n                    \"foo.BAR.baz:46245\",\n                    \"foo.ba-ar.baz:46245\",\n                    \"-foo:1234\",\n                    \"xn--c1yn36f:134\",\n                    \"-\",\n                    \"_\",\n                    \"~\",\n                    \"!\",\n                    \"$\",\n                    \"'\",\n                    \"(\",\n                    \")\",\n                };\n            }\n        }\n\n        [Theory]\n        [MemberData(nameof(HostHeaderData))]\n        public async Task XForwardedHostAllowsValidCharacters(string host)\n        {\n            var assertsExecuted = false;\n\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedHost\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.Equal(host, context.Request.Host.ToString());\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Host\"] = host;\n            });\n            Assert.True(assertsExecuted);\n        }\n\n        public static TheoryData<string> HostHeaderInvalidData\n        {\n            get\n            {\n                // see https://tools.ietf.org/html/rfc7230#section-5.4\n                var data = new TheoryData<string>() {\n                    \"\", // Empty\n                    \"[]\", // Too short\n                    \"[::]\", // Too short\n                    \"[ghijkl]\", // Non-hex\n                    \"[afd:adf:123\", // Incomplete\n                    \"[afd:adf]123\", // Missing :\n                    \"[afd:adf]:\", // Missing port digits\n                    \"[afd adf]\", // Space\n                    \"[ad-314]\", // dash\n                    \":1234\", // Missing host\n                    \"a:b:c\", // Missing []\n                    \"::1\", // Missing []\n                    \"::\", // Missing everything\n                    \"abcd:1abcd\", // Letters in port\n                    \"abcd:1.2\", // Dot in port\n                    \"1.2.3.4:\", // Missing port digits\n                    \"1.2 .4\", // Space\n                };\n\n                // These aren't allowed anywhere in the host header\n                var invalid = \"\\\"#%*+/;<=>?@[]\\\\^`{}|\";\n                foreach (var ch in invalid)\n                {\n                    data.Add(ch.ToString());\n                }\n\n                invalid = \"!\\\"#$%&'()*+,/;<=>?@[]\\\\^_`{}|~-\";\n                foreach (var ch in invalid)\n                {\n                    data.Add(\"[abd\" + ch + \"]:1234\");\n                }\n\n                invalid = \"!\\\"#$%&'()*+/;<=>?@[]\\\\^_`{}|~:abcABC-.\";\n                foreach (var ch in invalid)\n                {\n                    data.Add(\"a.b.c:\" + ch);\n                }\n\n                return data;\n            }\n        }\n\n        [Theory]\n        [MemberData(nameof(HostHeaderInvalidData))]\n        public async Task XForwardedHostFailsForInvalidCharacters(string host)\n        {\n            var assertsExecuted = false;\n\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedHost\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.NotEqual(host, context.Request.Host.Value);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Host\"] = host;\n            });\n            Assert.True(assertsExecuted);\n        }\n\n        [Theory]\n        [InlineData(\"localHost\", \"localhost\")]\n        [InlineData(\"localHost\", \"*\")] // Any - Used by HttpSys\n        [InlineData(\"localHost\", \"[::]\")] // IPv6 Any - This is what Kestrel reports when binding to *\n        [InlineData(\"localHost\", \"0.0.0.0\")] // IPv4 Any\n        [InlineData(\"localhost:9090\", \"example.com;localHost\")]\n        [InlineData(\"example.com:443\", \"example.com;localhost\")]\n        [InlineData(\"localHost:80\", \"localhost;\")]\n        [InlineData(\"foo.eXample.com:443\", \"*.exampLe.com\")]\n        [InlineData(\"f.eXample.com:443\", \"*.exampLe.com\")]\n        [InlineData(\"127.0.0.1\", \"127.0.0.1\")]\n        [InlineData(\"127.0.0.1:443\", \"127.0.0.1\")]\n        [InlineData(\"xn--c1yn36f:443\", \"xn--c1yn36f\")]\n        [InlineData(\"xn--c1yn36f:443\", \"點看\")]\n        [InlineData(\"[::ABC]\", \"[::aBc]\")]\n        [InlineData(\"[::1]:80\", \"[::1]\")]\n        public async Task XForwardedHostAllowsSpecifiedHost(string host, string allowedHost)\n        {\n            bool assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedHost,\n                        AllowedHosts = allowedHost.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.Equal(host, context.Request.Headers[HeaderNames.Host]);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n            var response = await server.SendAsync(ctx =>\n            {\n                ctx.Request.Headers[\"X-forwarded-Host\"] = host;\n            });\n            Assert.True(assertsExecuted);\n        }\n\n        [Theory]\n        [InlineData(\"example.com\", \"localhost\")]\n        [InlineData(\"localhost:9090\", \"example.com;\")]\n        [InlineData(\";\", \"example.com;localhost\")]\n        [InlineData(\";:80\", \"example.com;localhost\")]\n        [InlineData(\":80\", \"localhost\")]\n        [InlineData(\":\", \"localhost\")]\n        [InlineData(\"example.com:443\", \"*.example.com\")]\n        [InlineData(\".example.com:443\", \"*.example.com\")]\n        [InlineData(\"foo.com:443\", \"*.example.com\")]\n        [InlineData(\"foo.example.com.bar:443\", \"*.example.com\")]\n        [InlineData(\".com:443\", \"*.com\")]\n        // Unicode in the host shouldn't be allowed without punycode anyways. This match fails because the middleware converts\n        // its input to punycode.\n        [InlineData(\"點看\", \"點看\")]\n        [InlineData(\"[::1\", \"[::1]\")]\n        [InlineData(\"[::1:80\", \"[::1]\")]\n        public async Task XForwardedHostFailsMismatchedHosts(string host, string allowedHost)\n        {\n            bool assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedHost,\n                        AllowedHosts = new[] { allowedHost }\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.NotEqual<string>(host, context.Request.Headers[HeaderNames.Host]);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n            var response = await server.SendAsync(ctx =>\n            {\n                ctx.Request.Headers[\"X-forwarded-Host\"] = host;\n            });\n            Assert.True(assertsExecuted);\n        }\n\n        [Fact]\n        public async Task XForwardedHostStopsAtFirstUnspecifiedHost()\n        {\n            bool assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedHost,\n                        ForwardLimit = 10,\n                        AllowedHosts = new[] { \"bar.com\", \"*.foo.com\" }\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.Equal(\"bar.foo.com:432\", context.Request.Headers[HeaderNames.Host]);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n            var response = await server.SendAsync(ctx =>\n            {\n                ctx.Request.Headers[\"X-forwarded-Host\"] = \"stuff:523, bar.foo.com:432, bar.com:80\";\n            });\n            Assert.True(assertsExecuted);\n        }\n\n        [Theory]\n        [InlineData(0, \"h1\", \"http\")]\n        [InlineData(1, \"\", \"http\")]\n        [InlineData(1, \"h1\", \"h1\")]\n        [InlineData(3, \"h1\", \"h1\")]\n        [InlineData(1, \"h2, h1\", \"h1\")]\n        [InlineData(2, \"h2, h1\", \"h2\")]\n        [InlineData(10, \"h3, h2, h1\", \"h3\")]\n        public async Task XForwardedProtoOverrideChangesRequestProtocol(int limit, string header, string expected)\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedProto,\n                        ForwardLimit = limit,\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = header;\n            });\n\n            Assert.Equal(expected, context.Request.Scheme);\n        }\n\n        public static TheoryData<string> ProtoHeaderData\n        {\n            get\n            {\n                // ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n                return new TheoryData<string>() {\n                    \"z\",\n                    \"Z\",\n                    \"1\",\n                    \"y+\",\n                    \"1-\",\n                    \"a.\",\n                };\n            }\n        }\n\n        [Theory]\n        [MemberData(nameof(ProtoHeaderData))]\n        public async Task XForwardedProtoAcceptsValidProtocols(string scheme)\n        {\n            var assertsExecuted = false;\n\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedProto\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.Equal(scheme, context.Request.Scheme);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = scheme;\n            });\n            Assert.True(assertsExecuted);\n        }\n\n        public static TheoryData<string> ProtoHeaderInvalidData\n        {\n            get\n            {\n                // ALPHA *( ALPHA / DIGIT / \"+\" / \"-\" / \".\" )\n                var data = new TheoryData<string>() {\n                    \"a b\", // Space\n                };\n\n                // These aren't allowed anywhere in the scheme header\n                var invalid = \"!\\\"#$%&'()*/:;<=>?@[]\\\\^_`{}|~\";\n                foreach (var ch in invalid)\n                {\n                    data.Add(ch.ToString());\n                }\n\n                return data;\n            }\n        }\n\n        [Theory]\n        [MemberData(nameof(ProtoHeaderInvalidData))]\n        public async Task XForwardedProtoRejectsInvalidProtocols(string scheme)\n        {\n            var assertsExecuted = false;\n\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedProto,\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.Equal(\"http\", context.Request.Scheme);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = scheme;\n            });\n            Assert.True(assertsExecuted);\n        }\n\n        [Theory]\n        [InlineData(0, \"h1\", \"::1\", \"http\")]\n        [InlineData(1, \"\", \"::1\", \"http\")]\n        [InlineData(1, \"h1\", \"::1\", \"h1\")]\n        [InlineData(3, \"h1\", \"::1\", \"h1\")]\n        [InlineData(3, \"h2, h1\", \"::1\", \"http\")]\n        [InlineData(5, \"h2, h1\", \"::1, ::1\", \"h2\")]\n        [InlineData(10, \"h3, h2, h1\", \"::1, ::1, ::1\", \"h3\")]\n        [InlineData(10, \"h3, h2, h1\", \"::1, badip, ::1\", \"h1\")]\n        public async Task XForwardedProtoOverrideLimitedByXForwardedForCount(int limit, string protoHeader, string forHeader, string expected)\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor,\n                        RequireHeaderSymmetry = true,\n                        ForwardLimit = limit,\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = protoHeader;\n                c.Request.Headers[\"X-Forwarded-For\"] = forHeader;\n            });\n\n            Assert.Equal(expected, context.Request.Scheme);\n        }\n\n        [Theory]\n        [InlineData(0, \"h1\", \"::1\", \"http\")]\n        [InlineData(1, \"\", \"::1\", \"http\")]\n        [InlineData(1, \"h1\", \"\", \"h1\")]\n        [InlineData(1, \"h1\", \"::1\", \"h1\")]\n        [InlineData(3, \"h1\", \"::1\", \"h1\")]\n        [InlineData(3, \"h1\", \"::1, ::1\", \"h1\")]\n        [InlineData(3, \"h2, h1\", \"::1\", \"h2\")]\n        [InlineData(5, \"h2, h1\", \"::1, ::1\", \"h2\")]\n        [InlineData(10, \"h3, h2, h1\", \"::1, ::1, ::1\", \"h3\")]\n        [InlineData(10, \"h3, h2, h1\", \"::1, badip, ::1\", \"h1\")]\n        public async Task XForwardedProtoOverrideCanBeIndependentOfXForwardedForCount(int limit, string protoHeader, string forHeader, string expected)\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor,\n                        RequireHeaderSymmetry = false,\n                        ForwardLimit = limit,\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = protoHeader;\n                c.Request.Headers[\"X-Forwarded-For\"] = forHeader;\n            });\n\n            Assert.Equal(expected, context.Request.Scheme);\n        }\n\n        [Theory]\n        [InlineData(\"\", \"\", \"::1\", false, \"http\")]\n        [InlineData(\"h1\", \"\", \"::1\", false, \"http\")]\n        [InlineData(\"h1\", \"F::\", \"::1\", false, \"h1\")]\n        [InlineData(\"h1\", \"F::\", \"E::\", false, \"h1\")]\n        [InlineData(\"\", \"\", \"::1\", true, \"http\")]\n        [InlineData(\"h1\", \"\", \"::1\", true, \"http\")]\n        [InlineData(\"h1\", \"F::\", \"::1\", true, \"h1\")]\n        [InlineData(\"h1\", \"\", \"F::\", true, \"http\")]\n        [InlineData(\"h1\", \"E::\", \"F::\", true, \"http\")]\n        [InlineData(\"h2, h1\", \"\", \"::1\", true, \"http\")]\n        [InlineData(\"h2, h1\", \"F::, D::\", \"::1\", true, \"h1\")]\n        [InlineData(\"h2, h1\", \"E::, D::\", \"F::\", true, \"http\")]\n        public async Task XForwardedProtoOverrideLimitedByLoopback(string protoHeader, string forHeader, string remoteIp, bool loopback, string expected)\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    var options = new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor,\n                        RequireHeaderSymmetry = true,\n                        ForwardLimit = 5,\n                    };\n                    if (!loopback)\n                    {\n                        options.KnownNetworks.Clear();\n                        options.KnownProxies.Clear();\n                    }\n                    app.UseForwardedHeaders(options);\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = protoHeader;\n                c.Request.Headers[\"X-Forwarded-For\"] = forHeader;\n                c.Connection.RemoteIpAddress = IPAddress.Parse(remoteIp);\n            });\n\n            Assert.Equal(expected, context.Request.Scheme);\n        }\n\n        [Fact]\n        public void AllForwardsDisabledByDefault()\n        {\n            var options = new ForwardedHeadersOptions();\n            Assert.True(options.ForwardedHeaders == ForwardedHeaders.None);\n            Assert.Equal(1, options.ForwardLimit);\n            Assert.Single(options.KnownNetworks);\n            Assert.Single(options.KnownProxies);\n        }\n\n        [Fact]\n        public async Task AllForwardsEnabledChangeRequestRemoteIpHostandProtocol()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.All\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = \"Protocol\";\n                c.Request.Headers[\"X-Forwarded-For\"] = \"11.111.111.11\";\n                c.Request.Headers[\"X-Forwarded-Host\"] = \"testhost\";\n            });\n\n            Assert.Equal(\"11.111.111.11\", context.Connection.RemoteIpAddress.ToString());\n            Assert.Equal(\"testhost\", context.Request.Host.ToString());\n            Assert.Equal(\"Protocol\", context.Request.Scheme);\n        }\n\n        [Fact]\n        public async Task AllOptionsDisabledRequestDoesntChange()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.None\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = \"Protocol\";\n                c.Request.Headers[\"X-Forwarded-For\"] = \"11.111.111.11\";\n                c.Request.Headers[\"X-Forwarded-Host\"] = \"otherhost\";\n            });\n\n            Assert.Null(context.Connection.RemoteIpAddress);\n            Assert.Equal(\"localhost\", context.Request.Host.ToString());\n            Assert.Equal(\"http\", context.Request.Scheme);\n        }\n\n        [Fact]\n        public async Task PartiallyEnabledForwardsPartiallyChangesRequest()\n        {\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(new ForwardedHeadersOptions\n                    {\n                        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-Proto\"] = \"Protocol\";\n                c.Request.Headers[\"X-Forwarded-For\"] = \"11.111.111.11\";\n            });\n\n            Assert.Equal(\"11.111.111.11\", context.Connection.RemoteIpAddress.ToString());\n            Assert.Equal(\"localhost\", context.Request.Host.ToString());\n            Assert.Equal(\"Protocol\", context.Request.Scheme);\n        }\n\n        [Theory]\n        [InlineData(\"22.33.44.55,::ffff:127.0.0.1\", \"\", \"\", \"22.33.44.55\")]\n        [InlineData(\"22.33.44.55,::ffff:172.123.142.121\", \"172.123.142.121\", \"\", \"22.33.44.55\")]\n        [InlineData(\"22.33.44.55,::ffff:172.123.142.121\", \"::ffff:172.123.142.121\", \"\", \"22.33.44.55\")]\n        [InlineData(\"22.33.44.55,::ffff:172.123.142.121,172.32.24.23\", \"\", \"172.0.0.0/8\", \"22.33.44.55\")]\n        [InlineData(\"2a00:1450:4009:802::200e,2a02:26f0:2d:183::356e,::ffff:172.123.142.121,172.32.24.23\", \"\", \"172.0.0.0/8,2a02:26f0:2d:183::1/64\", \"2a00:1450:4009:802::200e\")]\n        [InlineData(\"22.33.44.55,2a02:26f0:2d:183::356e,::ffff:127.0.0.1\", \"2a02:26f0:2d:183::356e\", \"\", \"22.33.44.55\")]\n        public async Task XForwardForIPv4ToIPv6Mapping(string forHeader, string knownProxies, string knownNetworks, string expectedRemoteIp)\n        {\n            var options = new ForwardedHeadersOptions\n            {\n                ForwardedHeaders = ForwardedHeaders.XForwardedFor,\n                ForwardLimit = null,\n            };\n\n            foreach (var knownProxy in knownProxies.Split(new string[] { \",\" }, StringSplitOptions.RemoveEmptyEntries))\n            {\n                var proxy = IPAddress.Parse(knownProxy);\n                options.KnownProxies.Add(proxy);\n            }\n            foreach (var knownNetwork in knownNetworks.Split(new string[] { \",\" }, options:StringSplitOptions.RemoveEmptyEntries))\n            {\n                var knownNetworkParts = knownNetwork.Split('/');\n                var networkIp = IPAddress.Parse(knownNetworkParts[0]);\n                var prefixLength = int.Parse(knownNetworkParts[1]);\n                options.KnownNetworks.Add(new IPNetwork(networkIp, prefixLength));\n            }\n\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseForwardedHeaders(options);\n                });\n            var server = new TestServer(builder);\n\n            var context = await server.SendAsync(c =>\n            {\n                c.Request.Headers[\"X-Forwarded-For\"] = forHeader;\n            });\n\n            Assert.Equal(expectedRemoteIp, context.Connection.RemoteIpAddress.ToString());\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpOverrides.Tests/HttpMethodOverrideMiddlewareTest.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.TestHost;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.HttpOverrides\n{\n    public class HttpMethodOverrideMiddlewareTest\n    {\n        [Fact]\n        public async Task XHttpMethodOverrideHeaderAvaiableChangesRequestMethod()\n        {\n            var assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseHttpMethodOverride();\n                    app.Run(context =>\n                    {\n                        assertsExecuted = true;\n                        Assert.Equal(\"DELETE\", context.Request.Method);\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var req = new HttpRequestMessage(HttpMethod.Post, \"\");\n            req.Headers.Add(\"X-Http-Method-Override\", \"DELETE\");\n            await server.CreateClient().SendAsync(req);\n            Assert.True(assertsExecuted);\n        }\n\n        [Fact]\n        public async Task XHttpMethodOverrideHeaderUnavaiableDoesntChangeRequestMethod()\n        {\n            var assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseHttpMethodOverride();\n                    app.Run(context =>\n                    {\n                        Assert.Equal(\"POST\",context.Request.Method);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var req = new HttpRequestMessage(HttpMethod.Post, \"\");\n            await server.CreateClient().SendAsync(req);\n            Assert.True(assertsExecuted);\n        }\n\n        [Fact]\n        public async Task XHttpMethodOverrideFromGetRequestDoesntChangeMethodType()\n        {\n            var assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseHttpMethodOverride();\n                    app.Run(context =>\n                    {\n                        Assert.Equal(\"GET\", context.Request.Method);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var req = new HttpRequestMessage(HttpMethod.Get, \"\");\n            await server.CreateClient().SendAsync(req);\n            Assert.True(assertsExecuted);\n        }\n\n\n        [Fact]\n        public async Task FormFieldAvailableChangesRequestMethod()\n        {\n            var assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseHttpMethodOverride(new HttpMethodOverrideOptions()\n                    {\n                        FormFieldName = \"_METHOD\"\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.Equal(\"DELETE\", context.Request.Method);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var req = new HttpRequestMessage(HttpMethod.Post, \"\");\n            req.Content = new FormUrlEncodedContent(new Dictionary<string, string>()\n            {\n                { \"_METHOD\", \"DELETE\" }\n            });\n\n\n            await server.CreateClient().SendAsync(req);\n            Assert.True(assertsExecuted);\n        }\n\n        [Fact]\n        public async Task FormFieldUnavailableDoesNotChangeRequestMethod()\n        {\n            var assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseHttpMethodOverride(new HttpMethodOverrideOptions()\n                    {\n                        FormFieldName = \"_METHOD\"\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.Equal(\"POST\", context.Request.Method);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var req = new HttpRequestMessage(HttpMethod.Post, \"\");\n            req.Content = new FormUrlEncodedContent(new Dictionary<string, string>()\n            {\n            });\n\n\n            await server.CreateClient().SendAsync(req);\n            Assert.True(assertsExecuted);\n        }\n\n        [Fact]\n        public async Task FormFieldEmptyDoesNotChangeRequestMethod()\n        {\n            var assertsExecuted = false;\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseHttpMethodOverride(new HttpMethodOverrideOptions()\n                    {\n                        FormFieldName = \"_METHOD\"\n                    });\n                    app.Run(context =>\n                    {\n                        Assert.Equal(\"POST\", context.Request.Method);\n                        assertsExecuted = true;\n                        return Task.FromResult(0);\n                    });\n                });\n            var server = new TestServer(builder);\n\n            var req = new HttpRequestMessage(HttpMethod.Post, \"\");\n            req.Content = new FormUrlEncodedContent(new Dictionary<string, string>()\n            {\n                { \"_METHOD\", \"\" }\n            });\n\n\n            await server.CreateClient().SendAsync(req);\n            Assert.True(assertsExecuted);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpOverrides.Tests/IPEndPointParserTest.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Net;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.HttpOverrides.Internal\n{\n    public class IPEndPointParserTests\n    {\n        [Theory]\n        [InlineData(\"127.0.0.1\", \"127.0.0.1\", 0)]\n        [InlineData(\"127.0.0.1:1\", \"127.0.0.1\", 1)]\n        [InlineData(\"1\", \"0.0.0.1\", 0)]\n        [InlineData(\"1:1\", \"0.0.0.1\", 1)]\n        [InlineData(\"::1\", \"::1\", 0)]\n        [InlineData(\"[::1]\", \"::1\", 0)]\n        [InlineData(\"[::1]:1\", \"::1\", 1)]\n        public void ParsesCorrectly(string input, string expectedAddress, int expectedPort)\n        {\n            IPEndPoint endpoint;\n            var success = IPEndPointParser.TryParse(input, out endpoint);\n            Assert.True(success);\n            Assert.Equal(expectedAddress, endpoint.Address.ToString());\n            Assert.Equal(expectedPort, endpoint.Port);\n        }\n\n        [Theory]\n        [InlineData(null)]\n        [InlineData(\"[::1]:\")]\n        [InlineData(\"[::1:\")]\n        [InlineData(\"::1:\")]\n        [InlineData(\"127:\")]\n        [InlineData(\"127.0.0.1:\")]\n        [InlineData(\"\")]\n        [InlineData(\"[]\")]\n        [InlineData(\"]\")]\n        [InlineData(\"]:1\")]\n        public void ShouldNotParse(string input)\n        {\n            IPEndPoint endpoint;\n            var success = IPEndPointParser.TryParse(input, out endpoint);\n            Assert.False(success);\n            Assert.Null(endpoint);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpOverrides.Tests/IPNetworkTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\nusing System.Net;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.HttpOverrides\n{\n    public class IPNetworkTest\n    {\n        [Theory]\n        [InlineData(\"10.1.1.0\", 8, \"10.1.1.10\")]\n        [InlineData(\"174.0.0.0\", 7, \"175.1.1.10\")]\n        [InlineData(\"10.174.0.0\", 15, \"10.175.1.10\")]\n        [InlineData(\"10.168.0.0\", 14, \"10.171.1.10\")]\n        public void Contains_Positive(string prefixText, int length, string addressText)\n        {\n            var network = new IPNetwork(IPAddress.Parse(prefixText), length);\n            Assert.True(network.Contains(IPAddress.Parse(addressText)));\n        }\n\n        [Theory]\n        [InlineData(\"10.1.0.0\", 16, \"10.2.1.10\")]\n        [InlineData(\"174.0.0.0\", 7, \"173.1.1.10\")]\n        [InlineData(\"10.174.0.0\", 15, \"10.173.1.10\")]\n        [InlineData(\"10.168.0.0\", 14, \"10.172.1.10\")]\n        public void Contains_Negative(string prefixText, int length, string addressText)\n        {\n            var network = new IPNetwork(IPAddress.Parse(prefixText), length);\n            Assert.False(network.Contains(IPAddress.Parse(addressText)));\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpOverrides.Tests/Microsoft.AspNetCore.HttpOverrides.Tests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.HttpOverrides\\Microsoft.AspNetCore.HttpOverrides.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Testing\" Version=\"$(MicrosoftExtensionsLoggingTestingPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpsPolicy.Tests/HstsMiddlewareTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.TestHost;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Logging.Testing;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy.Tests\n{\n    public class HstsMiddlewareTests\n    {\n        [Fact]\n        public async Task SetOptionsWithDefault_SetsMaxAgeToCorrectValue()\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                })\n                .Configure(app =>\n                {\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            client.BaseAddress = new Uri(\"https://example.com:5050\");\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n            Assert.Equal(\"max-age=2592000\", response.Headers.GetValues(HeaderNames.StrictTransportSecurity).FirstOrDefault());\n        }\n\n        [Theory]\n        [InlineData(0, false, false, \"max-age=0\")]\n        [InlineData(-1, false, false, \"max-age=-1\")]\n        [InlineData(0, true, false, \"max-age=0; includeSubDomains\")]\n        [InlineData(50000, false, true, \"max-age=50000; preload\")]\n        [InlineData(0, true, true, \"max-age=0; includeSubDomains; preload\")]\n        [InlineData(50000, true, true, \"max-age=50000; includeSubDomains; preload\")]\n        public async Task SetOptionsThroughConfigure_SetsHeaderCorrectly(int maxAge, bool includeSubDomains, bool preload, string expected)\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.Configure<HstsOptions>(options => {\n                        options.Preload = preload;\n                        options.IncludeSubDomains = includeSubDomains;\n                        options.MaxAge = TimeSpan.FromSeconds(maxAge);\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            client.BaseAddress = new Uri(\"https://example.com:5050\");\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n            Assert.Equal(expected, response.Headers.GetValues(HeaderNames.StrictTransportSecurity).FirstOrDefault());\n        }\n\n        [Theory]\n        [InlineData(0, false, false, \"max-age=0\")]\n        [InlineData(-1, false, false, \"max-age=-1\")]\n        [InlineData(0, true, false, \"max-age=0; includeSubDomains\")]\n        [InlineData(50000, false, true, \"max-age=50000; preload\")]\n        [InlineData(0, true, true, \"max-age=0; includeSubDomains; preload\")]\n        [InlineData(50000, true, true, \"max-age=50000; includeSubDomains; preload\")]\n        public async Task SetOptionsThroughHelper_SetsHeaderCorrectly(int maxAge, bool includeSubDomains, bool preload, string expected)\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddHsts(options => {\n                        options.Preload = preload;\n                        options.IncludeSubDomains = includeSubDomains;\n                        options.MaxAge = TimeSpan.FromSeconds(maxAge);\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            client.BaseAddress = new Uri(\"https://example.com:5050\");\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n            Assert.Equal(expected, response.Headers.GetValues(HeaderNames.StrictTransportSecurity).FirstOrDefault());\n        }\n\n        [Theory]\n        [InlineData(\"localhost\")]\n        [InlineData(\"Localhost\")]\n        [InlineData(\"LOCALHOST\")]\n        [InlineData(\"127.0.0.1\")]\n        [InlineData(\"[::1]\")]\n        public async Task DefaultExcludesCommonLocalhostDomains_DoesNotSetHstsHeader(string host)\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HstsMiddleware>,\n                TestSink.EnableWithTypeName<HstsMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            \n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n                .Configure(app =>\n                {\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            client.BaseAddress = new Uri($\"https://{host}:5050\");\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n            Assert.Empty(response.Headers);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.Single();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal($\"The host '{host}' is excluded. Skipping HSTS header.\", message.State.ToString(), ignoreCase: true);\n        }\n\n        [Theory]\n        [InlineData(\"localhost\")]\n        [InlineData(\"127.0.0.1\")]\n        [InlineData(\"[::1]\")]\n        public async Task AllowLocalhostDomainsIfListIsReset_SetHstsHeader(string host)\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HstsMiddleware>,\n                TestSink.EnableWithTypeName<HstsMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n\n                    services.AddHsts(options =>\n                    {\n                        options.ExcludedHosts.Clear();\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            client.BaseAddress = new Uri($\"https://{host}:5050\");\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n            Assert.Single(response.Headers);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.Single();\n            Assert.Equal(LogLevel.Trace, message.LogLevel);\n            Assert.Equal(\"Adding HSTS header to response.\", message.State.ToString());\n        }\n        \n        [Theory]\n        [InlineData(\"example.com\")]\n        [InlineData(\"Example.com\")]\n        [InlineData(\"EXAMPLE.COM\")]\n        public async Task AddExcludedDomains_DoesNotAddHstsHeader(string host)\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HstsMiddleware>,\n                TestSink.EnableWithTypeName<HstsMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                    \n                    services.AddHsts(options => {\n                        options.ExcludedHosts.Add(host);\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            client.BaseAddress = new Uri($\"https://{host}:5050\");\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n            Assert.Empty(response.Headers);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.Single();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal($\"The host '{host}' is excluded. Skipping HSTS header.\", message.State.ToString(), ignoreCase: true);\n        }\n\n        [Fact]\n        public async Task WhenRequestIsInsecure_DoesNotAddHstsHeader()\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HstsMiddleware>,\n                TestSink.EnableWithTypeName<HstsMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n                .Configure(app =>\n                {\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            client.BaseAddress = new Uri(\"http://example.com:5050\");\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n            Assert.Empty(response.Headers);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.Single();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal(\"The request is insecure. Skipping HSTS header.\", message.State.ToString());\n        }\n\n        [Fact]\n        public async Task WhenRequestIsSecure_AddsHstsHeader()\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HstsMiddleware>,\n                TestSink.EnableWithTypeName<HstsMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n                .Configure(app =>\n                {\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            client.BaseAddress = new Uri(\"https://example.com:5050\");\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n            Assert.Contains(response.Headers, x => x.Key == HeaderNames.StrictTransportSecurity);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.Single();\n            Assert.Equal(LogLevel.Trace, message.LogLevel);\n            Assert.Equal(\"Adding HSTS header to response.\", message.State.ToString());\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpsPolicy.Tests/HttpsPolicyTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Linq;\nusing System.Net;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Hosting.Server.Features;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.AspNetCore.TestHost;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy.Tests\n{\n    public class HttpsPolicyTests\n    {\n        [Theory]\n        [InlineData(302, 443, 2592000, false, false, \"max-age=2592000\", \"https://localhost/\")]\n        [InlineData(301, 5050, 2592000, false, false, \"max-age=2592000\", \"https://localhost:5050/\")]\n        [InlineData(301, 443, 2592000, false, false, \"max-age=2592000\", \"https://localhost/\")]\n        [InlineData(301, 443, 2592000, true, false, \"max-age=2592000; includeSubDomains\", \"https://localhost/\")]\n        [InlineData(301, 443, 2592000, false, true, \"max-age=2592000; preload\", \"https://localhost/\")]\n        [InlineData(301, 443, 2592000, true, true, \"max-age=2592000; includeSubDomains; preload\", \"https://localhost/\")]\n        [InlineData(302, 5050, 2592000, true, true, \"max-age=2592000; includeSubDomains; preload\", \"https://localhost:5050/\")]\n        public async Task SetsBothHstsAndHttpsRedirection_RedirectOnFirstRequest_HstsOnSecondRequest(int statusCode, int? tlsPort, int maxAge, bool includeSubDomains, bool preload, string expectedHstsHeader, string expectedUrl)\n        {\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.Configure<HttpsRedirectionOptions>(options =>\n                    {\n                        options.RedirectStatusCode = statusCode;\n                        options.HttpsPort = tlsPort;\n                    });\n                    services.Configure<HstsOptions>(options =>\n                    {\n                        options.IncludeSubDomains = includeSubDomains;\n                        options.MaxAge = TimeSpan.FromSeconds(maxAge);\n                        options.Preload = preload;\n                        options.ExcludedHosts.Clear(); // allowing localhost for testing\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.UseHttpsRedirection();\n                    app.UseHsts();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var featureCollection = new FeatureCollection();\n            featureCollection.Set<IServerAddressesFeature>(new ServerAddressesFeature());\n            var server = new TestServer(builder, featureCollection);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(statusCode, (int)response.StatusCode);\n            Assert.Equal(expectedUrl, response.Headers.Location.ToString());\n\n            client = server.CreateClient();\n            client.BaseAddress = new Uri(response.Headers.Location.ToString());\n            request = new HttpRequestMessage(HttpMethod.Get, expectedUrl);\n            response = await client.SendAsync(request);\n\n            Assert.Equal(expectedHstsHeader, response.Headers.GetValues(HeaderNames.StrictTransportSecurity).FirstOrDefault());\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpsPolicy.Tests/HttpsRedirectionMiddlewareTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Linq;\nusing System.Net;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Hosting.Server.Features;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.AspNetCore.TestHost;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Logging.Testing;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.HttpsPolicy.Tests\n{\n    public class HttpsRedirectionMiddlewareTests\n    {\n        [Fact]\n        public async Task SetOptions_NotEnabledByDefault()\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n                .Configure(app =>\n                {\n                    app.UseHttpsRedirection();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.Single();\n            Assert.Equal(LogLevel.Warning, message.LogLevel);\n            Assert.Equal(\"Failed to determine the https port for redirect.\", message.State.ToString());\n        }\n\n        [Theory]\n        [InlineData(302, 5001, \"https://localhost:5001/\")]\n        [InlineData(307, 1, \"https://localhost:1/\")]\n        [InlineData(308, 3449, \"https://localhost:3449/\")]\n        [InlineData(301, 5050, \"https://localhost:5050/\")]\n        [InlineData(301, 443, \"https://localhost/\")]\n        public async Task SetOptions_SetStatusCodeHttpsPort(int statusCode, int? httpsPort, string expected)\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                    services.Configure<HttpsRedirectionOptions>(options =>\n                    {\n                        options.RedirectStatusCode = statusCode;\n                        options.HttpsPort = httpsPort;\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.UseHttpsRedirection();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(statusCode, (int)response.StatusCode);\n            Assert.Equal(expected, response.Headers.Location.ToString());\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.Single();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal($\"Redirecting to '{expected}'.\", message.State.ToString());\n        }\n\n        [Theory]\n        [InlineData(302, 5001, \"https://localhost:5001/\")]\n        [InlineData(307, 1, \"https://localhost:1/\")]\n        [InlineData(308, 3449, \"https://localhost:3449/\")]\n        [InlineData(301, 5050, \"https://localhost:5050/\")]\n        [InlineData(301, 443, \"https://localhost/\")]\n        public async Task SetOptionsThroughHelperMethod_SetStatusCodeAndHttpsPort(int statusCode, int? httpsPort, string expectedUrl)\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                    services.AddHttpsRedirection(options =>\n                    {\n                        options.RedirectStatusCode = statusCode;\n                        options.HttpsPort = httpsPort;\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.UseHttpsRedirection();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(statusCode, (int)response.StatusCode);\n            Assert.Equal(expectedUrl, response.Headers.Location.ToString());\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.Single();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal($\"Redirecting to '{expectedUrl}'.\", message.State.ToString());\n        }\n\n        [Theory]\n        [InlineData(null, null, \"https://localhost:4444/\", \"https://localhost:4444/\")]\n        [InlineData(null, null, \"https://localhost:443/\", \"https://localhost/\")]\n        [InlineData(null, null, \"https://localhost/\", \"https://localhost/\")]\n        [InlineData(null, \"5000\", \"https://localhost:4444/\", \"https://localhost:5000/\")]\n        [InlineData(null, \"443\", \"https://localhost:4444/\", \"https://localhost/\")]\n        [InlineData(443, \"5000\", \"https://localhost:4444/\", \"https://localhost/\")]\n        [InlineData(4000, \"5000\", \"https://localhost:4444/\", \"https://localhost:4000/\")]\n        [InlineData(5000, null, \"https://localhost:4444/\", \"https://localhost:5000/\")]\n        public async Task SetHttpsPortEnvironmentVariableAndServerFeature_ReturnsCorrectStatusCodeOnResponse(\n            int? optionsHttpsPort, string configHttpsPort, string serverAddressFeatureUrl, string expectedUrl)\n        {\n            var builder = new WebHostBuilder()\n               .ConfigureServices(services =>\n               {\n                   services.AddHttpsRedirection(options =>\n                   {\n                       options.HttpsPort = optionsHttpsPort;\n                   });\n               })\n               .Configure(app =>\n               {\n                   app.UseHttpsRedirection();\n                   app.Run(context =>\n                   {\n                       return context.Response.WriteAsync(\"Hello world\");\n                   });\n               });\n\n            builder.UseSetting(\"HTTPS_PORT\", configHttpsPort);\n\n            var featureCollection = new FeatureCollection();\n            featureCollection.Set<IServerAddressesFeature>(new ServerAddressesFeature());\n\n            var server = new TestServer(builder, featureCollection);\n            if (serverAddressFeatureUrl != null)\n            {\n                server.Features.Get<IServerAddressesFeature>().Addresses.Add(serverAddressFeatureUrl);\n            }\n\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(expectedUrl, response.Headers.Location.ToString());\n        }\n\n        [Fact]\n        public async Task SetServerAddressesFeature_SingleHttpsAddress_Success()\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n               .Configure(app =>\n               {\n                   app.UseHttpsRedirection();\n                   app.Run(context =>\n                   {\n                       return context.Response.WriteAsync(\"Hello world\");\n                   });\n               });\n\n            var featureCollection = new FeatureCollection();\n            featureCollection.Set<IServerAddressesFeature>(new ServerAddressesFeature());\n            var server = new TestServer(builder, featureCollection);\n\n            server.Features.Get<IServerAddressesFeature>().Addresses.Add(\"https://localhost:5050\");\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(\"https://localhost:5050/\", response.Headers.Location.ToString());\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Equal(2, logMessages.Count);\n            var message = logMessages.First();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal(\"Https port '5050' discovered from server endpoints.\", message.State.ToString());\n\n            message = logMessages.Skip(1).First();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal(\"Redirecting to 'https://localhost:5050/'.\", message.State.ToString());\n        }\n\n        [Fact]\n        public async Task SetServerAddressesFeature_MultipleHttpsAddresses_LogsAndFailsToRedirect()\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n               .Configure(app =>\n               {\n                   app.UseHttpsRedirection();\n                   app.Run(context =>\n                   {\n                       return context.Response.WriteAsync(\"Hello world\");\n                   });\n               });\n\n            var featureCollection = new FeatureCollection();\n            featureCollection.Set<IServerAddressesFeature>(new ServerAddressesFeature());\n            var server = new TestServer(builder, featureCollection);\n\n            server.Features.Get<IServerAddressesFeature>().Addresses.Add(\"https://localhost:5050\");\n            server.Features.Get<IServerAddressesFeature>().Addresses.Add(\"https://localhost:5051\");\n\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n            Assert.Equal(200, (int)response.StatusCode);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.First();\n            Assert.Equal(LogLevel.Warning, message.LogLevel);\n            Assert.Equal(\"Cannot determine the https port from IServerAddressesFeature, multiple values were found. \" +\n                \"Please set the desired port explicitly on HttpsRedirectionOptions.HttpsPort.\", message.State.ToString());\n        }\n\n        [Fact]\n        public async Task SetServerAddressesFeature_MultipleHttpsAddressesWithSamePort_Success()\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n               .Configure(app =>\n               {\n                   app.UseHttpsRedirection();\n                   app.Run(context =>\n                   {\n                       return context.Response.WriteAsync(\"Hello world\");\n                   });\n               });\n\n            var featureCollection = new FeatureCollection();\n            featureCollection.Set<IServerAddressesFeature>(new ServerAddressesFeature());\n            var server = new TestServer(builder, featureCollection);\n\n            server.Features.Get<IServerAddressesFeature>().Addresses.Add(\"https://localhost:5050\");\n            server.Features.Get<IServerAddressesFeature>().Addresses.Add(\"https://example.com:5050\");\n\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(\"https://localhost:5050/\", response.Headers.Location.ToString());\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Equal(2, logMessages.Count);\n            var message = logMessages.First();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal(\"Https port '5050' discovered from server endpoints.\", message.State.ToString());\n\n            message = logMessages.Skip(1).First();\n            Assert.Equal(LogLevel.Debug, message.LogLevel);\n            Assert.Equal(\"Redirecting to 'https://localhost:5050/'.\", message.State.ToString());\n        }\n\n        [Fact]\n        public async Task NoServerAddressFeature_DoesNotThrow_DoesNotRedirect()\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n                .Configure(app =>\n                {\n                    app.UseHttpsRedirection();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            var response = await client.SendAsync(request);\n            Assert.Equal(200, (int)response.StatusCode);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.First();\n            Assert.Equal(LogLevel.Warning, message.LogLevel);\n            Assert.Equal(\"Failed to determine the https port for redirect.\", message.State.ToString());\n        }\n\n        [Fact]\n        public async Task SetNullAddressFeature_DoesNotThrow()\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>,\n                TestSink.EnableWithTypeName<HttpsRedirectionMiddleware>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n                .Configure(app =>\n                {\n                    app.UseHttpsRedirection();\n                    app.Run(context =>\n                    {\n                        return context.Response.WriteAsync(\"Hello world\");\n                    });\n                });\n\n            var featureCollection = new FeatureCollection();\n            featureCollection.Set<IServerAddressesFeature>(null);\n            var server = new TestServer(builder, featureCollection);\n\n            var client = server.CreateClient();\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            var response = await client.SendAsync(request);\n            Assert.Equal(200, (int)response.StatusCode);\n\n            var logMessages = sink.Writes.ToList();\n\n            Assert.Single(logMessages);\n            var message = logMessages.First();\n            Assert.Equal(LogLevel.Warning, message.LogLevel);\n            Assert.Equal(\"Failed to determine the https port for redirect.\", message.State.ToString());\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.HttpsPolicy.Tests/Microsoft.AspNetCore.HttpsPolicy.Tests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>netcoreapp2.2</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.HttpsPolicy\\Microsoft.AspNetCore.HttpsPolicy.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Testing\" Version=\"$(MicrosoftExtensionsLoggingTestingPackageVersion)\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.ResponseCompression.Tests/BodyWrapperStreamTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Net.Http.Headers;\nusing Moq;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.ResponseCompression.Tests\n{\n    public class BodyWrapperStreamTests\n    {\n        [Theory]\n        [InlineData(null, \"Accept-Encoding\")]\n        [InlineData(\"\", \"Accept-Encoding\")]\n        [InlineData(\"AnotherHeader\", \"AnotherHeader,Accept-Encoding\")]\n        [InlineData(\"Accept-Encoding\", \"Accept-Encoding\")]\n        [InlineData(\"accepT-encodinG\", \"accepT-encodinG\")]\n        [InlineData(\"accept-encoding,AnotherHeader\", \"accept-encoding,AnotherHeader\")]\n        public void OnWrite_AppendsAcceptEncodingToVaryHeader_IfNotPresent(string providedVaryHeader, string expectedVaryHeader)\n        {\n            var httpContext = new DefaultHttpContext();\n            httpContext.Response.Headers[HeaderNames.Vary] = providedVaryHeader;\n            var stream = new BodyWrapperStream(httpContext, new MemoryStream(), new MockResponseCompressionProvider(flushable: true), null, null);\n\n            stream.Write(new byte[] { }, 0, 0);\n\n\n            Assert.Equal(expectedVaryHeader, httpContext.Response.Headers[HeaderNames.Vary]);\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void Write_IsPassedToUnderlyingStream_WhenDisableResponseBuffering(bool flushable)\n        {\n\n            var buffer = new byte[] { 1 };\n            byte[] written = null;\n\n            var mock = new Mock<Stream>();\n            mock.SetupGet(s => s.CanWrite).Returns(true);\n            mock.Setup(s => s.Write(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()))\n                .Callback<byte[], int, int>((b, o, c) =>\n                {\n                    written = new ArraySegment<byte>(b, 0, c).ToArray();\n                });\n\n            var stream = new BodyWrapperStream(new DefaultHttpContext(), mock.Object, new MockResponseCompressionProvider(flushable), null, null);\n\n            stream.DisableResponseBuffering();\n            stream.Write(buffer, 0, buffer.Length);\n\n            Assert.Equal(buffer, written);\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public async Task WriteAsync_IsPassedToUnderlyingStream_WhenDisableResponseBuffering(bool flushable)\n        {\n            var buffer = new byte[] { 1 };\n\n            var memoryStream = new MemoryStream();\n            var stream = new BodyWrapperStream(new DefaultHttpContext(), memoryStream, new MockResponseCompressionProvider(flushable), null, null);\n\n            stream.DisableResponseBuffering();\n            await stream.WriteAsync(buffer, 0, buffer.Length);\n\n            Assert.Equal(buffer, memoryStream.ToArray());\n        }\n\n        [Fact]\n        public async Task SendFileAsync_IsPassedToUnderlyingStream_WhenDisableResponseBuffering()\n        {\n            var memoryStream = new MemoryStream();\n\n            var stream = new BodyWrapperStream(new DefaultHttpContext(), memoryStream, new MockResponseCompressionProvider(true), null, null);\n\n            stream.DisableResponseBuffering();\n\n            var path = \"testfile1kb.txt\";\n            await stream.SendFileAsync(path, 0, null, CancellationToken.None);\n\n            Assert.Equal(File.ReadAllBytes(path), memoryStream.ToArray());\n        }\n\n        [Theory]\n        [InlineData(true)]\n        [InlineData(false)]\n        public void BeginWrite_IsPassedToUnderlyingStream_WhenDisableResponseBuffering(bool flushable)\n        {\n            var buffer = new byte[] { 1 };\n\n            var memoryStream = new MemoryStream();\n\n            var stream = new BodyWrapperStream(new DefaultHttpContext(), memoryStream, new MockResponseCompressionProvider(flushable), null, null);\n\n            stream.DisableResponseBuffering();\n            stream.BeginWrite(buffer, 0, buffer.Length, (o) => {}, null);\n\n            Assert.Equal(buffer, memoryStream.ToArray());\n        }\n\n        private class MockResponseCompressionProvider: IResponseCompressionProvider\n        {\n            private readonly bool _flushable;\n\n            public MockResponseCompressionProvider(bool flushable)\n            {\n                _flushable = flushable;\n            }\n\n            public ICompressionProvider GetCompressionProvider(HttpContext context)\n            {\n                return new MockCompressionProvider(_flushable);\n            }\n\n            public bool ShouldCompressResponse(HttpContext context)\n            {\n                return true;\n            }\n\n            public bool CheckRequestAcceptsCompression(HttpContext context)\n            {\n                return true;\n            }\n        }\n\n\n        private class MockCompressionProvider : ICompressionProvider\n        {\n            public MockCompressionProvider(bool flushable)\n            {\n                SupportsFlush = flushable;\n            }\n\n            public string EncodingName { get; }\n\n            public bool SupportsFlush { get; }\n\n            public Stream CreateStream(Stream outputStream)\n            {\n                if (SupportsFlush)\n                {\n                    return new BufferedStream(outputStream);\n                }\n                else\n                {\n                    return new NoFlushBufferedStream(outputStream);\n                }\n\n            }\n        }\n\n        private class NoFlushBufferedStream : Stream\n        {\n            private readonly BufferedStream _bufferedStream;\n\n            public NoFlushBufferedStream(Stream outputStream)\n            {\n                _bufferedStream = new BufferedStream(outputStream);\n            }\n\n            public override void Flush()\n            {\n            }\n\n            public override int Read(byte[] buffer, int offset, int count) => _bufferedStream.Read(buffer, offset, count);\n\n            public override long Seek(long offset, SeekOrigin origin) => _bufferedStream.Seek(offset, origin);\n\n            public override void SetLength(long value) => _bufferedStream.SetLength(value);\n\n            public override void Write(byte[] buffer, int offset, int count) => _bufferedStream.Write(buffer, offset, count);\n\n            public override bool CanRead => _bufferedStream.CanRead;\n\n            public override bool CanSeek => _bufferedStream.CanSeek;\n\n            public override bool CanWrite => _bufferedStream.CanWrite;\n\n            public override long Length => _bufferedStream.Length;\n\n            public override long Position\n            {\n                get { return _bufferedStream.Position; }\n                set { _bufferedStream.Position = value; }\n            }\n\n            protected override void Dispose(bool disposing)\n            {\n                base.Dispose(disposing);\n                _bufferedStream.Flush();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.ResponseCompression.Tests/Microsoft.AspNetCore.ResponseCompression.Tests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <Content Include=\"testfile1kb.txt\" CopyToOutputDirectory=\"PreserveNewest\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.ResponseCompression\\Microsoft.AspNetCore.ResponseCompression.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Http\" Version=\"$(MicrosoftAspNetCoreHttpPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Testing\" Version=\"$(MicrosoftExtensionsLoggingTestingPackageVersion)\" />\n    <PackageReference Include=\"Microsoft.Net.Http.Headers\" Version=\"$(MicrosoftNetHttpHeadersPackageVersion)\" />\n    <PackageReference Include=\"Moq\" Version=\"$(MoqPackageVersion)\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.ResponseCompression.Tests/ResponseCompressionMiddlewareTest.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.IO.Compression;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.AspNetCore.TestHost;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Logging.Testing;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.ResponseCompression.Tests\n{\n    public class ResponseCompressionMiddlewareTest\n    {\n        private const string TextPlain = \"text/plain\";\n\n        public static IEnumerable<object[]> SupportedEncodings =>\n            TestData.Select(x => new object[] { x.EncodingName });\n\n        public static IEnumerable<object[]> SupportedEncodingsWithBodyLength =>\n            TestData.Select(x => new object[] { x.EncodingName, x.ExpectedBodyLength });\n\n        private static IEnumerable<EncodingTestData> TestData\n        {\n            get\n            {\n                yield return new EncodingTestData(\"gzip\", expectedBodyLength: 24);\n#if NETCOREAPP2_2\n                yield return new EncodingTestData(\"br\", expectedBodyLength: 20);\n#elif NET461\n#else\n#error Target frameworks need to be updated.\n#endif\n            }\n        }\n\n        [Fact]\n        public void Options_HttpsDisabledByDefault()\n        {\n            var options = new ResponseCompressionOptions();\n\n            Assert.False(options.EnableForHttps);\n        }\n\n        [Fact]\n        public async Task Request_NoAcceptEncoding_Uncompressed()\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: null, responseType: TextPlain);\n\n            CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: false);\n            AssertLog(logMessages.Single(), LogLevel.Debug, \"No response compression available, the Accept-Encoding header is missing or invalid.\");\n        }\n\n        [Fact]\n        public async Task Request_AcceptGzipDeflate_CompressedGzip()\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: new[] { \"gzip\", \"deflate\" }, responseType: TextPlain);\n\n            CheckResponseCompressed(response, expectedBodyLength: 24, expectedEncoding: \"gzip\");\n            AssertCompressedWithLog(logMessages, \"gzip\");\n        }\n\n        [Fact]\n        public async Task Request_AcceptBrotli_CompressedBrotli()\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: new[] { \"br\" }, responseType: TextPlain);\n\n#if NET461\n            CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: true);\n#elif NETCOREAPP2_2\n            CheckResponseCompressed(response, expectedBodyLength: 20, expectedEncoding: \"br\");\n            AssertCompressedWithLog(logMessages, \"br\");\n#else\n#error Target frameworks need to be updated.\n#endif\n        }\n\n        [Theory]\n        [InlineData(\"gzip\", \"br\")]\n        [InlineData(\"br\", \"gzip\")]\n        public async Task Request_AcceptMixed_CompressedBrotli(string encoding1, string encoding2)\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, new[] { encoding1, encoding2 }, responseType: TextPlain);\n\n#if NET461\n            CheckResponseCompressed(response, expectedBodyLength: 24, expectedEncoding: \"gzip\");\n            AssertCompressedWithLog(logMessages, \"gzip\");\n#elif NETCOREAPP2_2\n            CheckResponseCompressed(response, expectedBodyLength: 20, expectedEncoding: \"br\");\n            AssertCompressedWithLog(logMessages, \"br\");\n#else\n#error Target frameworks need to be updated.\n#endif\n        }\n\n#if NETCOREAPP2_2\n        [Theory]\n        [InlineData(\"gzip\", \"br\")]\n        [InlineData(\"br\", \"gzip\")]\n        public async Task Request_AcceptMixed_ConfiguredOrder_CompressedGzip(string encoding1, string encoding2)\n        {\n            void Configure(ResponseCompressionOptions options)\n            {\n                options.Providers.Add<GzipCompressionProvider>();\n                options.Providers.Add<BrotliCompressionProvider>();\n            }\n\n            var (response, logMessages) = await InvokeMiddleware(100, new[] { encoding1, encoding2 }, responseType: TextPlain, configure: Configure);\n\n            CheckResponseCompressed(response, expectedBodyLength: 24, expectedEncoding: \"gzip\");\n            AssertCompressedWithLog(logMessages, \"gzip\");\n        }\n#elif NET461\n#else\n#error Target frameworks need to be updated.\n#endif\n\n        [Fact]\n        public async Task Request_AcceptUnknown_NotCompressed()\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: new[] { \"unknown\" }, responseType: TextPlain);\n\n            CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: true);\n            Assert.Equal(3, logMessages.Count);\n            AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n            AssertLog(logMessages.Skip(1).First(), LogLevel.Trace, \"Response compression is available for this Content-Type.\");\n            AssertLog(logMessages.Skip(2).First(), LogLevel.Debug, \"No matching response compression provider found.\");\n        }\n\n        [Theory]\n        [InlineData(\"text/plain\")]\n        [InlineData(\"text/PLAIN\")]\n        [InlineData(\"text/plain; charset=ISO-8859-4\")]\n        [InlineData(\"text/plain ; charset=ISO-8859-4\")]\n        public async Task ContentType_WithCharset_Compress(string contentType)\n        {\n            var (response, logMessages) = await InvokeMiddleware(uncompressedBodyLength: 100, requestAcceptEncodings: new[] { \"gzip\" }, contentType);\n\n            CheckResponseCompressed(response, expectedBodyLength: 24, expectedEncoding: \"gzip\");\n            AssertCompressedWithLog(logMessages, \"gzip\");\n        }\n\n        [Fact]\n        public async Task GZipCompressionProvider_OptionsSetInDI_Compress()\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.NoCompression);\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        return context.Response.WriteAsync(new string('a', 100));\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(\"gzip\");\n\n            var response = await client.SendAsync(request);\n\n            CheckResponseCompressed(response, expectedBodyLength: 123, expectedEncoding: \"gzip\");\n        }\n\n        [Theory]\n        [InlineData(\"\")]\n        [InlineData(\"text/plain2\")]\n        public async Task MimeTypes_OtherContentTypes_NoMatch(string contentType)\n        {\n            var (response, logMessages) = await InvokeMiddleware(uncompressedBodyLength: 100, requestAcceptEncodings: new[] { \"gzip\" }, contentType);\n\n            CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: false);\n            Assert.Equal(2, logMessages.Count);\n            AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n            var expected = string.IsNullOrEmpty(contentType) ? \"(null)\" : contentType;\n            AssertLog(logMessages.Skip(1).First(), LogLevel.Debug, $\"Response compression is not enabled for the Content-Type '{expected}'.\");\n        }\n\n        [Theory]\n        [InlineData(null, null, \"text/plain\", true)]\n        [InlineData(null, new string[0], \"text/plain\", true)]\n        [InlineData(null, new[] { \"TEXT/plain\" }, \"text/plain\", false)]\n        [InlineData(null, new[] { \"TEXT/*\" }, \"text/plain\", true)]\n        [InlineData(null, new[] { \"*/*\" }, \"text/plain\", true)]\n\n        [InlineData(new string[0], null, \"text/plain\", true)]\n        [InlineData(new string[0], new string[0], \"text/plain\", true)]\n        [InlineData(new string[0], new[] { \"TEXT/plain\" }, \"text/plain\", false)]\n        [InlineData(new string[0], new[] { \"TEXT/*\" }, \"text/plain\", true)]\n        [InlineData(new string[0], new[] { \"*/*\" }, \"text/plain\", true)]\n\n        [InlineData(new[] { \"TEXT/plain\" }, null, \"text/plain\", true)]\n        [InlineData(new[] { \"TEXT/plain\" }, new string[0], \"text/plain\", true)]\n        [InlineData(new[] { \"TEXT/plain\" }, new[] { \"TEXT/plain\" }, \"text/plain\", false)]\n        [InlineData(new[] { \"TEXT/plain\" }, new[] { \"TEXT/*\" }, \"text/plain\", true)]\n        [InlineData(new[] { \"TEXT/plain\" }, new[] { \"*/*\" }, \"text/plain\", true)]\n\n        [InlineData(new[] { \"TEXT/*\" }, null, \"text/plain\", true)]\n        [InlineData(new[] { \"TEXT/*\" }, new string[0], \"text/plain\", true)]\n        [InlineData(new[] { \"TEXT/*\" }, new[] { \"TEXT/plain\" }, \"text/plain\", false)]\n        [InlineData(new[] { \"TEXT/*\" }, new[] { \"TEXT/*\" }, \"text/plain\", false)]\n        [InlineData(new[] { \"TEXT/*\" }, new[] { \"*/*\" }, \"text/plain\", true)]\n\n        [InlineData(new[] { \"*/*\" }, null, \"text/plain\", true)]\n        [InlineData(new[] { \"*/*\" }, new string[0], \"text/plain\", true)]\n        [InlineData(new[] { \"*/*\" }, new[] { \"TEXT/plain\" }, \"text/plain\", false)]\n        [InlineData(new[] { \"*/*\" }, new[] { \"TEXT/*\" }, \"text/plain\", false)]\n        [InlineData(new[] { \"*/*\" }, new[] { \"*/*\" }, \"text/plain\", true)]\n\n        [InlineData(null, null, \"text/plain2\", false)]\n        [InlineData(null, new string[0], \"text/plain2\", false)]\n        [InlineData(null, new[] { \"TEXT/plain\" }, \"text/plain2\", false)]\n        [InlineData(null, new[] { \"TEXT/*\" }, \"text/plain2\", false)]\n        [InlineData(null, new[] { \"*/*\" }, \"text/plain2\", false)]\n\n        [InlineData(new string[0], null, \"text/plain2\", false)]\n        [InlineData(new string[0], new string[0], \"text/plain2\", false)]\n        [InlineData(new string[0], new[] { \"TEXT/plain\" }, \"text/plain2\", false)]\n        [InlineData(new string[0], new[] { \"TEXT/*\" }, \"text/plain2\", false)]\n        [InlineData(new string[0], new[] { \"*/*\" }, \"text/plain2\", false)]\n\n        [InlineData(new[] { \"TEXT/plain\" }, null, \"text/plain2\", false)]\n        [InlineData(new[] { \"TEXT/plain\" }, new string[0], \"text/plain2\", false)]\n        [InlineData(new[] { \"TEXT/plain\" }, new[] { \"TEXT/plain\" }, \"text/plain2\", false)]\n        [InlineData(new[] { \"TEXT/plain\" }, new[] { \"TEXT/*\" }, \"text/plain2\", false)]\n        [InlineData(new[] { \"TEXT/plain\" }, new[] { \"*/*\" }, \"text/plain2\", false)]\n\n        [InlineData(new[] { \"TEXT/*\" }, null, \"text/plain2\", true)]\n        [InlineData(new[] { \"TEXT/*\" }, new string[0], \"text/plain2\", true)]\n        [InlineData(new[] { \"TEXT/*\" }, new[] { \"TEXT/plain\" }, \"text/plain2\", true)]\n        [InlineData(new[] { \"TEXT/*\" }, new[] { \"TEXT/*\" }, \"text/plain2\", false)]\n        [InlineData(new[] { \"TEXT/*\" }, new[] { \"*/*\" }, \"text/plain2\", true)]\n\n        [InlineData(new[] { \"*/*\" }, null, \"text/plain2\", true)]\n        [InlineData(new[] { \"*/*\" }, new string[0], \"text/plain2\", true)]\n        [InlineData(new[] { \"*/*\" }, new[] { \"TEXT/plain\" }, \"text/plain2\", true)]\n        [InlineData(new[] { \"*/*\" }, new[] { \"TEXT/*\" }, \"text/plain2\", false)]\n        [InlineData(new[] { \"*/*\" }, new[] { \"*/*\" }, \"text/plain2\", true)]\n        public async Task MimeTypes_IncludedAndExcluded(\n            string[] mimeTypes,\n            string[] excludedMimeTypes,\n            string contentType,\n            bool compress\n            )\n        {\n            var (response, logMessages) = await InvokeMiddleware(uncompressedBodyLength: 100, requestAcceptEncodings: new[] { \"gzip\" }, contentType,\n                configure: options =>\n                {\n                    options.MimeTypes = mimeTypes;\n                    options.ExcludedMimeTypes = excludedMimeTypes;\n                });\n\n            if (compress)\n            {\n                CheckResponseCompressed(response, expectedBodyLength: 24, expectedEncoding: \"gzip\");\n                AssertCompressedWithLog(logMessages, \"gzip\");\n            }\n            else\n            {\n                CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: false);\n                Assert.Equal(2, logMessages.Count);\n                AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n                AssertLog(logMessages.Skip(1).First(), LogLevel.Debug, $\"Response compression is not enabled for the Content-Type '{contentType}'.\");\n            }\n        }\n\n        [Fact]\n        public async Task NoIncludedMimeTypes_UseDefaults()\n        {\n            var (response, logMessages) = await InvokeMiddleware(uncompressedBodyLength: 100, requestAcceptEncodings: new[] { \"gzip\" }, TextPlain,\n                configure: options =>\n                {\n                    options.ExcludedMimeTypes = new[] { \"text/*\" };\n                });\n\n            CheckResponseCompressed(response, expectedBodyLength: 24, expectedEncoding: \"gzip\");\n            AssertCompressedWithLog(logMessages, \"gzip\");\n        }\n\n        [Theory]\n        [InlineData(\"\")]\n        [InlineData(\"text/plain\")]\n        [InlineData(\"text/PLAIN\")]\n        [InlineData(\"text/plain; charset=ISO-8859-4\")]\n        [InlineData(\"text/plain ; charset=ISO-8859-4\")]\n        [InlineData(\"text/plain2\")]\n        public async Task NoBody_NotCompressed(string contentType)\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = contentType;\n                        return Task.FromResult(0);\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(\"gzip\");\n\n            var response = await client.SendAsync(request);\n\n            CheckResponseNotCompressed(response, expectedBodyLength: 0, sendVaryHeader: false);\n        }\n\n        [Fact]\n        public async Task Request_AcceptStar_Compressed()\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: new[] { \"*\" }, responseType: TextPlain);\n\n#if NET461\n            CheckResponseCompressed(response, expectedBodyLength: 24, expectedEncoding: \"gzip\");\n            AssertCompressedWithLog(logMessages, \"gzip\");\n#elif NETCOREAPP2_2\n            CheckResponseCompressed(response, expectedBodyLength: 20, expectedEncoding: \"br\");\n            AssertCompressedWithLog(logMessages, \"br\");\n#else\n#error Target frameworks need to be updated.\n#endif\n        }\n\n        [Fact]\n        public async Task Request_AcceptIdentity_NotCompressed()\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: new[] { \"identity\" }, responseType: TextPlain);\n\n            CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: true);\n            Assert.Equal(3, logMessages.Count);\n            AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n            AssertLog(logMessages.Skip(1).First(), LogLevel.Trace, \"Response compression is available for this Content-Type.\");\n            AssertLog(logMessages.Skip(2).First(), LogLevel.Debug, \"No matching response compression provider found.\");\n        }\n\n        [Theory]\n        [InlineData(new[] { \"identity;q=0.5\", \"gzip;q=1\" }, 24)]\n        [InlineData(new[] { \"identity;q=0\", \"gzip;q=0.8\" }, 24)]\n        [InlineData(new[] { \"identity;q=0.5\", \"gzip\" }, 24)]\n        public async Task Request_AcceptWithHigherCompressionQuality_Compressed(string[] acceptEncodings, int expectedBodyLength)\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: acceptEncodings, responseType: TextPlain);\n\n            CheckResponseCompressed(response, expectedBodyLength: expectedBodyLength, expectedEncoding: \"gzip\");\n            AssertCompressedWithLog(logMessages, \"gzip\");\n        }\n\n        [Theory]\n        [InlineData(new[] { \"gzip;q=0.5\", \"identity;q=0.8\" }, 100)]\n        public async Task Request_AcceptWithhigherIdentityQuality_NotCompressed(string[] acceptEncodings, int expectedBodyLength)\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: acceptEncodings, responseType: TextPlain);\n\n            CheckResponseNotCompressed(response, expectedBodyLength: expectedBodyLength, sendVaryHeader: true);\n            Assert.Equal(3, logMessages.Count);\n            AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n            AssertLog(logMessages.Skip(1).First(), LogLevel.Trace, \"Response compression is available for this Content-Type.\");\n            AssertLog(logMessages.Skip(2).First(), LogLevel.Debug, \"No matching response compression provider found.\");\n        }\n\n        [Fact]\n        public async Task Response_UnknownMimeType_NotCompressed()\n        {\n            var (response, logMessages) = await InvokeMiddleware(100, requestAcceptEncodings: new[] { \"gzip\" }, responseType: \"text/custom\");\n\n            CheckResponseNotCompressed(response, expectedBodyLength: 100, sendVaryHeader: false);\n            Assert.Equal(2, logMessages.Count);\n            AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n            AssertLog(logMessages.Skip(1).First(), LogLevel.Debug, \"Response compression is not enabled for the Content-Type 'text/custom'.\");\n        }\n\n        [Fact]\n        public async Task Response_WithContentRange_NotCompressed()\n        {\n            var (response, logMessages) = await InvokeMiddleware(50, requestAcceptEncodings: new[] { \"gzip\" }, responseType: TextPlain, addResponseAction: (r) =>\n            {\n                r.Headers[HeaderNames.ContentRange] = \"1-2/*\";\n            });\n\n            CheckResponseNotCompressed(response, expectedBodyLength: 50, sendVaryHeader: false);\n            Assert.Equal(2, logMessages.Count);\n            AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n            AssertLog(logMessages.Skip(1).First(), LogLevel.Debug, \"Response compression disabled due to the Content-Range header.\");\n        }\n\n\n        [Fact]\n        public async Task Response_WithContentEncodingAlreadySet_NotReCompressed()\n        {\n            var otherContentEncoding = \"something\";\n\n            var (response, logMessages) = await InvokeMiddleware(50, requestAcceptEncodings: new[] { \"gzip\" }, responseType: TextPlain, addResponseAction: (r) =>\n            {\n                r.Headers[HeaderNames.ContentEncoding] = otherContentEncoding;\n            });\n\n            Assert.True(response.Content.Headers.ContentEncoding.Contains(otherContentEncoding));\n            Assert.False(response.Content.Headers.ContentEncoding.Contains(\"gzip\"));\n            Assert.Equal(50, response.Content.Headers.ContentLength);\n            Assert.Equal(2, logMessages.Count);\n            AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n            AssertLog(logMessages.Skip(1).First(), LogLevel.Debug, \"Response compression disabled due to the Content-Encoding header.\");\n        }\n\n        [Theory]\n        [InlineData(false, 100)]\n        [InlineData(true, 24)]\n        public async Task Request_Https_CompressedIfEnabled(bool enableHttps, int expectedLength)\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<ResponseCompressionProvider>,\n                TestSink.EnableWithTypeName<ResponseCompressionProvider>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                    services.AddResponseCompression(options =>\n                    {\n                        options.EnableForHttps = enableHttps;\n                        options.MimeTypes = new[] { TextPlain };\n                    });\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.ContentType = TextPlain;\n                        return context.Response.WriteAsync(new string('a', 100));\n                    });\n                });\n\n            var server = new TestServer(builder)\n            {\n                BaseAddress = new Uri(\"https://localhost/\")\n            };\n\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(\"gzip\");\n\n            var response = await client.SendAsync(request);\n\n            Assert.Equal(expectedLength, response.Content.ReadAsByteArrayAsync().Result.Length);\n\n            var logMessages = sink.Writes.ToList();\n            if (enableHttps)\n            {\n                AssertCompressedWithLog(logMessages, \"gzip\");\n            }\n            else\n            {\n                AssertLog(logMessages.Single(), LogLevel.Debug, \"No response compression available for HTTPS requests. See ResponseCompressionOptions.EnableForHttps.\");\n            }\n        }\n\n        [Theory]\n        [MemberData(nameof(SupportedEncodingsWithBodyLength))]\n        public async Task FlushHeaders_SendsHeaders_Compresses(string encoding, int expectedBodyLength)\n        {\n            var responseReceived = new ManualResetEvent(false);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        context.Response.Body.Flush();\n                        Assert.True(responseReceived.WaitOne(TimeSpan.FromSeconds(3)));\n                        return context.Response.WriteAsync(new string('a', 100));\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(encoding);\n\n            var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);\n            responseReceived.Set();\n\n            await response.Content.LoadIntoBufferAsync();\n\n            CheckResponseCompressed(response, expectedBodyLength, encoding);\n        }\n\n        [Theory]\n        [MemberData(nameof(SupportedEncodingsWithBodyLength))]\n        public async Task FlushAsyncHeaders_SendsHeaders_Compresses(string encoding, int expectedBodyLength)\n        {\n            var responseReceived = new ManualResetEvent(false);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(async context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        await context.Response.Body.FlushAsync();\n                        Assert.True(responseReceived.WaitOne(TimeSpan.FromSeconds(3)));\n                        await context.Response.WriteAsync(new string('a', 100));\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(encoding);\n\n            var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);\n            responseReceived.Set();\n\n            await response.Content.LoadIntoBufferAsync();\n\n            CheckResponseCompressed(response, expectedBodyLength, encoding);\n        }\n\n        [Theory]\n        [MemberData(nameof(SupportedEncodings))]\n        public async Task FlushBody_CompressesAndFlushes(string encoding)\n        {\n            var responseReceived = new ManualResetEvent(false);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        context.Response.Body.Write(new byte[10], 0, 10);\n                        context.Response.Body.Flush();\n                        Assert.True(responseReceived.WaitOne(TimeSpan.FromSeconds(3)));\n                        context.Response.Body.Write(new byte[90], 0, 90);\n                        return Task.FromResult(0);\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(encoding);\n\n            var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);\n\n            Assert.False(response.Content.Headers.TryGetValues(HeaderNames.ContentMD5, out _));\n            Assert.Single(response.Content.Headers.ContentEncoding, encoding);\n\n            var body = await response.Content.ReadAsStreamAsync();\n            var read = await body.ReadAsync(new byte[100], 0, 100);\n            Assert.True(read > 0);\n\n            responseReceived.Set();\n\n            read = await body.ReadAsync(new byte[100], 0, 100);\n            Assert.True(read > 0);\n        }\n\n        [Theory]\n        [MemberData(nameof(SupportedEncodings))]\n        public async Task FlushAsyncBody_CompressesAndFlushes(string encoding)\n        {\n            var responseReceived = new ManualResetEvent(false);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(async context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        await context.Response.WriteAsync(new string('a', 10));\n                        await context.Response.Body.FlushAsync();\n                        Assert.True(responseReceived.WaitOne(TimeSpan.FromSeconds(3)));\n                        await context.Response.WriteAsync(new string('a', 90));\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(encoding);\n\n            var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);\n\n            Assert.False(response.Content.Headers.TryGetValues(HeaderNames.ContentMD5, out _));\n            Assert.Single(response.Content.Headers.ContentEncoding, encoding);\n\n            var body = await response.Content.ReadAsStreamAsync();\n            var read = await body.ReadAsync(new byte[100], 0, 100);\n            Assert.True(read > 0);\n\n            responseReceived.Set();\n\n            read = await body.ReadAsync(new byte[100], 0, 100);\n            Assert.True(read > 0);\n        }\n\n        [Theory]\n        [MemberData(nameof(SupportedEncodings))]\n        public async Task TrickleWriteAndFlush_FlushesEachWrite(string encoding)\n        {\n            var responseReceived = new[]\n            {\n                new ManualResetEvent(false),\n                new ManualResetEvent(false),\n                new ManualResetEvent(false),\n                new ManualResetEvent(false),\n                new ManualResetEvent(false),\n            };\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        context.Features.Get<IHttpBufferingFeature>()?.DisableResponseBuffering();\n\n                        foreach (var signal in responseReceived)\n                        {\n                            context.Response.Body.Write(new byte[1], 0, 1);\n                            context.Response.Body.Flush();\n                            Assert.True(signal.WaitOne(TimeSpan.FromSeconds(3)));\n                        }\n                        return Task.FromResult(0);\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(encoding);\n\n            var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);\n\n#if NET461 // Flush not supported, compression disabled\n            Assert.NotNull(response.Content.Headers.GetValues(HeaderNames.ContentMD5));\n            Assert.Empty(response.Content.Headers.ContentEncoding);\n#elif NETCOREAPP2_2 // Flush supported, compression enabled\n            Assert.False(response.Content.Headers.TryGetValues(HeaderNames.ContentMD5, out _));\n            Assert.Single(response.Content.Headers.ContentEncoding, encoding);\n#else\n#error Target frameworks need to be updated.\n#endif\n\n            var body = await response.Content.ReadAsStreamAsync();\n\n            foreach (var signal in responseReceived)\n            {\n                var read = await body.ReadAsync(new byte[100], 0, 100);\n                Assert.True(read > 0);\n\n                signal.Set();\n            }\n        }\n\n        [Theory]\n        [MemberData(nameof(SupportedEncodings))]\n        public async Task TrickleWriteAndFlushAsync_FlushesEachWrite(string encoding)\n        {\n            var responseReceived = new[]\n            {\n                new ManualResetEvent(false),\n                new ManualResetEvent(false),\n                new ManualResetEvent(false),\n                new ManualResetEvent(false),\n                new ManualResetEvent(false),\n            };\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(async context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        context.Features.Get<IHttpBufferingFeature>()?.DisableResponseBuffering();\n\n                        foreach (var signal in responseReceived)\n                        {\n                            await context.Response.WriteAsync(\"a\");\n                            await context.Response.Body.FlushAsync();\n                            Assert.True(signal.WaitOne(TimeSpan.FromSeconds(3)));\n                        }\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(encoding);\n\n            var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);\n\n#if NET461 // Flush not supported, compression disabled\n            Assert.NotNull(response.Content.Headers.GetValues(HeaderNames.ContentMD5));\n            Assert.Empty(response.Content.Headers.ContentEncoding);\n#elif NETCOREAPP2_2 // Flush supported, compression enabled\n            Assert.False(response.Content.Headers.TryGetValues(HeaderNames.ContentMD5, out _));\n            Assert.Single(response.Content.Headers.ContentEncoding, encoding);\n#else\n#error Target framework needs to be updated\n#endif\n\n            var body = await response.Content.ReadAsStreamAsync();\n\n            foreach (var signal in responseReceived)\n            {\n                var read = await body.ReadAsync(new byte[100], 0, 100);\n                Assert.True(read > 0);\n\n                signal.Set();\n            }\n        }\n\n        [Fact]\n        public async Task SendFileAsync_OnlySetIfFeatureAlreadyExists()\n        {\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        context.Response.ContentLength = 1024;\n                        var sendFile = context.Features.Get<IHttpSendFileFeature>();\n                        Assert.Null(sendFile);\n                        return Task.FromResult(0);\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(\"gzip\");\n\n            var response = await client.SendAsync(request);\n            response.EnsureSuccessStatusCode();\n        }\n\n        [Fact]\n        public async Task SendFileAsync_DifferentContentType_NotBypassed()\n        {\n            FakeSendFileFeature fakeSendFile = null;\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.Use((context, next) =>\n                    {\n                        fakeSendFile = new FakeSendFileFeature(context.Response.Body);\n                        context.Features.Set<IHttpSendFileFeature>(fakeSendFile);\n                        return next();\n                    });\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = \"custom/type\";\n                        context.Response.ContentLength = 1024;\n                        var sendFile = context.Features.Get<IHttpSendFileFeature>();\n                        Assert.NotNull(sendFile);\n                        return sendFile.SendFileAsync(\"testfile1kb.txt\", 0, null, CancellationToken.None);\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(\"gzip\");\n\n            var response = await client.SendAsync(request);\n\n            CheckResponseNotCompressed(response, expectedBodyLength: 1024, sendVaryHeader: false);\n\n            Assert.True(fakeSendFile.Invoked);\n        }\n\n        [Fact]\n        public async Task SendFileAsync_FirstWrite_CompressesAndFlushes()\n        {\n            FakeSendFileFeature fakeSendFile = null;\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.Use((context, next) =>\n                    {\n                        fakeSendFile = new FakeSendFileFeature(context.Response.Body);\n                        context.Features.Set<IHttpSendFileFeature>(fakeSendFile);\n                        return next();\n                    });\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        context.Response.ContentLength = 1024;\n                        var sendFile = context.Features.Get<IHttpSendFileFeature>();\n                        Assert.NotNull(sendFile);\n                        return sendFile.SendFileAsync(\"testfile1kb.txt\", 0, null, CancellationToken.None);\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(\"gzip\");\n\n            var response = await client.SendAsync(request);\n\n            CheckResponseCompressed(response, expectedBodyLength: 34, expectedEncoding: \"gzip\");\n\n            Assert.False(fakeSendFile.Invoked);\n        }\n\n        [Fact]\n        public async Task SendFileAsync_AfterFirstWrite_CompressesAndFlushes()\n        {\n            FakeSendFileFeature fakeSendFile = null;\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression();\n                })\n                .Configure(app =>\n                {\n                    app.Use((context, next) =>\n                    {\n                        fakeSendFile = new FakeSendFileFeature(context.Response.Body);\n                        context.Features.Set<IHttpSendFileFeature>(fakeSendFile);\n                        return next();\n                    });\n                    app.UseResponseCompression();\n                    app.Run(async context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = TextPlain;\n                        var sendFile = context.Features.Get<IHttpSendFileFeature>();\n                        Assert.NotNull(sendFile);\n\n                        await context.Response.WriteAsync(new string('a', 100));\n                        await sendFile.SendFileAsync(\"testfile1kb.txt\", 0, null, CancellationToken.None);\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            request.Headers.AcceptEncoding.ParseAdd(\"gzip\");\n\n            var response = await client.SendAsync(request);\n\n            CheckResponseCompressed(response, expectedBodyLength: 40, expectedEncoding: \"gzip\");\n\n            Assert.False(fakeSendFile.Invoked);\n        }\n\n        private async Task<(HttpResponseMessage, List<WriteContext>)> InvokeMiddleware(\n            int uncompressedBodyLength,\n            string[] requestAcceptEncodings,\n            string responseType,\n            Action<HttpResponse> addResponseAction = null,\n            Action<ResponseCompressionOptions> configure = null)\n        {\n            var sink = new TestSink(\n                TestSink.EnableWithTypeName<ResponseCompressionProvider>,\n                TestSink.EnableWithTypeName<ResponseCompressionProvider>);\n            var loggerFactory = new TestLoggerFactory(sink, enabled: true);\n\n            var builder = new WebHostBuilder()\n                .ConfigureServices(services =>\n                {\n                    services.AddResponseCompression(configure ?? (_ => { }));\n                    services.AddSingleton<ILoggerFactory>(loggerFactory);\n                })\n                .Configure(app =>\n                {\n                    app.UseResponseCompression();\n                    app.Run(context =>\n                    {\n                        context.Response.Headers[HeaderNames.ContentMD5] = \"MD5\";\n                        context.Response.ContentType = responseType;\n                        Assert.Null(context.Features.Get<IHttpSendFileFeature>());\n                        addResponseAction?.Invoke(context.Response);\n                        return context.Response.WriteAsync(new string('a', uncompressedBodyLength));\n                    });\n                });\n\n            var server = new TestServer(builder);\n            var client = server.CreateClient();\n\n            var request = new HttpRequestMessage(HttpMethod.Get, \"\");\n            for (var i = 0; i < requestAcceptEncodings?.Length; i++)\n            {\n                request.Headers.AcceptEncoding.Add(System.Net.Http.Headers.StringWithQualityHeaderValue.Parse(requestAcceptEncodings[i]));\n            }\n\n            return (await client.SendAsync(request), sink.Writes.ToList());\n        }\n\n        private void CheckResponseCompressed(HttpResponseMessage response, int expectedBodyLength, string expectedEncoding)\n        {\n            var containsVaryAcceptEncoding = false;\n            foreach (var value in response.Headers.GetValues(HeaderNames.Vary))\n            {\n                if (value.Contains(HeaderNames.AcceptEncoding))\n                {\n                    containsVaryAcceptEncoding = true;\n                    break;\n                }\n            }\n            Assert.True(containsVaryAcceptEncoding);\n            Assert.False(response.Content.Headers.TryGetValues(HeaderNames.ContentMD5, out _));\n            Assert.Single(response.Content.Headers.ContentEncoding, expectedEncoding);\n            Assert.Equal(expectedBodyLength, response.Content.Headers.ContentLength);\n        }\n\n        private void CheckResponseNotCompressed(HttpResponseMessage response, int expectedBodyLength, bool sendVaryHeader)\n        {\n            if (sendVaryHeader)\n            {\n                var containsVaryAcceptEncoding = false;\n                foreach (var value in response.Headers.GetValues(HeaderNames.Vary))\n                {\n                    if (value.Contains(HeaderNames.AcceptEncoding))\n                    {\n                        containsVaryAcceptEncoding = true;\n                        break;\n                    }\n                }\n                Assert.True(containsVaryAcceptEncoding);\n            }\n            else\n            {\n                Assert.False(response.Headers.Contains(HeaderNames.Vary));\n            }\n            Assert.NotNull(response.Content.Headers.GetValues(HeaderNames.ContentMD5));\n            Assert.Empty(response.Content.Headers.ContentEncoding);\n            Assert.Equal(expectedBodyLength, response.Content.Headers.ContentLength);\n        }\n\n        private void AssertLog(WriteContext log, LogLevel level, string message)\n        {\n            Assert.Equal(level, log.LogLevel);\n            Assert.Equal(message, log.State.ToString());\n        }\n\n        private void AssertCompressedWithLog(List<WriteContext> logMessages, string provider)\n        {\n            Assert.Equal(3, logMessages.Count);\n            AssertLog(logMessages.First(), LogLevel.Trace, \"This request accepts compression.\");\n            AssertLog(logMessages.Skip(1).First(), LogLevel.Trace, \"Response compression is available for this Content-Type.\");\n            AssertLog(logMessages.Skip(2).First(), LogLevel.Debug, $\"The response will be compressed with '{provider}'.\");\n        }\n\n        private class FakeSendFileFeature : IHttpSendFileFeature\n        {\n            private readonly Stream _innerBody;\n\n            public FakeSendFileFeature(Stream innerBody)\n            {\n                _innerBody = innerBody;\n            }\n\n            public bool Invoked { get; set; }\n\n            public async Task SendFileAsync(string path, long offset, long? count, CancellationToken cancellation)\n            {\n                // This implementation should only be delegated to if compression is disabled.\n                Invoked = true;\n                using (var file = new FileStream(path, FileMode.Open))\n                {\n                    file.Seek(offset, SeekOrigin.Begin);\n                    if (count.HasValue)\n                    {\n                        throw new NotImplementedException(\"Not implemented for testing\");\n                    }\n                    await file.CopyToAsync(_innerBody, 81920, cancellation);\n                }\n            }\n        }\n\n        private readonly struct EncodingTestData\n        {\n            public EncodingTestData(string encodingName, int expectedBodyLength)\n            {\n                EncodingName = encodingName;\n                ExpectedBodyLength = expectedBodyLength;\n            }\n\n            public string EncodingName { get; }\n\n            public int ExpectedBodyLength { get; }\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.ResponseCompression.Tests/testfile1kb.txt",
    "content": "﻿aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/ConditionPatternParserTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite\n{\n    public class ConditionPatternParserTest\n    {\n        [Theory]\n        [InlineData(\">hey\", OperationType.Greater, \"hey\", ConditionType.StringComp)]\n        [InlineData(\"<hey\", OperationType.Less, \"hey\", ConditionType.StringComp)]\n        [InlineData(\">=hey\", OperationType.GreaterEqual, \"hey\", ConditionType.StringComp)]\n        [InlineData(\"<=hey\", OperationType.LessEqual, \"hey\", ConditionType.StringComp)]\n        [InlineData(\"=hey\", OperationType.Equal, \"hey\", ConditionType.StringComp)]\n        public void ConditionPatternParser_CheckStringComp(string condition, OperationType operation, string variable, ConditionType conditionType)\n        {\n            var results = new ConditionPatternParser().ParseActionCondition(condition);\n\n            var expected = new ParsedModRewriteInput { OperationType = operation, ConditionType = conditionType, Operand = variable, Invert = false };\n            Assert.True(CompareConditions(expected, results));\n        }\n\n        [Fact]\n        public void ConditionPatternParser_CheckRegexEqual()\n        {\n            var condition = @\"(.*)\";\n            var results = new ConditionPatternParser().ParseActionCondition(condition);\n\n            var expected = new ParsedModRewriteInput { ConditionType = ConditionType.Regex, Operand = \"(.*)\", Invert = false };\n            Assert.True(CompareConditions(expected, results));\n        }\n\n        [Theory]\n        [InlineData(\"-d\", OperationType.Directory, ConditionType.PropertyTest)]\n        [InlineData(\"-f\", OperationType.RegularFile, ConditionType.PropertyTest)]\n        [InlineData(\"-F\", OperationType.ExistingFile, ConditionType.PropertyTest)]\n        [InlineData(\"-h\", OperationType.SymbolicLink, ConditionType.PropertyTest)]\n        [InlineData(\"-L\", OperationType.SymbolicLink, ConditionType.PropertyTest)]\n        [InlineData(\"-l\", OperationType.SymbolicLink, ConditionType.PropertyTest)]\n        [InlineData(\"-s\", OperationType.Size, ConditionType.PropertyTest)]\n        [InlineData(\"-U\", OperationType.ExistingUrl, ConditionType.PropertyTest)]\n        [InlineData(\"-x\", OperationType.Executable, ConditionType.PropertyTest)]\n        public void ConditionPatternParser_CheckFileOperations(string condition, OperationType operation, ConditionType cond)\n        {\n            var results = new ConditionPatternParser().ParseActionCondition(condition);\n\n            var expected = new ParsedModRewriteInput { ConditionType = cond, OperationType = operation, Invert = false };\n            Assert.True(CompareConditions(expected, results));\n        }\n\n        [Theory]\n        [InlineData(\"!-d\", OperationType.Directory, ConditionType.PropertyTest)]\n        [InlineData(\"!-f\", OperationType.RegularFile, ConditionType.PropertyTest)]\n        [InlineData(\"!-F\", OperationType.ExistingFile, ConditionType.PropertyTest)]\n        [InlineData(\"!-h\", OperationType.SymbolicLink, ConditionType.PropertyTest)]\n        [InlineData(\"!-L\", OperationType.SymbolicLink, ConditionType.PropertyTest)]\n        [InlineData(\"!-l\", OperationType.SymbolicLink, ConditionType.PropertyTest)]\n        [InlineData(\"!-s\", OperationType.Size, ConditionType.PropertyTest)]\n        [InlineData(\"!-U\", OperationType.ExistingUrl, ConditionType.PropertyTest)]\n        [InlineData(\"!-x\", OperationType.Executable, ConditionType.PropertyTest)]\n        public void ConditionPatternParser_CheckFileOperationsInverted(string condition, OperationType operation, ConditionType cond)\n        {\n            var results = new ConditionPatternParser().ParseActionCondition(condition);\n\n            var expected = new ParsedModRewriteInput { ConditionType = cond, OperationType = operation, Invert = true };\n            Assert.True(CompareConditions(expected, results));\n        }\n\n        [Theory]\n        [InlineData(\"-gt1\", OperationType.Greater, \"1\", ConditionType.IntComp)]\n        [InlineData(\"-lt1\", OperationType.Less, \"1\", ConditionType.IntComp)]\n        [InlineData(\"-ge1\", OperationType.GreaterEqual, \"1\", ConditionType.IntComp)]\n        [InlineData(\"-le1\", OperationType.LessEqual, \"1\", ConditionType.IntComp)]\n        [InlineData(\"-eq1\", OperationType.Equal, \"1\", ConditionType.IntComp)]\n        [InlineData(\"-ne1\", OperationType.NotEqual, \"1\", ConditionType.IntComp)]\n        public void ConditionPatternParser_CheckIntComp(string condition, OperationType operation, string variable, ConditionType cond)\n        {\n            var results = new ConditionPatternParser().ParseActionCondition(condition);\n\n            var expected = new ParsedModRewriteInput { ConditionType = cond, OperationType = operation, Invert = false, Operand = variable };\n            Assert.True(CompareConditions(expected, results));\n        }\n\n        [Theory]\n        [InlineData(\"\", \"Unrecognized parameter type: '', terminated at string index: '0'\")]\n        [InlineData(\"!\", \"Unrecognized parameter type: '!', terminated at string index: '1'\")]\n        [InlineData(\">\", \"Unrecognized parameter type: '>', terminated at string index: '1'\")]\n        [InlineData(\"<\", \"Unrecognized parameter type: '<', terminated at string index: '1'\")]\n        [InlineData(\"=\", \"Unrecognized parameter type: '=', terminated at string index: '1'\")]\n        [InlineData(\">=\", \"Unrecognized parameter type: '>=', terminated at string index: '2'\")]\n        [InlineData(\"<=\", \"Unrecognized parameter type: '<=', terminated at string index: '2'\")]\n        [InlineData(\"-a\", \"Unrecognized parameter type: '-a', terminated at string index: '1'\")]\n        [InlineData(\"-gewow\", \"Unrecognized parameter type: '-gewow', terminated at string index: '3'\")]\n        public void ConditionPatternParser_AssertBadInputThrowsFormatException(string input, string expected)\n        {\n            var ex = Assert.Throws<FormatException>(() => new ConditionPatternParser().ParseActionCondition(input));\n            Assert.Equal(expected, ex.Message);\n        }\n\n        private bool CompareConditions(ParsedModRewriteInput i1, ParsedModRewriteInput i2)\n        {\n            if (i1.OperationType != i2.OperationType ||\n                i1.ConditionType != i2.ConditionType ||\n                i1.Operand != i2.Operand ||\n                i1.Invert != i2.Invert)\n            {\n                return false;\n            }\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/CookieActionFactoryTest.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Test\n{\n    public class CookieActionFactoryTest\n    {\n        [Fact]\n        public void Creates_OneCookie()\n        {\n            var cookie = new CookieActionFactory().Create(\"NAME:VALUE:DOMAIN:1440:path:secure:httponly\");\n\n            Assert.Equal(\"NAME\", cookie.Name);\n            Assert.Equal(\"VALUE\", cookie.Value);\n            Assert.Equal(\"DOMAIN\", cookie.Domain);\n            Assert.Equal(TimeSpan.FromMinutes(1440), cookie.Lifetime);\n            Assert.Equal(\"path\", cookie.Path);\n            Assert.True(cookie.Secure);\n            Assert.True(cookie.HttpOnly);\n        }\n\n        [Fact]\n        public void Creates_OneCookie_AltSeparator()\n        {\n            var action = new CookieActionFactory().Create(\";NAME;VALUE:WithColon;DOMAIN;1440;path;secure;httponly\");\n\n            Assert.Equal(\"NAME\", action.Name);\n            Assert.Equal(\"VALUE:WithColon\", action.Value);\n            Assert.Equal(\"DOMAIN\", action.Domain);\n            Assert.Equal(TimeSpan.FromMinutes(1440), action.Lifetime);\n            Assert.Equal(\"path\", action.Path);\n            Assert.True(action.Secure);\n            Assert.True(action.HttpOnly);\n        }\n\n        [Fact]\n        public void Creates_HttpOnly()\n        {\n            var action = new CookieActionFactory().Create(\";NAME;VALUE;DOMAIN;;;;httponly\");\n\n            Assert.Equal(\"NAME\", action.Name);\n            Assert.Equal(\"VALUE\", action.Value);\n            Assert.Equal(\"DOMAIN\", action.Domain);\n            Assert.Equal(0, action.Lifetime.TotalSeconds);\n            Assert.Equal(string.Empty, action.Path);\n            Assert.False(action.Secure);\n            Assert.True(action.HttpOnly);\n        }\n\n        [Theory]\n        [InlineData(\"NAME::\", \"\", null)]\n        [InlineData(\"NAME::domain\", \"\", \"domain\")]\n        [InlineData(\"NAME:VALUE:;\", \"VALUE\", null)] // special case with dangling ';'\n        [InlineData(\"NAME:value:\", \"value\", null)]\n        [InlineData(\" NAME :  v  :  \", \"v\", null)] // trims values\n        public void TrimsValues(string flagValue, string value, string domain)\n        {\n            var factory = new CookieActionFactory();\n            var action = factory.Create(flagValue);\n            Assert.Equal(\"NAME\", action.Name);\n            Assert.NotNull(action.Value);\n            Assert.Equal(value, action.Value);\n            Assert.Equal(domain, action.Domain);\n        }\n\n        [Theory]\n        [InlineData(\"NAME\")] // missing value and domain\n        [InlineData(\"NAME:   \")] // missing  domain\n        [InlineData(\"NAME:VALUE\")] // missing domain\n        [InlineData(\";NAME;VAL:UE\")] // missing domain\n        public void ThrowsForInvalidFormat(string flagValue)\n        {\n            var factory = new CookieActionFactory();\n            var ex = Assert.Throws<FormatException>(() => factory.Create(flagValue));\n            Assert.Equal(Resources.FormatError_InvalidChangeCookieFlag(flagValue), ex.Message);\n        }\n\n        [Theory]\n        [InlineData(\"bad_number\")]\n        [InlineData(\"-1\")]\n        [InlineData(\"0.9\")]\n        public void ThrowsForInvalidIntFormat(string badInt)\n        {\n            var factory = new CookieActionFactory();\n            var ex = Assert.Throws<FormatException>(() => factory.Create(\"NAME:VALUE:DOMAIN:\" + badInt));\n            Assert.Equal(Resources.FormatError_CouldNotParseInteger(badInt), ex.Message);\n        }\n    }\n}"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/FlagParserTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite\n{\n    public class FlagParserTest\n    {\n        [Fact]\n        public void FlagParser_CheckSingleTerm()\n        {\n            var results = new FlagParser().Parse(\"[NC]\");\n            var dict = new Dictionary<FlagType, string>();\n            dict.Add(FlagType.NoCase, string.Empty);\n            var expected = new Flags(dict);\n\n            Assert.True(DictionaryContentsEqual(expected.FlagDictionary, results.FlagDictionary));\n        }\n\n        [Fact]\n        public void FlagParser_CheckManyTerms()\n        {\n            var results = new FlagParser().Parse(\"[NC,F,L]\");\n            var dict = new Dictionary<FlagType, string>();\n            dict.Add(FlagType.NoCase, string.Empty);\n            dict.Add(FlagType.Forbidden, string.Empty);\n            dict.Add(FlagType.Last, string.Empty);\n            var expected = new Flags(dict);\n\n            Assert.True(DictionaryContentsEqual(expected.FlagDictionary, results.FlagDictionary));\n        }\n\n        [Fact]\n        public void FlagParser_CheckManyTermsWithEquals()\n        {\n            var results = new FlagParser().Parse(\"[NC,F,R=301]\");\n            var dict = new Dictionary<FlagType, string>();\n            dict.Add(FlagType.NoCase, string.Empty);\n            dict.Add(FlagType.Forbidden, string.Empty);\n            dict.Add(FlagType.Redirect, \"301\");\n            var expected = new Flags(dict);\n\n            Assert.True(DictionaryContentsEqual(expected.FlagDictionary, results.FlagDictionary));\n        }\n\n        [Theory]\n        [InlineData(\"]\", \"Flags should start and end with square brackets: [flags]\")]\n        [InlineData(\"[\", \"Flags should start and end with square brackets: [flags]\")]\n        [InlineData(\"[R, L]\", \"Unrecognized flag: ' L'\")] // cannot have spaces after ,\n        [InlineData(\"[RL]\", \"Unrecognized flag: 'RL'\")]\n        public void FlagParser_AssertFormatErrorWhenFlagsArePoorlyConstructed(string input, string expected)\n        {\n            var ex = Assert.Throws<FormatException>(() => new FlagParser().Parse(input));\n            Assert.Equal(expected, ex.Message);\n        }\n\n        [Fact]\n        public void FlagParser_AssertArgumentExceptionWhenFlagsAreNullOrEmpty()\n        {\n            Assert.Throws<ArgumentException>(() => new FlagParser().Parse(null));\n            Assert.Throws<ArgumentException>(() => new FlagParser().Parse(string.Empty));\n        }\n\n        [Theory]\n        [InlineData(\"[CO=VAR:VAL]\", \"VAR:VAL\")]\n        [InlineData(\"[CO=!VAR]\", \"!VAR\")]\n        [InlineData(\"[CO=;NAME:VALUE;ABC:123]\", \";NAME:VALUE;ABC:123\")]\n        public void Flag_ParserHandlesComplexFlags(string flagString, string expected)\n        {\n            var results = new FlagParser().Parse(flagString);\n            string value;\n            Assert.True(results.GetValue(FlagType.Cookie, out value));\n            Assert.Equal(expected, value);\n        }\n\n        public bool DictionaryContentsEqual<TKey, TValue>(IDictionary<TKey, TValue> dictionary, IDictionary<TKey, TValue> other)\n        {\n            return (other ?? new Dictionary<TKey, TValue>())\n                .OrderBy(kvp => kvp.Key)\n                .SequenceEqual((dictionary ?? new Dictionary<TKey, TValue>())\n                .OrderBy(kvp => kvp.Key));\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/FormatExceptionTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite\n{\n    public class FormatExceptionTests\n    {\n        [Theory]\n        [InlineData(@\"RewriteCond 1 2\\\", @\"Invalid escaper character in string: RewriteCond 1 2\\\")]\n        [InlineData(\"BadExpression 1 2 3 4\", \"Could not parse the mod_rewrite file. Message: 'Too many tokens on line'.  Line number '1'.\")]\n        [InlineData(\"RewriteCond % 2\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %{ 2\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %{asdf} 2\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %z 2\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond $ 2\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond $z 2\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 !\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 >\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 >=\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 <\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 <=\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 =\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 -\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 -a\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        [InlineData(\"RewriteCond %1 -getemp\", \"Could not parse the mod_rewrite file.  Line number '1'.\")]\n        public void ThrowFormatExceptionWithCorrectMessage(string input, string expected)\n        {\n            // Arrange, Act, Assert\n            var ex = Assert.Throws<FormatException>(() => new FileParser().Parse(new StringReader(input)));\n            Assert.Equal(expected, ex.Message);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/ModRewriteMiddlewareTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing System.Net;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.TestHost;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite\n{\n    public class ModRewriteMiddlewareTest\n    {\n        [Fact]\n        public async Task Invoke_RewritePathWhenMatching()\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(\"RewriteRule /hey/(.*) /$1 \"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(context.Request.Path));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"/hey/hello\");\n\n            Assert.Equal(\"/hello\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_RewritePathTerminatesOnFirstSuccessOfRule()\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(\"RewriteRule /hey/(.*) /$1 [L]\"))\n                            .AddApacheModRewrite(new StringReader(\"RewriteRule /hello /what\"));\n            var builder = new WebHostBuilder()\n                 .Configure(app =>\n                 {\n                     app.UseRewriter(options);\n                     app.Run(context => context.Response.WriteAsync(context.Request.Path));\n                 });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"/hey/hello\");\n\n            Assert.Equal(\"/hello\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_RewritePathDoesNotTerminateOnFirstSuccessOfRule()\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(\"RewriteRule /hey/(.*) /$1\"))\n                                       .AddApacheModRewrite(new StringReader(\"RewriteRule /hello /what\"));\n            var builder = new WebHostBuilder()\n                 .Configure(app =>\n                 {\n                     app.UseRewriter(options);\n                     app.Run(context => context.Response.WriteAsync(context.Request.Path));\n                 });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"/hey/hello\");\n\n            Assert.Equal(\"/what\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_ShouldIgnoreComments()\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(\"#RewriteRule ^/hey/(.*) /$1 \"));\n            var builder = new WebHostBuilder()\n                 .Configure(app =>\n                 {\n                     app.UseRewriter(options);\n                     app.Run(context => context.Response.WriteAsync(context.Request.Path));\n                 });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"/hey/hello\");\n\n            Assert.Equal(\"/hey/hello\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_ShouldRewriteHomepage()\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@\"RewriteRule ^/$ /homepage.html\"));\n            var builder = new WebHostBuilder()\n                 .Configure(app =>\n                 {\n                     app.UseRewriter(options);\n                     app.Run(context => context.Response.WriteAsync(context.Request.Path));\n                 });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"http://www.foo.org/\");\n\n            Assert.Equal(\"/homepage.html\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_ShouldIgnorePorts()\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@\"RewriteRule ^/$ /homepage.html\"));\n            var builder = new WebHostBuilder()\n              .Configure(app =>\n              {\n                  app.UseRewriter(options);\n                  app.Run(context => context.Response.WriteAsync(context.Request.Path));\n              });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"http://www.foo.org:42/\");\n\n            Assert.Equal(\"/homepage.html\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_HandleNegatedRewriteRules()\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@\"RewriteRule !^/$ /homepage.html\"));\n            var builder = new WebHostBuilder()\n              .Configure(app =>\n              {\n                  app.UseRewriter(options);\n                  app.Run(context => context.Response.WriteAsync(context.Request.Path));\n              });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"http://www.foo.org/\");\n\n            Assert.Equal(\"/\", response);\n        }\n\n        [Theory]\n        [InlineData(\"http://www.foo.org/homepage.aspx\", @\"RewriteRule (.*)\\.aspx $1.php\", \"/homepage.php\")]\n        [InlineData(\"http://www.foo.org/pages/homepage.aspx\", @\"RewriteRule (.*)/(.*)\\.aspx $2.php\", \"/homepage.php\")]\n        public async Task Invoke_BackReferencesShouldBeApplied(string url, string rule, string expected)\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(rule));\n            var builder = new WebHostBuilder()\n             .Configure(app =>\n                 {\n                     app.UseRewriter(options);\n                     app.Run(context => context.Response.WriteAsync(context.Request.Path));\n                 });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(url);\n\n            Assert.Equal(expected, response);\n        }\n\n        [Theory]\n        [InlineData(\"http://www.foo.org/homepage.aspx\", @\"RewriteRule (.*)\\.aspx $1.php\", \"/homepage.php\")]\n        [InlineData(\"http://www.foo.org/homepage.ASPX\", @\"RewriteRule (.*)\\.aspx $1.php\", \"/homepage.ASPX\")]\n        [InlineData(\"http://www.foo.org/homepage.aspx\", @\"RewriteRule (.*)\\.aspx $1.php [NC]\", \"/homepage.php\")]\n        [InlineData(\"http://www.foo.org/homepage.ASPX\", @\"RewriteRule (.*)\\.aspx $1.php [NC]\", \"/homepage.php\")]\n        [InlineData(\"http://www.foo.org/homepage.aspx\", @\"RewriteRule (.*)\\.aspx $1.php [nocase]\", \"/homepage.php\")]\n        [InlineData(\"http://www.foo.org/homepage.ASPX\", @\"RewriteRule (.*)\\.aspx $1.php [nocase]\", \"/homepage.php\")]\n        public async Task Invoke_ShouldHandleFlagNoCase(string url, string rule, string expected)\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(rule));\n            var builder = new WebHostBuilder()\n             .Configure(app =>\n             {\n                 app.UseRewriter(options);\n                 app.Run(context => context.Response.WriteAsync(context.Request.Path));\n             });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(url);\n\n            Assert.Equal(expected, response);\n        }\n\n        [Fact]\n        public async Task Invoke_CheckFullUrlWithOnlyPath()\n        {\n            var options = new RewriteOptions()\n                .AddApacheModRewrite(new StringReader(@\"RewriteRule (.+) http://www.example.com$1/\"));\n            var builder = new WebHostBuilder()\n              .Configure(app =>\n              {\n                  app.UseRewriter(options);\n                  app.Run(context => context.Response.WriteAsync(context.Request.Path));\n              });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"http://www.foo.org/blog/2016-jun\");\n\n            Assert.Equal(@\"/blog/2016-jun/\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_CheckFullUrlWithUFlag()\n        {\n            var options = new RewriteOptions()\n                .AddApacheModRewrite(new StringReader(@\"RewriteRule (.+) http://www.example.com$1/\"));\n            var builder = new WebHostBuilder()\n              .Configure(app =>\n              {\n                  app.UseRewriter(options);\n                  app.Run(context => context.Response.WriteAsync(context.Request.Scheme + \"://\" + context.Request.Host.Host + context.Request.Path + context.Request.QueryString));\n              });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"http://www.foo.org/blog/2016-jun\");\n\n            Assert.Equal(@\"http://www.example.com/blog/2016-jun/\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_CheckModFileConditions()\n        {\n            var options = new RewriteOptions()\n                .AddApacheModRewrite(new StringReader(@\"RewriteRule (.+) http://www.example.com$1/\"));\n            var builder = new WebHostBuilder()\n              .Configure(app =>\n              {\n                  app.UseRewriter(options);\n                  app.Run(context => context.Response.WriteAsync(context.Request.Scheme + \"://\" + context.Request.Host.Host + context.Request.Path + context.Request.QueryString));\n              });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"http://www.foo.org/blog/2016-jun\");\n\n            Assert.Equal(@\"http://www.example.com/blog/2016-jun/\", response);\n        }\n\n        [Theory]\n        [InlineData(\"http://www.example.com/foo/\")]\n        public async Task Invoke_EnsureHttps(string input)\n        {\n            var options = new RewriteOptions()\n                .AddApacheModRewrite(new StringReader(\"RewriteCond %{REQUEST_URI} /foo/  \\nRewriteCond %{HTTPS} !on   \\nRewriteRule ^(.*)$ https://www.example.com$1 [R=301,L]\"));\n            var builder = new WebHostBuilder()\n              .Configure(app =>\n              {\n                  app.UseRewriter(options);\n                  app.Run(context => context.Response.WriteAsync(context.Request.Scheme + \"://\" + context.Request.Host.Host + context.Request.Path + context.Request.QueryString));\n              });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(input);\n\n            Assert.Equal(response.StatusCode, (HttpStatusCode)301);\n            Assert.Equal(@\"https://www.example.com/foo/\", response.Headers.Location.AbsoluteUri);\n        }\n\n        [Theory]\n        [InlineData(\"http://www.example.com/\")]\n        public async Task Invoke_CaptureEmptyStringInRegexAssertRedirectLocationHasForwardSlash(string input)\n        {\n            var options = new RewriteOptions()\n                .AddApacheModRewrite(new StringReader(\"RewriteRule ^(.*)$ $1 [R=301,L]\"));\n            var builder = new WebHostBuilder()\n              .Configure(app =>\n              {\n                  app.UseRewriter(options);\n                  app.Run(context => context.Response.WriteAsync(context.Request.Scheme + \"://\" + context.Request.Host.Host + context.Request.Path + context.Request.QueryString));\n              });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(input);\n\n            Assert.Equal(HttpStatusCode.MovedPermanently, response.StatusCode);\n            Assert.Equal(\"/\", response.Headers.Location.OriginalString);\n        }\n\n        [Theory]\n        [InlineData(\"http://www.example.com/\")]\n        public async Task Invoke_CaptureEmptyStringInRegexAssertRewriteHasForwardSlash(string input)\n        {\n            var options = new RewriteOptions()\n                .AddApacheModRewrite(new StringReader(\"RewriteRule ^(.*)$ $1 [L]\"));\n            var builder = new WebHostBuilder()\n              .Configure(app =>\n              {\n                  app.UseRewriter(options);\n                  app.Run(context => context.Response.WriteAsync(context.Request.Path + context.Request.QueryString));\n              });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(input);\n            Assert.Equal(\"/\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_CaptureEmptyStringInRegexAssertLocationHeaderContainsPathBase()\n        {\n            var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@\"RewriteRule ^(.*)$ $1 [R=301,L]\"));\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n                app.Run(context => context.Response.WriteAsync(\n                        context.Request.Path +\n                        context.Request.QueryString));\n            });\n            var server = new TestServer(builder) { BaseAddress = new Uri(\"http://localhost:5000/foo\") };\n\n            var response = await server.CreateClient().GetAsync(\"\");\n\n            Assert.Equal(\"/foo\", response.Headers.Location.OriginalString);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/RewriteTokenizerTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite\n{\n    public class RewriteTokenizerTest\n    {\n        [Fact]\n        public void Tokenize_RewriteCondtion()\n        {\n            var testString = \"RewriteCond %{HTTPS} !-f\";\n            var tokens = new Tokenizer().Tokenize(testString);\n\n            var expected = new List<string>();\n            expected.Add(\"RewriteCond\");\n            expected.Add(\"%{HTTPS}\");\n            expected.Add(\"!-f\");\n            Assert.Equal(expected, tokens);\n        }\n\n        [Fact]\n        public void Tokenize_CheckEscapedSpaceIgnored()\n        {\n            var testString = @\"RewriteCond %{HTTPS}\\ what !-f\";\n            var tokens = new Tokenizer().Tokenize(testString);\n\n            var expected = new List<string>();\n            expected.Add(\"RewriteCond\");\n            expected.Add(@\"%{HTTPS} what\");\n            expected.Add(\"!-f\");\n            Assert.Equal(expected, tokens);\n        }\n\n        [Fact]\n        public void Tokenize_CheckWhiteSpaceDirectlyFollowedByEscapeCharacter_CorrectSplit()\n        {\n            var testString = @\"RewriteCond %{HTTPS} \\ what !-f\";\n            var tokens = new Tokenizer().Tokenize(testString);\n\n            var expected = new List<string>();\n            expected.Add(@\"RewriteCond\");\n            expected.Add(@\"%{HTTPS}\");\n            expected.Add(@\" what\");\n            expected.Add(@\"!-f\");\n            Assert.Equal(expected, tokens);\n        }\n\n        [Fact]\n        public void Tokenize_CheckWhiteSpaceAtEndOfString_CorrectSplit()\n        {\n            var testString = @\"RewriteCond %{HTTPS} \\ what !-f    \";\n            var tokens = new Tokenizer().Tokenize(testString);\n\n            var expected = new List<string>();\n            expected.Add(@\"RewriteCond\");\n            expected.Add(@\"%{HTTPS}\");\n            expected.Add(@\" what\");\n            expected.Add(@\"!-f\");\n            Assert.Equal(expected, tokens);\n        }\n\n        [Fact]\n        public void Tokenize_CheckQuotesAreProperlyRemovedFromString()\n        {\n            var testString = \"RewriteCond \\\"%{HTTPS}\\\" \\\"\\\\ what\\\" \\\"!-f\\\"    \";\n            var tokens = new Tokenizer().Tokenize(testString);\n\n            var expected = new List<string>();\n            expected.Add(@\"RewriteCond\");\n            expected.Add(@\"%{HTTPS}\");\n            expected.Add(@\" what\");\n            expected.Add(@\"!-f\");\n            Assert.Equal(expected, tokens);\n        }\n\n        [Fact]\n        public void Tokenize_AssertFormatExceptionWhenEscapeCharacterIsAtEndOfString()\n        {\n            var ex = Assert.Throws<FormatException>(() => new Tokenizer().Tokenize(\"\\\\\"));\n            Assert.Equal(@\"Invalid escaper character in string: \\\", ex.Message);\n        }\n\n        [Fact]\n        public void Tokenize_AssertFormatExceptionWhenUnevenNumberOfQuotes()\n        {\n            var ex = Assert.Throws<FormatException>(() => new Tokenizer().Tokenize(\"\\\"\"));\n            Assert.Equal(\"Mismatched number of quotes: \\\"\", ex.Message);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/RuleBuilderTest.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests\n{\n    public class RuleBuilderTest\n    {\n        [Fact]\n        // see https://httpd.apache.org/docs/2.4/rewrite/advanced.html#setenvvars\n        public void AddAction_Throws_ChangeEnvNotSupported()\n        {\n            var builder = new RuleBuilder();\n            var flags = new Flags();\n            flags.SetFlag(FlagType.Env, \"rewritten:1\");\n\n            var ex = Assert.Throws<NotSupportedException>(() => builder.AddAction(null, flags));\n            Assert.Equal(Resources.Error_ChangeEnvironmentNotSupported, ex.Message);\n        }\n\n        [Fact]\n        public void AddAction_DefaultRedirectStatusCode()\n        {\n            var builder = new RuleBuilder();\n            var flags = new Flags();\n            var pattern = new Pattern(new List<PatternSegment>());\n            flags.SetFlag(FlagType.Redirect, string.Empty);\n\n            builder.AddAction(pattern, flags);\n            var redirectAction = (RedirectAction)builder._actions[0];\n\n            Assert.Equal(StatusCodes.Status302Found, redirectAction.StatusCode);\n        }\n    }\n}"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/RuleRegexParserTest.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite\n{\n    public class RuleRegexParserTest\n    {\n        [Fact]\n        public void RuleRegexParser_ShouldThrowOnNull()\n        {\n            Assert.Throws<FormatException>(() => new RuleRegexParser().ParseRuleRegex(null));\n        }\n\n        [Fact]\n        public void RuleRegexParser_ShouldThrowOnEmpty()\n        {\n            Assert.Throws<FormatException>(() => new RuleRegexParser().ParseRuleRegex(string.Empty));\n        }\n\n        [Fact]\n        public void RuleRegexParser_RegularRegexExpression()\n        {\n            var results = new RuleRegexParser().ParseRuleRegex(\"(.*)\");\n            Assert.False(results.Invert);\n            Assert.Equal(\"(.*)\", results.Operand);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/TestStringParserTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite\n{\n    public class TestStringParserTests\n    {\n        [Fact]\n        public void ConditionParser_SingleServerVariable()\n        {\n            var serverVar = \"%{HTTPS}\";\n\n            var result = new TestStringParser().Parse(serverVar);\n\n            var list = new List<PatternSegment>();\n            list.Add(new IsHttpsModSegment());\n            var expected = new Pattern(list);\n            AssertPatternsEqual(expected, result);\n        }\n\n        [Fact]\n        public void ConditionParser_MultipleServerVariables()\n        {\n            var serverVar = \"%{HTTPS}%{REQUEST_URI}\";\n            var result = new TestStringParser().Parse(serverVar);\n\n            var list = new List<PatternSegment>();\n            list.Add(new IsHttpsModSegment());\n            list.Add(new UrlSegment());\n            var expected = new Pattern(list);\n            AssertPatternsEqual(expected, result);\n        }\n\n        [Fact]\n        public void ConditionParser_ParseLiteral()\n        {\n            var serverVar = \"Hello!\";\n            var result = new TestStringParser().Parse(serverVar);\n\n            var list = new List<PatternSegment>();\n            list.Add(new LiteralSegment(serverVar));\n            var expected = new Pattern(list);\n            AssertPatternsEqual(expected, result);\n        }\n\n        [Fact]\n        public void ConditionParser_ParseConditionParameters()\n        {\n            var serverVar = \"%1\";\n            var result = new TestStringParser().Parse(serverVar);\n\n            var list = new List<PatternSegment>();\n            list.Add(new ConditionMatchSegment(1));\n            var expected = new Pattern(list);\n            AssertPatternsEqual(expected, result);\n        }\n\n        [Fact]\n        public void ConditionParser_ParseMultipleConditionParameters()\n        {\n            var serverVar = \"%1%2\";\n            var result = new TestStringParser().Parse(serverVar);\n\n            var list = new List<PatternSegment>();\n            list.Add(new ConditionMatchSegment(1));\n            list.Add(new ConditionMatchSegment(2));\n            var expected = new Pattern(list);\n            AssertPatternsEqual(expected, result);\n        }\n\n        [Fact]\n        public void ConditionParser_ParseRuleVariable()\n        {\n            var serverVar = \"$1\";\n            var result = new TestStringParser().Parse(serverVar);\n\n            var list = new List<PatternSegment>();\n            list.Add(new RuleMatchSegment(1));\n            var expected = new Pattern(list);\n            AssertPatternsEqual(expected, result);\n        }\n        [Fact]\n        public void ConditionParser_ParseMultipleRuleVariables()\n        {\n            var serverVar = \"$1$2\";\n            var result = new TestStringParser().Parse(serverVar);\n\n            var list = new List<PatternSegment>();\n            list.Add(new RuleMatchSegment(1));\n            list.Add(new RuleMatchSegment(2));\n            var expected = new Pattern(list);\n            AssertPatternsEqual(expected, result);\n        }\n\n        [Fact]\n        public void ConditionParser_ParserComplexRequest()\n        {\n            var serverVar = \"%{HTTPS}/$1\";\n            var result = new TestStringParser().Parse(serverVar);\n\n            var list = new List<PatternSegment>();\n            list.Add(new IsHttpsModSegment());\n            list.Add(new LiteralSegment(\"/\"));\n            list.Add(new RuleMatchSegment(1));\n            var expected = new Pattern(list);\n            AssertPatternsEqual(expected, result);\n        }\n\n        [Theory]\n        [InlineData(@\"%}\", \"Cannot parse '%}' to integer at string index: '1'\")] // no } at end\n        [InlineData(@\"%{\", \"Missing close brace for parameter at string index: '2'\")] // no closing }\n        [InlineData(@\"%a\", \"Cannot parse '%a' to integer at string index: '1'\")] // invalid character after %\n        [InlineData(@\"$a\", \"Cannot parse '$a' to integer at string index: '1'\")] // invalid character after $\n        [InlineData(@\"%{asdf\", \"Missing close brace for parameter at string index: '6'\")] // no closing } with characters\n        public void ConditionParser_InvalidInput(string testString, string expected)\n        {\n            var ex = Assert.Throws<FormatException>(() => new TestStringParser().Parse(testString));\n            Assert.Equal(expected, ex.Message);\n        }\n\n        private void AssertPatternsEqual(Pattern p1, Pattern p2)\n        {\n            Assert.Equal(p1.PatternSegments.Count, p2.PatternSegments.Count);\n\n            for (int i = 0; i < p1.PatternSegments.Count; i++)\n            {\n                var s1 = p1.PatternSegments[i];\n                var s2 = p2.PatternSegments[i];\n\n                Assert.Equal(s1.GetType(), s2.GetType());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/FileParserTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite\n{\n    public class FileParserTests\n    {\n        [Fact]\n        public void RuleParse_ParseTypicalRule()\n        {\n            // arrange\n            var xml = @\"<rewrite>\n                            <rules>\n                                <rule name=\"\"Rewrite to article.aspx\"\">\n                                    <match url = \"\"^article/([0-9]+)/([_0-9a-z-]+)\"\" />\n                                    <action type=\"\"Rewrite\"\" url =\"\"article.aspx?id={R:1}&amp;title={R:2}\"\" />\n                                </rule>\n                            </rules>\n                        </rewrite>\";\n\n            var expected = new List<IISUrlRewriteRule>();\n            expected.Add(CreateTestRule(new ConditionCollection(),\n                url: \"^article/([0-9]+)/([_0-9a-z-]+)\",\n                name: \"Rewrite to article.aspx\",\n                actionType: ActionType.Rewrite,\n                pattern: \"article.aspx?id={R:1}&amp;title={R:2}\"));\n\n            // act\n            var res = new UrlRewriteFileParser().Parse(new StringReader(xml));\n\n            // assert\n            AssertUrlRewriteRuleEquality(expected, res);\n        }\n\n        [Fact]\n        public void RuleParse_ParseSingleRuleWithSingleCondition()\n        {\n            // arrange\n            var xml = @\"<rewrite>\n                            <rules>\n                                <rule name=\"\"Rewrite to article.aspx\"\">\n                                    <match url = \"\"^article/([0-9]+)/([_0-9a-z-]+)\"\" />\n                                    <conditions>\n                                        <add input=\"\"{HTTPS}\"\" pattern=\"\"^OFF$\"\" />\n                                    </conditions>\n                                    <action type=\"\"Rewrite\"\" url =\"\"article.aspx?id={R:1}&amp;title={R:2}\"\" />\n                                </rule>\n                            </rules>\n                        </rewrite>\";\n\n            var condList = new ConditionCollection();\n            condList.Add(new Condition\n            {\n                Input = new InputParser().ParseInputString(\"{HTTPS}\"),\n                Match = new RegexMatch(new Regex(\"^OFF$\"), false)\n            });\n\n            var expected = new List<IISUrlRewriteRule>();\n            expected.Add(CreateTestRule(condList,\n                url: \"^article/([0-9]+)/([_0-9a-z-]+)\",\n                name: \"Rewrite to article.aspx\",\n                actionType: ActionType.Rewrite,\n                pattern: \"article.aspx?id={R:1}&amp;title={R:2}\"));\n\n            // act\n            var res = new UrlRewriteFileParser().Parse(new StringReader(xml));\n\n            // assert\n            AssertUrlRewriteRuleEquality(expected, res);\n        }\n\n        [Fact]\n        public void RuleParse_ParseMultipleRules()\n        {\n            // arrange\n            var xml = @\"<rewrite>\n                            <rules>\n                                <rule name=\"\"Rewrite to article.aspx\"\">\n                                    <match url = \"\"^article/([0-9]+)/([_0-9a-z-]+)\"\" />\n                                    <conditions>\n                                        <add input=\"\"{HTTPS}\"\" pattern=\"\"^OFF$\"\" />\n                                    </conditions>\n                                    <action type=\"\"Rewrite\"\" url =\"\"article.aspx?id={R:1}&amp;title={R:2}\"\" />\n                                </rule>\n                                <rule name=\"\"Rewrite to another article.aspx\"\">\n                                    <match url = \"\"^article/([0-9]+)/([_0-9a-z-]+)\"\" />\n                                    <conditions>\n                                        <add input=\"\"{HTTPS}\"\" pattern=\"\"^OFF$\"\" />\n                                    </conditions>\n                                    <action type=\"\"Rewrite\"\" url =\"\"article.aspx?id={R:1}&amp;title={R:2}\"\" />\n                                </rule>\n                            </rules>\n                        </rewrite>\";\n\n            var condList = new ConditionCollection();\n            condList.Add(new Condition\n            {\n                Input = new InputParser().ParseInputString(\"{HTTPS}\"),\n                Match = new RegexMatch(new Regex(\"^OFF$\"), false)\n            });\n\n            var expected = new List<IISUrlRewriteRule>();\n            expected.Add(CreateTestRule(condList,\n                url: \"^article/([0-9]+)/([_0-9a-z-]+)\",\n                name: \"Rewrite to article.aspx\",\n                actionType: ActionType.Rewrite,\n                pattern: \"article.aspx?id={R:1}&amp;title={R:2}\"));\n            expected.Add(CreateTestRule(condList,\n                url: \"^article/([0-9]+)/([_0-9a-z-]+)\",\n                name: \"Rewrite to another article.aspx\",\n                actionType: ActionType.Rewrite,\n                pattern: \"article.aspx?id={R:1}&amp;title={R:2}\"));\n\n            // act\n            var res = new UrlRewriteFileParser().Parse(new StringReader(xml));\n\n            // assert\n            AssertUrlRewriteRuleEquality(expected, res);\n        }\n\n        [Fact]\n        public void Should_parse_global_rules()\n        {\n            // arrange\n            var xml = @\"<rewrite>\n                            <globalRules>\n                                <rule name=\"\"httpsOnly\"\" patternSyntax=\"\"ECMAScript\"\" stopProcessing=\"\"true\"\">\n                                    <match url=\"\".*\"\" />\n                                    <conditions logicalGrouping=\"\"MatchAll\"\" trackAllCaptures=\"\"false\"\">\n                                        <add input=\"\"{HTTPS}\"\" pattern=\"\"off\"\" />\n                                    </conditions>\n                                    <action type=\"\"Redirect\"\" url=\"\"https://{HTTP_HOST}{REQUEST_URI}\"\" />\n                                </rule>\n                            </globalRules>\n                            <rules>\n                                <rule name=\"\"Rewrite to article.aspx\"\">\n                                    <match url = \"\"^article/([0-9]+)/([_0-9a-z-]+)\"\" />\n                                    <action type=\"\"Rewrite\"\" url =\"\"article.aspx?id={R:1}&amp;title={R:2}\"\" />\n                                </rule>\n                            </rules>\n                        </rewrite>\";\n\n            // act\n            var rules = new UrlRewriteFileParser().Parse(new StringReader(xml));\n\n            // assert\n            Assert.Equal(2, rules.Count);\n            Assert.True(rules[0].Global);\n            Assert.False(rules[1].Global);\n        }\n\n        // Creates a rule with appropriate default values of the url rewrite rule.\n        private IISUrlRewriteRule CreateTestRule(ConditionCollection conditions,\n            string name = \"\",\n            bool enabled = true,\n            PatternSyntax patternSyntax = PatternSyntax.ECMAScript,\n            bool stopProcessing = false,\n            string url = \"\",\n            bool ignoreCase = true,\n            bool negate = false,\n            ActionType actionType = ActionType.None,\n            string pattern = \"\",\n            bool appendQueryString = false,\n            bool rewrittenUrl = false,\n            bool global = false,\n            UriMatchPart uriMatchPart = UriMatchPart.Path,\n            RedirectType redirectType = RedirectType.Permanent\n            )\n        {\n            return new IISUrlRewriteRule(\n                name,\n                new RegexMatch(new Regex(\"^OFF$\"), negate),\n                conditions,\n                new RewriteAction(RuleResult.ContinueRules, new InputParser().ParseInputString(url, uriMatchPart), queryStringAppend: false),\n                global);\n        }\n\n        // TODO make rules comparable?\n        private void AssertUrlRewriteRuleEquality(IList<IISUrlRewriteRule> actual, IList<IISUrlRewriteRule> expected)\n        {\n            Assert.Equal(actual.Count, expected.Count);\n            for (var i = 0; i < actual.Count; i++)\n            {\n                var r1 = actual[i];\n                var r2 = expected[i];\n\n                Assert.Equal(r1.Name, r2.Name);\n\n                if (r1.Conditions == null)\n                {\n                    Assert.Equal(0, r2.Conditions.Count);\n                }\n                else if (r2.Conditions == null)\n                {\n                    Assert.Equal(0, r1.Conditions.Count);\n                }\n                else\n                {\n                    Assert.Equal(r1.Conditions.Count, r2.Conditions.Count);\n                    for (var j = 0; j < r1.Conditions.Count; j++)\n                    {\n                        var c1 = r1.Conditions[j];\n                        var c2 = r2.Conditions[j];\n                        Assert.Equal(c1.Input.PatternSegments.Count, c2.Input.PatternSegments.Count);\n                    }\n                }\n\n                Assert.Equal(r1.Action.GetType(), r2.Action.GetType());\n                Assert.Equal(r1.InitialMatch.GetType(), r2.InitialMatch.GetType());\n            }\n        }\n    }\n}"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/FormatExceptionHandlingTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.IO;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite\n{\n    public class FormatExceptionHandlingTests\n    {\n        [Theory]\n        [InlineData(\n@\"<rewrite>\n    <rules>\n        <rule name=\"\"Rewrite to article.aspx\"\">\n            <match url = \"\"(.*)\"\" />\n            <conditions>\n                <add input=\"\"{HTTPS}\"\" />\n            </conditions>\n            <action type=\"\"Rewrite\"\" url =\"\"foo\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n\t\t\t\"Match does not have an associated pattern attribute in condition\")]\n        [InlineData(\n@\"<rewrite>\n    <rules>\n        <rule name=\"\"Rewrite to article.aspx\"\">\n            <match url = \"\"(.*)\"\" />\n            <conditions>\n                <add input=\"\"{HTTPS}\"\" patternSyntax=\"\"ExactMatch\"\"/>\n            </conditions>\n            <action type=\"\"Rewrite\"\" url =\"\"foo\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n\t\t\t\"Match does not have an associated pattern attribute in condition\")]\n        [InlineData(\n@\"<rewrite>\n    <rules>\n        <rule name=\"\"Rewrite to article.aspx\"\">\n            <match url = \"\"(.*)\"\" />\n            <conditions>\n                <add input=\"\"{HTTPS\"\" pattern=\"\"^OFF$\"\" />\n            </conditions>\n            <action type=\"\"Rewrite\"\" url =\"\"foo\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n\t\t\t\"Missing close brace for parameter at string index: '6'\")]\n        [InlineData(\n@\"<rewrite>\n    <rules>\n        <rule name=\"\"Rewrite to article.aspx\"\">\n            <match url = \"\"(.*)\"\" />\n            <action type=\"\"Rewrite\"\" url =\"\"{\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n\t\t\t\"Missing close brace for parameter at string index: '1'\")]\n        public void ThrowFormatExceptionWithCorrectMessage(string input, string expected)\n        {\n            // Arrange, Act, Assert\n            var ex = Assert.Throws<FormatException>(() => new UrlRewriteFileParser().Parse(new StringReader(input)));\n            Assert.Equal(expected, ex.Message);\n        }\n    }\n}"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/InputParserTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Linq;\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Microsoft.Extensions.Logging.Abstractions;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite\n{\n    public class InputParserTests\n    {\n        [Fact]\n        public void InputParser_ParseLiteralString()\n        {\n            var testString = \"hello/hey/what\";\n            var result = new InputParser().ParseInputString(testString, UriMatchPart.Path);\n            Assert.Equal(1, result.PatternSegments.Count);\n        }\n\n        [Theory]\n        [InlineData(\"foo/bar/{R:1}/what\", 3)]\n        [InlineData(\"foo/{R:1}\", 2)]\n        [InlineData(\"foo/{R:1}/{C:2}\", 4)]\n        [InlineData(\"foo/{R:1}{C:2}\", 3)]\n        [InlineData(\"foo/\", 1)]\n        public void InputParser_ParseStringWithBackReference(string testString, int expected)\n        {\n            var result = new InputParser().ParseInputString(testString, UriMatchPart.Path);\n            Assert.Equal(expected, result.PatternSegments.Count);\n        }\n\n        // Test actual evaluation of the types, verifying the correct string comes from the evalation\n        [Theory]\n        [InlineData(\"hey/hello/what\", \"hey/hello/what\")]\n        [InlineData(\"hey/{R:1}/what\", \"hey/foo/what\")]\n        [InlineData(\"hey/{R:2}/what\", \"hey/bar/what\")]\n        [InlineData(\"hey/{R:3}/what\", \"hey/baz/what\")]\n        [InlineData(\"hey/{C:1}/what\", \"hey/foo/what\")]\n        [InlineData(\"hey/{C:2}/what\", \"hey/bar/what\")]\n        [InlineData(\"hey/{C:3}/what\", \"hey/baz/what\")]\n        [InlineData(\"hey/{R:1}/{C:1}\", \"hey/foo/foo\")]\n        public void EvaluateBackReferenceRule(string testString, string expected)\n        {\n            var middle = new InputParser().ParseInputString(testString, UriMatchPart.Path);\n            var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());\n            Assert.Equal(expected, result);\n        }\n\n        [Theory]\n        [InlineData(\"hey/{ToLower:HEY}\", \"hey/hey\")]\n        [InlineData(\"hey/{ToLower:{R:1}}\", \"hey/foo\")]\n        [InlineData(\"hey/{ToLower:{C:1}}\", \"hey/foo\")]\n        [InlineData(\"hey/{ToLower:{C:1}/what}\", \"hey/foo/what\")]\n        [InlineData(\"hey/ToLower:/what\", \"hey/ToLower:/what\")]\n        public void EvaluatToLowerRule(string testString, string expected)\n        {\n            var middle = new InputParser().ParseInputString(testString, UriMatchPart.Path);\n            var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());\n            Assert.Equal(expected, result);\n        }\n\n        [Theory]\n        [InlineData(\"hey/{UrlEncode:<hey>}\", \"hey/%3Chey%3E\")]\n        public void EvaluatUriEncodeRule(string testString, string expected)\n        {\n            var middle = new InputParser().ParseInputString(testString, UriMatchPart.Path);\n            var result = middle.Evaluate(CreateTestRewriteContext(), CreateTestRuleBackReferences(), CreateTestCondBackReferences());\n            Assert.Equal(expected, result);\n        }\n\n        [Theory]\n        [InlineData(\"{\")]\n        [InlineData(\"{:}\")]\n        [InlineData(\"{R:\")]\n        [InlineData(\"{R:1\")]\n        [InlineData(\"{R:A}\")]\n        [InlineData(\"{R:10}\")]\n        [InlineData(\"{R:-1}\")]\n        [InlineData(\"{foo:1\")]\n        [InlineData(\"{UrlEncode:{R:}}\")]\n        [InlineData(\"{UrlEncode:{R:1}\")]\n        [InlineData(\"{HTTPS\")]\n        public void FormatExceptionsOnBadSyntax(string testString)\n        {\n            Assert.Throws<FormatException>(() => new InputParser().ParseInputString(testString, UriMatchPart.Path));\n        }\n\n        [Fact]\n        public void Should_throw_FormatException_if_no_rewrite_maps_are_defined()\n        {\n            Assert.Throws<FormatException>(() => new InputParser(null).ParseInputString(\"{apiMap:{R:1}}\", UriMatchPart.Path));\n        }\n\n        [Fact]\n        public void Should_throw_FormatException_if_rewrite_map_not_found()\n        {\n            const string definedMapName = \"testMap\";\n            const string undefinedMapName = \"apiMap\";\n            var map = new IISRewriteMap(definedMapName);\n            var maps = new IISRewriteMapCollection { map };\n            Assert.Throws<FormatException>(() => new InputParser(maps).ParseInputString($\"{{{undefinedMapName}:{{R:1}}}}\", UriMatchPart.Path));\n        }\n\n        [Fact]\n        public void Should_parse_RewriteMapSegment_and_successfully_evaluate_result()\n        {\n            const string expectedMapName = \"apiMap\";\n            const string expectedKey = \"api.test.com\";\n            const string expectedValue = \"test.com/api\";\n            var map = new IISRewriteMap(expectedMapName);\n            map[expectedKey] = expectedValue;\n            var maps = new IISRewriteMapCollection { map };\n\n            var inputString = $\"{{{expectedMapName}:{{R:1}}}}\";\n            var pattern = new InputParser(maps).ParseInputString(inputString, UriMatchPart.Path);\n            Assert.Equal(1, pattern.PatternSegments.Count);\n\n            var segment = pattern.PatternSegments.Single();\n            var rewriteMapSegment = segment as RewriteMapSegment;\n            Assert.NotNull(rewriteMapSegment);\n\n            var result = rewriteMapSegment.Evaluate(CreateTestRewriteContext(), CreateRewriteMapRuleMatch(expectedKey).BackReferences, CreateRewriteMapConditionMatch(inputString).BackReferences);\n            Assert.Equal(expectedValue, result);\n        }\n\n        private RewriteContext CreateTestRewriteContext()\n        {\n            var context = new DefaultHttpContext();\n            return new RewriteContext { HttpContext = context, StaticFileProvider = null, Logger = NullLogger.Instance };\n        }\n\n        private BackReferenceCollection CreateTestRuleBackReferences()\n        {\n            var match = Regex.Match(\"foo/bar/baz\", \"(.*)/(.*)/(.*)\");\n            return new BackReferenceCollection(match.Groups);\n        }\n\n        private BackReferenceCollection CreateTestCondBackReferences()\n        {\n            var match = Regex.Match(\"foo/bar/baz\", \"(.*)/(.*)/(.*)\");\n            return new BackReferenceCollection(match.Groups);\n        }\n\n        private MatchResults CreateRewriteMapRuleMatch(string input)\n        {\n            var match = Regex.Match(input, \"([^/]*)/?(.*)\");\n            return new MatchResults { BackReferences = new BackReferenceCollection(match.Groups), Success = match.Success };\n        }\n\n        private MatchResults CreateRewriteMapConditionMatch(string input)\n        {\n            var match = Regex.Match(input, \"(.+)\");\n            return new MatchResults { BackReferences = new BackReferenceCollection(match.Groups), Success = match.Success };\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/InvalidUrlRewriteFormatExceptionHandlingTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite\n{\n    public class InvalidUrlRewriteFormatExceptionHandlingTests\n    {\n        [Theory]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Rewrite to article.aspx\"\">\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'Condition must have an associated match'. Line number '3': '10'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Rewrite to article.aspx\"\">\n            <match />\n            <action type=\"\"Rewrite\"\" url=\"\"foo\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'Match must have Url Attribute'. Line number '4': '14'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Rewrite to article.aspx\"\">\n            <match url = \"\"(.*)\"\" />\n            <conditions>\n                <add pattern=\"\"^OFF$\"\" />\n            </conditions>\n            <action type=\"\"Rewrite\"\" url =\"\"foo\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'Conditions must have an input attribute'. Line number '6': '18'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Rewrite to article.aspx\"\">\n            <match url = \"\"(.*)\"\" />\n            <action type=\"\"Rewrite\"\" url =\"\"\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'Url attribute cannot contain an empty string'. Line number '5': '14'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\" />\n            <action type=\"\"Redirect\"\" redirectType=\"\"foo\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The redirectType parameter 'foo' was not recognized'. Line number '5': '14'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\" />\n            <action type=\"\"foo\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The type parameter 'foo' was not recognized'. Line number '5': '14'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\" />\n            <conditions logicalGrouping=\"\"foo\"\">\n                <add input=\"\"{REQUEST_FILENAME}\"\" matchType=\"\"isFile\"\" negate=\"\"true\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The logicalGrouping parameter 'foo' was not recognized'. Line number '5': '14'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\" patternSyntax=\"\"foo\"\">\n            <match url = \"\"(.*)/$\"\" />\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The patternSyntax parameter 'foo' was not recognized'. Line number '3': '10'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\" />\n            <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\" matchType=\"\"foo\"\" negate=\"\"true\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The matchType parameter 'foo' was not recognized'. Line number '6': '18'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\" enabled=\"\"foo\"\">\n            <match url = \"\"(.*)/$\"\" />\n            <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\" negate=\"\"true\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The enabled parameter 'foo' was not recognized'. Line number '3': '10'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\" stopProcessing=\"\"foo\"\">\n            <match url = \"\"(.*)/$\"\" />\n            <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\" negate=\"\"true\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The stopProcessing parameter 'foo' was not recognized'. Line number '3': '10'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\" ignoreCase=\"\"foo\"\"/>\n            <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\" negate=\"\"true\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The ignoreCase parameter 'foo' was not recognized'. Line number '4': '14'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\"/>\n            <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\" ignoreCase=\"\"foo\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The ignoreCase parameter 'foo' was not recognized'. Line number '6': '18'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\" negate=\"\"foo\"\"/>\n            <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The negate parameter 'foo' was not recognized'. Line number '4': '14'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\"/>\n            <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\" negate=\"\"foo\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The negate parameter 'foo' was not recognized'. Line number '6': '18'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\"/>\n            <conditions trackAllCaptures=\"\"foo\"\">\n                <add input=\"\"{REQUEST_FILENAME}\"\"/>\n            </conditions>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" />\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The trackAllCaptures parameter 'foo' was not recognized'. Line number '5': '14'.\")]\n        [InlineData(\n            @\"<rewrite>\n    <rules>\n        <rule name=\"\"Remove trailing slash\"\">\n            <match url = \"\"(.*)/$\"\"/>\n            <action type=\"\"Redirect\"\" url =\"\"{R:1}\"\" appendQueryString=\"\"foo\"\"/>\n        </rule>\n    </rules>\n</rewrite>\",\n            \"Could not parse the UrlRewrite file. Message: 'The appendQueryString parameter 'foo' was not recognized'. Line number '5': '14'.\")]\n        public void ThrowInvalidUrlRewriteFormatExceptionWithCorrectMessage(string input, string expected)\n        {\n            // Arrange, Act, Assert\n            var ex = Assert.Throws<InvalidUrlRewriteFormatException>(() => new UrlRewriteFileParser().Parse(new StringReader(input)));\n            Assert.Equal(expected, ex.Message);\n        }\n    }\n}"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/MiddleWareTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Net;\nusing System.Text.RegularExpressions;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Extensions;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\nusing Microsoft.AspNetCore.TestHost;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite\n{\n    public class MiddlewareTests\n    {\n        [Fact]\n        public async Task Invoke_RedirectPathToPathAndQuery()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Rewrite to article.aspx\"\">\n                <match url = \"\"^article/([0-9]+)/([_0-9a-z-]+)\"\" />\n                <action type=\"\"Redirect\"\" url =\"\"article.aspx?id={R:1}&amp;title={R:2}\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(context.Response.Headers[HeaderNames.Location]));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"article/10/hey\");\n\n            Assert.Equal(\"/article.aspx?id=10&title=hey\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task Invoke_RewritePathToPathAndQuery()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Rewrite to article.aspx\"\">\n                <match url = \"\"^article/([0-9]+)/([_0-9a-z-]+)\"\" />\n                <action type=\"\"Rewrite\"\" url =\"\"article.aspx?id={R:1}&amp;title={R:2}\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(context.Request.Path + context.Request.QueryString));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"/article/10/hey\");\n\n            Assert.Equal(\"/article.aspx?id=10&title=hey\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_RewriteBasedOnQueryStringParameters()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Query String Rewrite\"\">\n                <match url=\"\"page\\.asp$\"\" />\n                <conditions>\n                <add input=\"\"{QUERY_STRING}\"\" pattern=\"\"p1=(\\d+)\"\" />\n                <add input=\"\"##{C:1}##_{QUERY_STRING}\"\" pattern=\"\"##([^#]+)##_.*p2=(\\d+)\"\" />\n                </conditions>\n                <action type=\"\"Rewrite\"\" url=\"\"newpage.aspx?param1={C:1}&amp;param2={C:2}\"\" appendQueryString=\"\"false\"\"/>\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(context.Request.Path + context.Request.QueryString));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"page.asp?p2=321&p1=123\");\n\n            Assert.Equal(\"/newpage.aspx?param1=123&param2=321\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_RedirectToLowerCase()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Convert to lower case\"\" stopProcessing=\"\"true\"\">\n                <match url=\"\".*[A-Z].*\"\" ignoreCase=\"\"false\"\" />\n                <action type=\"\"Redirect\"\" url=\"\"{ToLower:{R:0}}\"\" redirectType=\"\"Permanent\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(context.Response.Headers[HeaderNames.Location]));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"HElLo\");\n\n            Assert.Equal(\"/hello\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task Invoke_RedirectRemoveTrailingSlash()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Remove trailing slash\"\" stopProcessing=\"\"true\"\">\n                <match url=\"\"(.*)/$\"\" />\n                <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\" matchType=\"\"IsFile\"\" negate=\"\"true\"\" />\n                <add input=\"\"{REQUEST_FILENAME}\"\" matchType=\"\"IsDirectory\"\" negate=\"\"true\"\" />\n                </conditions>\n                <action type=\"\"Redirect\"\" redirectType=\"\"Permanent\"\" url=\"\"{R:1}\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"hey/hello/\");\n\n            Assert.Equal(\"/hey/hello\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task Invoke_RedirectAddTrailingSlash()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Add trailing slash\"\" stopProcessing=\"\"true\"\">\n                <match url=\"\"(.*[^/])$\"\" />\n                <conditions>\n                <add input=\"\"{REQUEST_FILENAME}\"\" matchType=\"\"IsFile\"\" negate=\"\"true\"\" />\n                <add input=\"\"{REQUEST_FILENAME}\"\" matchType=\"\"IsDirectory\"\" negate=\"\"true\"\" />\n                </conditions>\n                <action type=\"\"Redirect\"\" redirectType=\"\"Permanent\"\" url=\"\"{R:1}/\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"hey/hello\");\n\n            Assert.Equal(\"/hey/hello/\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task Invoke_RedirectToHttps()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Redirect to HTTPS\"\" stopProcessing=\"\"true\"\">\n                <match url=\"\"(.*)\"\" />\n                <conditions>\n                <add input=\"\"{HTTPS}\"\" pattern=\"\"^OFF$\"\" />\n                </conditions>\n                <action type=\"\"Redirect\"\" url=\"\"https://{HTTP_HOST}/{R:1}\"\" redirectType=\"\"Permanent\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(\"http://example.com\"));\n\n            Assert.Equal(\"https://example.com/\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task Invoke_RewriteToHttps()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Rewrite to HTTPS\"\" stopProcessing=\"\"true\"\">\n                <match url=\"\"(.*)\"\" />\n                <conditions>\n                <add input=\"\"{HTTPS}\"\" pattern=\"\"^OFF$\"\" />\n                </conditions>\n                <action type=\"\"Rewrite\"\" url=\"\"https://{HTTP_HOST}/{R:1}\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(\n                        context.Request.Scheme +\n                        \"://\" +\n                        context.Request.Host +\n                        context.Request.Path +\n                        context.Request.QueryString));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(new Uri(\"http://example.com\"));\n\n            Assert.Equal(\"https://example.com/\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_ReverseProxyToAnotherSite()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Proxy\"\">\n                <match url=\"\"(.*)\"\" />\n                <action type=\"\"Rewrite\"\" url=\"\"http://internalserver/{R:1}\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(\n                        context.Request.Scheme +\n                        \"://\" +\n                        context.Request.Host +\n                        context.Request.Path +\n                        context.Request.QueryString));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(new Uri(\"http://example.com/\"));\n\n            Assert.Equal(\"http://internalserver/\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_CaptureEmptyStringInRegexAssertRedirectLocationHasForwardSlash()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url=\"\"(.*)\"\" />\n                <action type=\"\"Redirect\"\" url=\"\"{R:1}\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(\n                        context.Request.Scheme +\n                        \"://\" +\n                        context.Request.Host +\n                        context.Request.Path +\n                        context.Request.QueryString));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(\"http://example.com/\"));\n\n            Assert.Equal(\"/\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task Invoke_CaptureEmptyStringInRegexAssertRewriteLocationHasForwardSlash()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url=\"\"(.*)\"\" />\n                <action type=\"\"Rewrite\"\" url=\"\"{R:1}\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(\n                        context.Request.Path +\n                        context.Request.QueryString));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(new Uri(\"http://example.com/\"));\n\n            Assert.Equal(\"/\", response);\n        }\n\n        [Fact]\n        public async Task Invoke_CaptureEmptyStringInRegexAssertLocationHeaderContainsPathBase()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url=\"\"(.*)\"\" />\n                <action type=\"\"Redirect\"\" url=\"\"{R:1}\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n                app.Run(context => context.Response.WriteAsync(\n                        context.Request.Path +\n                        context.Request.QueryString));\n            });\n            var server = new TestServer(builder) { BaseAddress = new Uri(\"http://localhost:5000/foo\") };\n\n            var response = await server.CreateClient().GetAsync(\"\");\n\n            Assert.Equal(\"/foo\", response.Headers.Location.OriginalString);\n        }\n\n        [Theory]\n        [InlineData(\"IsFile\")]\n        [InlineData(\"isfile\")]\n        [InlineData(\"IsDirectory\")]\n        [InlineData(\"isdirectory\")]\n        public async Task VerifyIsFileAndIsDirectoryParsing(string matchType)\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader($@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url=\"\"(.*[^/])$\"\" />\n                <conditions>\n                <add input=\"\"{{REQUEST_FILENAME}}\"\" matchType=\"\"{matchType}\"\" negate=\"\"true\"\"/>\n                </conditions>\n                <action type=\"\"Redirect\"\" url=\"\"{{R:1}}/\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"hey/hello\");\n\n            Assert.Equal(\"/hey/hello/\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task VerifyTrackAllCaptures()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url=\"\"(.*)\"\" ignoreCase=\"\"false\"\" />\n                <conditions trackAllCaptures = \"\"true\"\" >\n                <add input=\"\"{REQUEST_URI}\"\" pattern=\"\"^/([a-zA-Z]+)/([0-9]+)$\"\" />\n                <add input=\"\"{QUERY_STRING}\"\" pattern=\"\"p2=([a-z]+)\"\" />\n                </conditions>\n                <action type=\"\"Redirect\"\" url =\"\"blogposts/{C:1}/{C:4}\"\" />\n                <!--rewrite action uses back - references to both conditions -->\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"article/23?p1=123&p2=abc\");\n\n            Assert.Equal(\"/blogposts/article/abc\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task VerifyTrackAllCapturesRuleAndConditionCapture()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url=\"\"(.*)\"\" ignoreCase=\"\"false\"\" />\n                <conditions trackAllCaptures = \"\"true\"\" >\n                <add input=\"\"{REQUEST_URI}\"\" pattern=\"\"^/([a-zA-Z]+)/([0-9]+)$\"\" />\n                <add input=\"\"{QUERY_STRING}\"\" pattern=\"\"p2=([a-z]+)\"\" />\n                </conditions>\n                <action type=\"\"Redirect\"\" url =\"\"blog/{R:0}/{C:4}\"\" />\n                <!--rewrite action uses back - references to both conditions -->\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"article/23?p1=123&p2=abc\");\n\n            Assert.Equal(\"/blog/article/23/abc\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task ThrowIndexOutOfRangeExceptionWithCorrectMessage()\n        {\n            // Arrange, Act, Assert\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url=\"\"(.*)\"\" ignoreCase=\"\"false\"\" />\n                <conditions trackAllCaptures = \"\"true\"\" >\n                <add input=\"\"{REQUEST_URI}\"\" pattern=\"\"^/([a-zA-Z]+)/([0-9]+)$\"\" />\n                <add input=\"\"{QUERY_STRING}\"\" pattern=\"\"p2=([a-z]+)\"\" />\n                </conditions>\n                <action type=\"\"Redirect\"\" url =\"\"blog/{R:0}/{C:9}\"\" />\n                <!--rewrite action uses back - references to both conditions -->\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var ex = await Assert.ThrowsAsync<IndexOutOfRangeException>(() => server.CreateClient().GetAsync(\"article/23?p1=123&p2=abc\"));\n\n            Assert.Equal(\"Cannot access back reference at index 9. Only 5 back references were captured.\", ex.Message);\n        }\n\n        [Fact]\n        public async Task Invoke_GlobalRuleConditionMatchesAgainstFullUri_ParsedRule()\n        {\n            // arrange\n            var xml = @\"<rewrite>\n                            <globalRules>\n                                <rule name=\"\"Test\"\" patternSyntax=\"\"ECMAScript\"\" stopProcessing=\"\"true\"\">\n                                    <match url=\"\".*\"\" />\n                                    <conditions logicalGrouping=\"\"MatchAll\"\" trackAllCaptures=\"\"false\"\">\n                                        <add input=\"\"{REQUEST_URI}\"\" pattern=\"\"^http://localhost/([0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12})(/.*)\"\" />\n                                    </conditions>\n                                    <action type=\"\"Rewrite\"\" url=\"\"http://www.test.com{C:2}\"\" />\n                                </rule>\n                            </globalRules>\n                        </rewrite>\";\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(xml));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(context.Request.GetEncodedUrl()));\n                });\n            var server = new TestServer(builder);\n\n            // act\n            var response = await server.CreateClient().GetStringAsync($\"http://localhost/{Guid.NewGuid()}/foo/bar\");\n\n            // assert\n            Assert.Equal(\"http://www.test.com/foo/bar\", response);\n        }\n\n        [Theory]\n        [InlineData(\"http://fetch.environment.local/dev/path\", \"http://1.1.1.1/path\")]\n        [InlineData(\"http://fetch.environment.local/qa/path\", \"http://fetch.environment.local/qa/path\")]\n        public async Task Invoke_ReverseProxyToAnotherSiteUsingXmlConfiguredRewriteMap(string requestUri, string expectedRewrittenUri)\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"\n                <rewrite>\n                    <rules>\n                        <rule name=\"\"Proxy\"\">\n                            <match url=\"\"([^/]*)(/?.*)\"\" />\n                            <conditions>\n                                <add input=\"\"{environmentMap:{R:1}}\"\" pattern=\"\"(.+)\"\" />\n                            </conditions>\n                            <action type=\"\"Rewrite\"\" url=\"\"http://{C:1}{R:2}\"\" appendQueryString=\"\"true\"\" />\n                        </rule>\n                    </rules>\n                    <rewriteMaps>\n                        <rewriteMap name=\"\"environmentMap\"\">\n                            <add key=\"\"dev\"\" value=\"\"1.1.1.1\"\" />\n                        </rewriteMap>\n                    </rewriteMaps>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(context.Request.GetEncodedUrl()));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(new Uri(requestUri));\n\n            Assert.Equal(expectedRewrittenUri, response);\n        }\n\n        [Fact]\n        public async Task Invoke_CustomResponse()\n        {\n            var options = new RewriteOptions().AddIISUrlRewrite(new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Forbidden\"\">\n                <match url = \"\".*\"\" />\n                <action type=\"\"CustomResponse\"\" statusCode=\"\"403\"\" statusReason=\"\"reason\"\" statusDescription=\"\"description\"\" />\n                </rule>\n                </rules>\n                </rewrite>\"));\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"article/10/hey\");\n            var content = await response.Content.ReadAsStringAsync();\n\n            Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);\n            Assert.Equal(\"reason\", response.ReasonPhrase);\n            Assert.Equal(\"description\", content);\n        }\n\n        [Theory]\n        [InlineData(@\"^http://localhost(/.*)\", \"http://localhost/foo/bar\", UriMatchPart.Path)]\n        [InlineData(@\"^http://localhost(/.*)\", \"http://www.test.com/foo/bar\", UriMatchPart.Full)]\n        public async Task Invoke_GlobalRuleConditionMatchesAgainstFullUri_CodedRule(string conditionInputPattern, string expectedResult, UriMatchPart uriMatchPart)\n        {\n            // arrange\n            var inputParser = new InputParser();\n\n            var ruleBuilder = new UrlRewriteRuleBuilder\n            {\n                Name = \"test\",\n                Global = false\n            };\n            ruleBuilder.AddUrlMatch(\".*\");\n\n            var condition = new UriMatchCondition(\n                inputParser,\n                \"{REQUEST_URI}\",\n                conditionInputPattern,\n                uriMatchPart,\n                ignoreCase: true,\n                negate: false);\n            ruleBuilder.ConfigureConditionBehavior(LogicalGrouping.MatchAll, trackAllCaptures: true);\n            ruleBuilder.AddUrlCondition(condition);\n\n            var action = new RewriteAction(\n                RuleResult.SkipRemainingRules,\n                inputParser.ParseInputString(@\"http://www.test.com{C:1}\", uriMatchPart),\n                queryStringAppend: false);\n            ruleBuilder.AddUrlAction(action);\n\n            var options = new RewriteOptions().Add(ruleBuilder.Build());\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(context.Request.GetEncodedUrl()));\n                });\n            var server = new TestServer(builder);\n\n            // act\n            var response = await server.CreateClient().GetStringAsync(\"http://localhost/foo/bar\");\n\n            // assert\n            Assert.Equal(expectedResult, response);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/RewriteMapParserTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing System.Linq;\nusing System.Xml.Linq;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.IISUrlRewrite\n{\n    public class RewriteMapParserTests\n    {\n        [Fact]\n        public void Should_parse_rewrite_map()\n        {\n            // arrange\n            const string expectedMapName = \"apiMap\";\n            const string expectedKey = \"api.test.com\";\n            const string expectedValue = \"test.com/api\";\n            var xml = $@\"<rewrite>\n                                <rewriteMaps>\n                                    <rewriteMap name=\"\"{expectedMapName}\"\">\n                                        <add key=\"\"{expectedKey}\"\" value=\"\"{expectedValue}\"\" />\n                                    </rewriteMap>\n                                </rewriteMaps>\n                            </rewrite>\";\n\n            // act\n            var xmlDoc = XDocument.Load(new StringReader(xml), LoadOptions.SetLineInfo);\n            var xmlRoot = xmlDoc.Descendants(RewriteTags.Rewrite).FirstOrDefault();\n            var actualMaps = RewriteMapParser.Parse(xmlRoot);\n\n            // assert\n            Assert.Equal(1, actualMaps.Count);\n\n            var actualMap = actualMaps[expectedMapName];\n            Assert.NotNull(actualMap);\n            Assert.Equal(expectedMapName, actualMap.Name);\n            Assert.Equal(expectedValue, actualMap[expectedKey]);\n        }\n    }\n}"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/ServerVariableTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite\n{\n    public class ServerVariableTests\n    {\n        [Theory]\n        [InlineData(\"CONTENT_LENGTH\", \"10\", UriMatchPart.Path)]\n        [InlineData(\"CONTENT_TYPE\", \"json\", UriMatchPart.Path)]\n        [InlineData(\"HTTP_ACCEPT\", \"accept\", UriMatchPart.Path)]\n        [InlineData(\"HTTP_COOKIE\", \"cookie\", UriMatchPart.Path)]\n        [InlineData(\"HTTP_HOST\", \"example.com\", UriMatchPart.Path)]\n        [InlineData(\"HTTP_REFERER\", \"referer\", UriMatchPart.Path)]\n        [InlineData(\"HTTP_USER_AGENT\", \"useragent\", UriMatchPart.Path)]\n        [InlineData(\"HTTP_CONNECTION\", \"connection\", UriMatchPart.Path)]\n        [InlineData(\"HTTP_URL\", \"/foo\", UriMatchPart.Path)]\n        [InlineData(\"HTTP_URL\", \"http://example.com/foo?bar=1\", UriMatchPart.Full)]\n        [InlineData(\"QUERY_STRING\", \"bar=1\", UriMatchPart.Path)]\n        [InlineData(\"REQUEST_FILENAME\", \"/foo\", UriMatchPart.Path)]\n        [InlineData(\"REQUEST_URI\", \"/foo\", UriMatchPart.Path)]\n        [InlineData(\"REQUEST_URI\", \"http://example.com/foo?bar=1\", UriMatchPart.Full)]\n        [InlineData(\"REQUEST_METHOD\", \"GET\", UriMatchPart.Full)]\n        public void CheckServerVariableParsingAndApplication(string variable, string expected, UriMatchPart uriMatchPart)\n        {\n            // Arrange and Act\n            var testParserContext = new ParserContext(\"test\");\n            var serverVar = ServerVariables.FindServerVariable(variable, testParserContext, uriMatchPart);\n            var lookup = serverVar.Evaluate(CreateTestHttpContext(), CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);\n            // Assert\n            Assert.Equal(expected, lookup);\n        }\n\n        private RewriteContext CreateTestHttpContext()\n        {\n            var context = new DefaultHttpContext();\n            context.Request.Method = HttpMethods.Get;\n            context.Request.Scheme = \"http\";\n            context.Request.Host = new HostString(\"example.com\");\n            context.Request.Path = PathString.FromUriComponent(\"/foo\");\n            context.Request.QueryString = QueryString.FromUriComponent(\"?bar=1\");\n            context.Request.ContentLength = 10;\n            context.Request.ContentType = \"json\";\n            context.Request.Headers[HeaderNames.Accept] = \"accept\";\n            context.Request.Headers[HeaderNames.Cookie] = \"cookie\";\n            context.Request.Headers[HeaderNames.Referer] = \"referer\";\n            context.Request.Headers[HeaderNames.UserAgent] = \"useragent\";\n            context.Request.Headers[HeaderNames.Connection] = \"connection\";\n            return new RewriteContext { HttpContext = context };\n        }\n\n        private MatchResults CreateTestRuleMatch()\n        {\n            var match = Regex.Match(\"foo/bar/baz\", \"(.*)/(.*)/(.*)\");\n            return new MatchResults { BackReferences = new BackReferenceCollection(match.Groups), Success = match.Success };\n        }\n\n        private MatchResults CreateTestCondMatch()\n        {\n            var match = Regex.Match(\"foo/bar/baz\", \"(.*)/(.*)/(.*)\");\n            return new MatchResults { BackReferences = new BackReferenceCollection(match.Groups), Success = match.Success };\n        }\n\n        [Fact]\n        private void EmptyQueryStringCheck()\n        {\n            var context = new DefaultHttpContext();\n            var rewriteContext = new RewriteContext { HttpContext = context };\n            var testParserContext = new ParserContext(\"test\");\n            var serverVar = ServerVariables.FindServerVariable(\"QUERY_STRING\", testParserContext, UriMatchPart.Path);\n            var lookup = serverVar.Evaluate(rewriteContext, CreateTestRuleMatch().BackReferences, CreateTestCondMatch().BackReferences);\n\n            Assert.Equal(string.Empty, lookup);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/UrlRewriteApplicationTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.IO;\nusing System.Linq;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlRewrite\n{\n    // TODO add more of these\n    public class UrlRewriteApplicationTests\n    {\n        [Fact]\n        public void ApplyRule_AssertStopProcessingFlagWillTerminateOnNoAction()\n        {\n            var xml = new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\" stopProcessing=\"\"true\"\">\n                <match url = \"\"(.*)\"\"/>\n                <action type = \"\"None\"\"/>\n                </rule>\n                </rules>\n                </rewrite>\");\n            var rules = new UrlRewriteFileParser().Parse(xml);\n\n            Assert.Equal(1, rules.Count);\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            rules.FirstOrDefault().ApplyRule(context);\n            Assert.Equal(RuleResult.SkipRemainingRules, context.Result);\n        }\n\n        [Fact]\n        public void ApplyRule_AssertNoTerminateFlagWillNotTerminateOnNoAction()\n        {\n            var xml = new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url = \"\"(.*)\"\" ignoreCase=\"\"false\"\" />\n                <action type = \"\"None\"\"/>\n                </rule>\n                </rules>\n                </rewrite>\");\n            var rules = new UrlRewriteFileParser().Parse(xml);\n\n            Assert.Equal(1, rules.Count);\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            rules.FirstOrDefault().ApplyRule(context);\n            Assert.Equal(RuleResult.ContinueRules, context.Result);\n        }\n\n        [Fact]\n        public void ApplyRule_TrackAllCaptures()\n        {\n            var xml = new StringReader(@\"<rewrite>\n                <rules>\n                <rule name=\"\"Test\"\">\n                <match url = \"\"(.*)\"\" ignoreCase=\"\"false\"\" />\n                <conditions trackAllCaptures = \"\"true\"\" >\n                <add input = \"\"{REQUEST_URI}\"\" pattern = \"\"^/([a-zA-Z]+)/([0-9]+)/$\"\" />\n                </conditions >\n                <action type = \"\"None\"\"/>\n                </rule>\n                </rules>\n                </rewrite>\");\n            var rules = new UrlRewriteFileParser().Parse(xml);\n\n            Assert.Equal(1, rules.Count);\n            Assert.True(rules[0].Conditions.TrackAllCaptures);\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            rules.FirstOrDefault().ApplyRule(context);\n            Assert.Equal(RuleResult.ContinueRules, context.Result);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/Microsoft.AspNetCore.Rewrite.Tests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>$(StandardTestTfms)</TargetFrameworks>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\Microsoft.AspNetCore.Rewrite\\Microsoft.AspNetCore.Rewrite.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/MiddlewareTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.TestHost;\nusing Microsoft.Extensions.DependencyInjection;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.CodeRules\n{\n    public class MiddlewareTests\n    {\n        [Fact]\n        public async Task CheckRewritePath()\n        {\n            var options = new RewriteOptions().AddRewrite(\"(.*)\", \"http://example.com/$1\", skipRemainingRules: false);\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                    app.Run(context => context.Response.WriteAsync(\n                        context.Request.Scheme +\n                        \"://\" +\n                        context.Request.Host +\n                        context.Request.Path +\n                        context.Request.QueryString));\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"foo\");\n\n            Assert.Equal(\"http://example.com/foo\", response);\n        }\n\n        [Fact]\n        public async Task CheckRedirectPath()\n        {\n            var options = new RewriteOptions().AddRedirect(\"(.*)\", \"http://example.com/$1\", statusCode: StatusCodes.Status301MovedPermanently);\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"foo\");\n\n            Assert.Equal(\"http://example.com/foo\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task RewriteRulesCanComeFromConfigureOptions()\n        {\n            var builder = new WebHostBuilder()\n            .ConfigureServices(services =>\n            {\n                services.Configure<RewriteOptions>(options =>\n                {\n                    options.AddRedirect(\"(.*)\", \"http://example.com/$1\", statusCode: StatusCodes.Status301MovedPermanently);\n                });\n            })\n            .Configure(app =>\n            {\n                app.UseRewriter();\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"foo\");\n\n            Assert.Equal(\"http://example.com/foo\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task CheckRedirectPathWithQueryString()\n        {\n            var options = new RewriteOptions().AddRedirect(\"(.*)\", \"http://example.com/$1\", statusCode: StatusCodes.Status301MovedPermanently);\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"foo?bar=1\");\n\n            Assert.Equal(\"http://example.com/foo?bar=1\", response.Headers.Location.OriginalString);\n        }\n\n        [Theory]\n        [InlineData(StatusCodes.Status301MovedPermanently)]\n        [InlineData(StatusCodes.Status302Found)]\n        [InlineData(StatusCodes.Status307TemporaryRedirect)]\n        [InlineData(StatusCodes.Status308PermanentRedirect)]\n        public async Task CheckRedirectToHttps(int statusCode)\n        {\n            var options = new RewriteOptions().AddRedirectToHttps(statusCode: statusCode);\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(\"http://example.com\"));\n\n            Assert.Equal(\"https://example.com/\", response.Headers.Location.OriginalString);\n            Assert.Equal(statusCode, (int)response.StatusCode);\n        }\n\n        [Fact]\n        public async Task CheckPermanentRedirectToHttps()\n        {\n            var options = new RewriteOptions().AddRedirectToHttpsPermanent();\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(\"http://example.com\"));\n\n            Assert.Equal(\"https://example.com/\", response.Headers.Location.OriginalString);\n            Assert.Equal(StatusCodes.Status301MovedPermanently, (int)response.StatusCode);\n        }\n\n        [Theory]\n        [InlineData(25, \"https://example.com:25/\")]\n        [InlineData(-25, \"https://example.com/\")]\n        public async Task CheckRedirectToHttpsWithSslPort(int sslPort, string expected)\n        {\n            var options = new RewriteOptions().AddRedirectToHttps(statusCode: StatusCodes.Status301MovedPermanently, sslPort: sslPort);\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(\"http://example.com\"));\n\n            Assert.Equal(expected, response.Headers.Location.OriginalString);\n            Assert.Equal(StatusCodes.Status301MovedPermanently, (int)response.StatusCode);\n        }\n\n        [Theory]\n        [InlineData(StatusCodes.Status301MovedPermanently)]\n        [InlineData(StatusCodes.Status302Found)]\n        [InlineData(StatusCodes.Status307TemporaryRedirect)]\n        [InlineData(StatusCodes.Status308PermanentRedirect)]\n        public async Task CheckRedirectToWwwWithStatusCode(int statusCode)\n        {\n            var options = new RewriteOptions().AddRedirectToWww(statusCode: statusCode);\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(\"https://example.com\"));\n\n            Assert.Equal(\"https://www.example.com/\", response.Headers.Location.OriginalString);\n            Assert.Equal(statusCode, (int)response.StatusCode);\n        }\n\n        [Theory]\n        [InlineData(\"http://example.com\", \"http://www.example.com/\")]\n        [InlineData(\"https://example.com\", \"https://www.example.com/\")]\n        [InlineData(\"http://example.com:8081\", \"http://www.example.com:8081/\")]\n        [InlineData(\"http://example.com:8081/example?q=1\", \"http://www.example.com:8081/example?q=1\")]\n        public async Task CheckRedirectToWww(string requestUri, string redirectUri)\n        {\n            var options = new RewriteOptions().AddRedirectToWww();\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(requestUri));\n\n            Assert.Equal(redirectUri, response.Headers.Location.OriginalString);\n            Assert.Equal(StatusCodes.Status307TemporaryRedirect, (int)response.StatusCode);\n        }\n\n        [Fact]\n        public async Task CheckPermanentRedirectToWww()\n        {\n            var options = new RewriteOptions().AddRedirectToWwwPermanent();\n            var builder = new WebHostBuilder()\n                .Configure(app =>\n                {\n                    app.UseRewriter(options);\n                });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(\"https://example.com\"));\n\n            Assert.Equal(\"https://www.example.com/\", response.Headers.Location.OriginalString);\n            Assert.Equal(StatusCodes.Status308PermanentRedirect, (int)response.StatusCode);\n        }\n\n        [Theory]\n        [InlineData(\"http://www.example.com\")]\n        [InlineData(\"https://www.example.com\")]\n        [InlineData(\"http://www.example.com:8081\")]\n        [InlineData(\"https://www.example.com:8081\")]\n        [InlineData(\"https://www.example.com:8081/example?q=1\")]\n        [InlineData(\"http://localhost\")]\n        [InlineData(\"https://localhost\")]\n        [InlineData(\"http://localhost:8081\")]\n        [InlineData(\"https://localhost:8081\")]\n        [InlineData(\"https://localhost:8081/example?q=1\")]\n        public async Task CheckNoRedirectToWww(string requestUri)\n        {\n            var options = new RewriteOptions().AddRedirectToWww();\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(new Uri(requestUri));\n\n            Assert.Null(response.Headers.Location);\n        }\n\n        [Fact]\n        public async Task CheckIfEmptyStringRedirectCorrectly()\n        {\n            var options = new RewriteOptions().AddRedirect(\"(.*)\", \"$1\", statusCode: StatusCodes.Status301MovedPermanently);\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetAsync(\"\");\n            Assert.Equal(\"/\", response.Headers.Location.OriginalString);\n        }\n\n        [Fact]\n        public async Task CheckIfEmptyStringRewriteCorrectly()\n        {\n            var options = new RewriteOptions().AddRewrite(\"(.*)\", \"$1\", skipRemainingRules: false);\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n                app.Run(context => context.Response.WriteAsync(\n                        context.Request.Path +\n                        context.Request.QueryString));\n            });\n            var server = new TestServer(builder);\n\n            var response = await server.CreateClient().GetStringAsync(\"\");\n\n            Assert.Equal(\"/\", response);\n        }\n\n        [Fact]\n        public async Task SettingPathBase()\n        {\n            var options = new RewriteOptions().AddRedirect(\"(.*)\", \"$1\");\n            var builder = new WebHostBuilder()\n            .Configure(app =>\n            {\n                app.UseRewriter(options);\n                app.Run(context => context.Response.WriteAsync(\n                        context.Request.Path +\n                        context.Request.QueryString));\n            });\n            var server = new TestServer(builder) { BaseAddress = new Uri(\"http://localhost:5000/foo\") };\n\n            var response = await server.CreateClient().GetAsync(\"\");\n\n            Assert.Equal(\"/foo\", response.Headers.Location.OriginalString);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ConditionMatchSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class ConditionMatchSegmentTests\n    {\n\n        [Theory]\n        [InlineData(1, \"foo\")]\n        [InlineData(2, \"bar\")]\n        [InlineData(3, \"baz\")]\n        public void ConditionMatch_AssertBackreferencesObtainsCorrectValue(int index, string expected)\n        {\n            // Arrange\n            var condMatch = CreateTestMatch();\n            var segment = new ConditionMatchSegment(index);\n\n            // Act\n            var results = segment.Evaluate(null, null, condMatch.BackReferences);\n\n            // Assert\n            Assert.Equal(expected, results);\n        }\n\n        private static MatchResults CreateTestMatch()\n        {\n            var match = Regex.Match(\"foo/bar/baz\", \"(.*)/(.*)/(.*)\");\n            return new MatchResults { BackReferences = new BackReferenceCollection(match.Groups), Success = match.Success };\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/DateTimeSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class DateTimeSegmentTests\n    {\n        [Theory]\n        [InlineData(\"TIME_YEAR\")]\n        [InlineData(\"TIME_MON\")]\n        [InlineData(\"TIME_DAY\")]\n        [InlineData(\"TIME_HOUR\")]\n        [InlineData(\"TIME_MIN\")]\n        [InlineData(\"TIME_SEC\")]\n        [InlineData(\"TIME_WDAY\")]\n        [InlineData(\"TIME\")]\n        public void DateTime_AssertDoesntThrowOnCheckOfSegment(string input)\n        {\n            // Arrange\n            var segment = new DateTimeSegment(input);\n\n            // Act\n            var results = segment.Evaluate(null, null, null);\n\n            // TODO testing dates is hard, could use moq\n            // currently just assert that the segment doesn't throw.\n        }\n\n        [Theory]\n        [InlineData(\"foo\", \"Unsupported segment: 'foo'\")]\n        [InlineData(\"wow\", \"Unsupported segment: 'wow'\")]\n        public void DateTime_AssertThrowsOnInvalidInput(string input, string expected)\n        {\n            // Act And Assert\n            var ex = Assert.Throws<FormatException>(() => new DateTimeSegment(input));\n            Assert.Equal(expected, ex.Message);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/HeaderSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class HeaderSegmentTests\n    {\n        [Fact]\n        public void HeaderSegment_AssertGettingWithHeaderReturnsCorrectValue()\n        {\n            // Arrange\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n\n            context.HttpContext.Request.Headers[HeaderNames.Location] = \"foo\";\n            var segment = new HeaderSegment(HeaderNames.Location);\n\n            // Act\n            var results = segment.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"foo\", results);\n        }\n\n        [Fact]\n        public void HeaderSegment_AssertGettingANonExistantHeaderReturnsNull()\n        {\n            // Arrange\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var segment = new HeaderSegment(HeaderNames.Location);\n\n            // Act\n            var results = segment.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Null(results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsModSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class IsHttpsModSegmentTests\n    {\n        [Theory]\n        [InlineData(\"http\", \"off\")]\n        [InlineData(\"https\", \"on\")]\n        public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected)\n        {\n            // Arrange\n            var segement = new IsHttpsModSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Request.Scheme = input;\n\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(expected, results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class IsHttpsSegmentTests\n    {\n        [Theory]\n        [InlineData(\"http\", \"OFF\")]\n        [InlineData(\"https\", \"ON\")]\n        public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected)\n        {\n            // Arrange\n            var segement = new IsHttpsUrlSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Request.Scheme = input;\n\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(expected, results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsIPV6SegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\n\nusing System.Net;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class IsIPV6SegmentTests\n    {\n        [Fact]\n        public void IsIPv6_AssertNullRemoteIpAddressReportsCorrectValue()\n        {\n            // Arrange\n            var segement = new IsIPV6Segment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.RemoteIpAddress = null;\n\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"off\", results);\n        }\n\n        [Fact]\n        public void IsIPv6_AssertCorrectBehaviorWhenIPv6IsUsed()\n        {\n            // Arrange\n            var segement = new IsIPV6Segment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse(\"2001:0db8:85a3:0000:0000:8a2e:0370:7334\");\n\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"on\", results);\n        }\n\n        [Fact]\n        public void IsIPv6_AssertCorrectBehaviorWhenIPv4IsUsed()\n        {\n            // Arrange\n            var segement = new IsIPV6Segment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse(\"20.30.40.50\");\n\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"off\", results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LIteralSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class LiteralSegmentTests\n    {\n        [Fact]\n        public void LiteralSegment_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new LiteralSegment(\"foo\");\n\n            // Act\n            var results = segement.Evaluate(null, null, null);\n\n            // Assert\n            Assert.Equal(\"foo\", results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalAddressSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\n\nusing System.Net;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class LocalAddressSegmentTests\n    {\n        [Fact]\n        public void LocalAddress_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new LocalAddressSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.LocalIpAddress = IPAddress.Parse(\"20.30.40.50\");\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"20.30.40.50\", results);\n        }\n\n        [Fact]\n        public void LocalAddress_AssertNullLocalIpAddressReturnsNull()\n        {\n            var segement = new LocalAddressSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.LocalIpAddress = null;\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Null( results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalPortSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\n\nusing System.Globalization;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class LocalPortSegmentTests\n    {\n        [Fact]\n        public void LocalPortSegment_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new LocalPortSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.LocalPort = 800;\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"800\", results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/QueryStringSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class QueryStringSegmentTests\n    {\n        [Fact]\n        public void QueryString_AssertSegmentIsCorrect()\n        {\n            var segement = new QueryStringSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Request.QueryString = new QueryString(\"?hey=1\");\n\n            var results = segement.Evaluate(context, null, null);\n\n            Assert.Equal(\"hey=1\", results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemoteAddressSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Net;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class RemoteAddressSegmentTests\n    {\n        [Fact]\n        public void RemoteAddress_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new RemoteAddressSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse(\"20.30.40.50\");\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"20.30.40.50\", results);\n        }\n\n        [Fact]\n        public void RemoteAddress_AssertNullLocalIpAddressReturnsNull()\n        {\n            var segement = new RemoteAddressSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.RemoteIpAddress = null;\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Null(results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemotePortSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class RemotePortSegmentTests\n    {\n        [Fact]\n        public void RemotePort_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new RemotePortSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Connection.RemotePort = 800;\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"800\", results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestFilenameSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class RequestFilenameSegmentTests\n    {\n        [Fact]\n        public void RequestFilename_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new RequestFileNameSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Request.Path = new PathString(\"/foo/bar\");\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"/foo/bar\", results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestMethodSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class RequestMethodSegmentTests\n    {\n        [Fact]\n        public void RequestMethod_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new RequestMethodSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Request.Method = HttpMethods.Get;\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(HttpMethods.Get, results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RuleMatchSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Text.RegularExpressions;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class RuleMatchSegmentTests\n    {\n        [Theory]\n        [InlineData(1, \"foo\")]\n        [InlineData(2, \"bar\")]\n        [InlineData(3, \"baz\")]\n        public void RuleMatch_AssertBackreferencesObtainsCorrectValue(int index, string expected)\n        {\n            // Arrange\n            var ruleMatch = CreateTestMatch();\n            var segment = new RuleMatchSegment(index);\n\n            // Act\n            var results = segment.Evaluate(null, ruleMatch.BackReferences, null);\n\n            // Assert\n            Assert.Equal(expected, results);\n        }\n\n        private static MatchResults CreateTestMatch()\n        {\n            var match = Regex.Match(\"foo/bar/baz\", \"(.*)/(.*)/(.*)\");\n            return new MatchResults { BackReferences = new BackReferenceCollection(match.Groups), Success = match.Success };\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/SchemeSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class SchemeSegmentTests\n    {\n        [Fact]\n        public void SchemeSegment_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new SchemeSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Request.Scheme = \"http\";\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"http\", results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ServerProtocolSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Http.Features;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class ServerProtocolSegmentTests\n    {\n        [Fact]\n        public void ServerProtocol_AssertSegmentIsCorrect()\n        {\n            // Arrange\n            var segement = new ServerProtocolSegment();\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            context.HttpContext.Features.Set<IHttpRequestFeature>(new HttpRequestFeature { Protocol = \"http\" });\n\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(\"http\", results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ToLowerSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class ToLowerSegmentTests\n    {\n        [Theory]\n        [InlineData(\"Hello\", \"hello\")]\n        [InlineData(\"WHAT\", \"what\")]\n        [InlineData(\"hey\", \"hey\")]\n        public void ToLower_AssertLowerCaseWorksAppropriately(string input, string expected)\n        {\n            // Arrange\n            var pattern = new Pattern(new List<PatternSegment>());\n            pattern.PatternSegments.Add(new LiteralSegment(input));\n            var segement = new ToLowerSegment(pattern);\n            var context = new RewriteContext();\n\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(expected, results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlEncodeSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System.Collections.Generic;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class UrlEncodeSegmentTests\n    {\n        [Theory]\n        [InlineData(\" \", \"%20\")]\n        [InlineData(\"x&y\", \"x%26y\")]\n        [InlineData(\"hey\", \"hey\")]\n        public void ToLower_AssertLowerCaseWorksAppropriately(string input, string expected)\n        {\n            // Arrange\n            var pattern = new Pattern(new List<PatternSegment>());\n            pattern.PatternSegments.Add(new LiteralSegment(input));\n            var segement = new UrlEncodeSegment(pattern);\n            var context = new RewriteContext();\n\n            // Act\n            var results = segement.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(expected, results);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlSegmentTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite;\nusing Microsoft.AspNetCore.Rewrite.Internal.PatternSegments;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments\n{\n    public class UrlSegmentTests\n    {\n        [Theory]\n        [InlineData(\"http\", \"localhost\", 80, null, UriMatchPart.Path, \"\")]\n        [InlineData(\"http\", \"localhost\", 80, \"\", UriMatchPart.Path, \"\")]\n        [InlineData(\"http\", \"localhost\", 80, \"/foo/bar\", UriMatchPart.Path, \"/foo/bar\")]\n        [InlineData(\"http\", \"localhost\", 80, \"/foo:bar\", UriMatchPart.Path, \"/foo:bar\")]\n        [InlineData(\"http\", \"localhost\", 80, \"/foo bar\", UriMatchPart.Path, \"/foo%20bar\")]\n        [InlineData(\"http\", \"localhost\", 80, null, UriMatchPart.Full, \"http://localhost:80/\")]\n        [InlineData(\"http\", \"localhost\", 80, \"\", UriMatchPart.Full, \"http://localhost:80/\")]\n        [InlineData(\"http\", \"localhost\", 80, \"/foo:bar\", UriMatchPart.Full, \"http://localhost:80/foo:bar\")]\n        [InlineData(\"http\", \"localhost\", 80, \"/foo bar\", UriMatchPart.Full, \"http://localhost:80/foo%20bar\")]\n        [InlineData(\"http\", \"localhost\", 80, \"/foo/bar\", UriMatchPart.Full, \"http://localhost:80/foo/bar\")]\n        [InlineData(\"http\", \"localhost\", 81, \"/foo/bar\", UriMatchPart.Full, \"http://localhost:81/foo/bar\")]\n        [InlineData(\"https\", \"localhost\", 443, \"/foo/bar\", UriMatchPart.Full, \"https://localhost:443/foo/bar\")]\n        public void AssertSegmentIsCorrect(string scheme, string host, int port, string path, UriMatchPart uriMatchPart, string expectedResult)\n        {\n            // Arrange\n            var httpContext = new DefaultHttpContext();\n            httpContext.Request.Scheme = scheme;\n            httpContext.Request.Host = new HostString(host, port);\n            httpContext.Request.Path = new PathString(path);\n\n            var context = new RewriteContext { HttpContext = httpContext };\n            context.HttpContext = httpContext;\n\n            // Act\n            var segment = new UrlSegment(uriMatchPart);\n            var results = segment.Evaluate(context, null, null);\n\n            // Assert\n            Assert.Equal(expectedResult, results);\n        }\n    }\n}"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/AbortActionTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions\n{\n    public class AbortActionTests\n    {\n        public void AbortAction_VerifyEndResponseResult()\n        {\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var action = new AbortAction();\n\n            action.ApplyAction(context, null, null);\n\n            Assert.Equal(RuleResult.EndResponse, context.Result);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/ChangeCookieActionTests.cs",
    "content": "// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Microsoft.Net.Http.Headers;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions\n{\n    public class ChangeCookieActionTests\n    {\n        [Fact]\n        public void SetsCookie()\n        {\n            var now = DateTimeOffset.UtcNow;\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var action = new ChangeCookieAction(\"Cookie\", () => now)\n            {\n                Value = \"Chocolate Chip\",\n                Domain = \"contoso.com\",\n                Lifetime = TimeSpan.FromMinutes(1440),\n                Path = \"/recipes\",\n                Secure = true,\n                HttpOnly = true\n            };\n\n            action.ApplyAction(context, null, null);\n\n            var cookieHeaders = context.HttpContext.Response.Headers[HeaderNames.SetCookie];\n            var header = Assert.Single(cookieHeaders);\n            Assert.Equal($\"Cookie=Chocolate%20Chip; expires={HeaderUtilities.FormatDate(now.AddMinutes(1440))}; domain=contoso.com; path=/recipes; secure; samesite=lax; httponly\", header);\n        }\n\n        [Fact]\n        public void ZeroLifetime()\n        {\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var action = new ChangeCookieAction(\"Cookie\")\n            {\n                Value = \"Chocolate Chip\",\n            };\n\n            action.ApplyAction(context, null, null);\n\n            var cookieHeaders = context.HttpContext.Response.Headers[HeaderNames.SetCookie];\n            var header = Assert.Single(cookieHeaders);\n            Assert.Equal($\"Cookie=Chocolate%20Chip; samesite=lax\", header);\n        }\n\n\n        [Fact]\n        public void UnsetCookie()\n        {\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var action = new ChangeCookieAction(\"Cookie\");\n\n            action.ApplyAction(context, null, null);\n\n            var cookieHeaders = context.HttpContext.Response.Headers[HeaderNames.SetCookie];\n            var header = Assert.Single(cookieHeaders);\n            Assert.Equal($\"Cookie=; samesite=lax\", header);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/ForbiddenActionTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions\n{\n    public class ForbiddenActionTests\n    {\n        [Fact]\n        public void Forbidden_Verify403IsInStatusCode()\n        {\n\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var action = new ForbiddenAction();\n\n            action.ApplyAction(context, null, null);\n\n            Assert.Equal(RuleResult.EndResponse, context.Result);\n            Assert.Equal(StatusCodes.Status403Forbidden, context.HttpContext.Response.StatusCode);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/GoneActionTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions\n{\n    public class GoneActionTests\n    {\n        [Fact]\n        public void Gone_Verify410IsInStatusCode()\n        {\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var action = new GoneAction();\n\n            action.ApplyAction(context, null, null);\n\n            Assert.Equal(RuleResult.EndResponse, context.Result);\n            Assert.Equal(StatusCodes.Status410Gone, context.HttpContext.Response.StatusCode);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/UrlMatches/ExactMatchTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlMatches\n{\n    public class ExactMatchTests\n    {\n        [Theory]\n        [InlineDataAttribute(true,\"string\",false,\"string\",true)]\n        [InlineDataAttribute(true, \"string\", true, \"string\", false)]\n        [InlineDataAttribute(false, \"STRING\", false, \"string\",false)]\n        [InlineDataAttribute(false, \"STRING\", true, \"string\", true)]\n        public void ExactMatch_Case_Sensitivity_Negate_Tests(bool ignoreCase, string inputString, bool negate, string pattern, bool expectedResult)\n        {\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var Match = new ExactMatch(ignoreCase, inputString, negate);\n            var matchResults = Match.Evaluate(pattern, context);\n            Assert.Equal(expectedResult, matchResults.Success);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/UrlMatches/IntegerMatchTests.cs",
    "content": "﻿// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite;\nusing Microsoft.AspNetCore.Rewrite.Internal;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlActions;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlMatches\n{\n    public class IntegerMatchTests\n    {\n        [Fact]\n        public void IntegerMatch_Constructor_Integer_Parse_Excetion()\n        {\n            var ex = Assert.Throws<FormatException>(() => new IntegerMatch(\"Not an int\", IntegerOperationType.Equal));\n            Assert.Equal(ex.Message, Resources.Error_IntegerMatch_FormatExceptionMessage);\n        }\n\n        [Theory]\n        [InlineData(1,IntegerOperationType.Equal,\"1\",true)]\n        [InlineData(1, IntegerOperationType.NotEqual, \"2\", true)]\n        [InlineData(2, IntegerOperationType.Less, \"1\", true)]\n        [InlineData(1, IntegerOperationType.LessEqual, \"2\", false)]\n        [InlineData(1, IntegerOperationType.Greater, \"2\", true)]\n        [InlineData(2, IntegerOperationType.GreaterEqual, \"1\", false)]\n        [InlineData(1, IntegerOperationType.Equal, \"Not an int\", false)]\n        [InlineData(1, IntegerOperationType.Equal, \"\", false)]\n        [InlineData(1, IntegerOperationType.Equal, \"2147483648\", false)]\n        public void IntegerMatch_Evaluation_Cases_Tests(int value,IntegerOperationType operation, string input,bool expectedResult)\n        {\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var integerMatch = new IntegerMatch(value, operation);\n            var matchResult = integerMatch.Evaluate(input, context);\n            Assert.Equal(expectedResult, matchResult.Success);\n        }\n    }\n}\n"
  },
  {
    "path": "test/Microsoft.AspNetCore.Rewrite.Tests/UrlMatches/StringMatchTests.cs",
    "content": "﻿using Microsoft.AspNetCore.Http;\nusing Microsoft.AspNetCore.Rewrite.Internal.UrlMatches;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Xunit;\n\nnamespace Microsoft.AspNetCore.Rewrite.Tests.UrlMatches\n{\n    public class StringMatchTests\n    {\n        [Theory]\n        [InlineData(\"hi\", StringOperationType.Equal,true,\"hi\",true)]\n        [InlineData(\"a\", StringOperationType.Greater, true, \"b\", true)]\n        [InlineData(\"a\", StringOperationType.GreaterEqual, true, \"b\", true)]\n        [InlineData(\"b\", StringOperationType.Less,true, \"a\", true)]\n        [InlineData(\"b\", StringOperationType.LessEqual, true, \"a\", true)]\n        [InlineData(\"\", StringOperationType.Equal, true, \"\", true)]\n        [InlineData(null, StringOperationType.Equal, true, null, true)]\n        public void StringMatch_Evaluation_Check_Cases(string value, StringOperationType operation, bool ignoreCase, string input, bool expectedResult)\n        {\n            var context = new RewriteContext { HttpContext = new DefaultHttpContext() };\n            var stringMatch = new StringMatch(value, operation, ignoreCase);\n            var matchResult = stringMatch.Evaluate(input, context);\n            Assert.Equal(expectedResult, matchResult.Success);\n        }\n    }\n}\n"
  },
  {
    "path": "version.props",
    "content": "﻿<Project>\n  <PropertyGroup>\n    <VersionPrefix>3.0.0</VersionPrefix>\n    <VersionSuffix>alpha1</VersionSuffix>\n    <PackageVersion Condition=\"'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' \">$(VersionPrefix)</PackageVersion>\n    <PackageVersion Condition=\"'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' \">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>\n    <BuildNumber Condition=\"'$(BuildNumber)' == ''\">t000</BuildNumber>\n    <FeatureBranchVersionPrefix Condition=\"'$(FeatureBranchVersionPrefix)' == ''\">a-</FeatureBranchVersionPrefix>\n    <VersionSuffix Condition=\"'$(VersionSuffix)' != '' And '$(FeatureBranchVersionSuffix)' != ''\">$(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\\w-]', '-'))</VersionSuffix>\n    <VersionSuffix Condition=\"'$(VersionSuffix)' != '' And '$(BuildNumber)' != ''\">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>\n\n    <ExperimentalVersionPrefix>0.6.0</ExperimentalVersionPrefix>\n    <ExperimentalVersionSuffix>alpha1</ExperimentalVersionSuffix>\n    <ExperimentalPackageVersion Condition=\"'$(IsFinalBuild)' == 'true' AND '$(ExperimentalVersionSuffix)' == 'rtm' \">$(ExperimentalVersionPrefix)</ExperimentalPackageVersion>\n    <ExperimentalPackageVersion Condition=\"'$(IsFinalBuild)' == 'true' AND '$(ExperimentalVersionSuffix)' != 'rtm' \">$(ExperimentalVersionPrefix)-$(ExperimentalVersionSuffix)-final</ExperimentalPackageVersion>\n    <ExperimentalVersionSuffix Condition=\"'$(ExperimentalVersionSuffix)' != '' And '$(BuildNumber)' != ''\">$(ExperimentalVersionSuffix)-$(BuildNumber)</ExperimentalVersionSuffix>\n  </PropertyGroup>\n</Project>\n"
  }
]