├── .appveyor.yml ├── .gitattributes ├── .gitignore ├── .travis.yml ├── .vsts-pipelines └── builds │ ├── ci-internal.yml │ └── ci-public.yml ├── BasicMiddleware.sln ├── CONTRIBUTING.md ├── Directory.Build.props ├── Directory.Build.targets ├── LICENSE.txt ├── NuGet.config ├── NuGetPackageVerifier.json ├── README.md ├── benchmarks └── Microsoft.AspNetCore.ResponseCompression.Benchmarks │ ├── AssemblyInfo.cs │ ├── Microsoft.AspNetCore.ResponseCompression.Benchmarks.csproj │ └── ResponseCompressionProviderBenchmark.cs ├── build.cmd ├── build.sh ├── build ├── Key.snk ├── dependencies.props ├── repo.props └── sources.props ├── korebuild-lock.txt ├── korebuild.json ├── run.cmd ├── run.ps1 ├── run.sh ├── samples ├── HostFilteringSample │ ├── HostFilteringSample.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.Production.json │ └── appsettings.json ├── HttpOverridesSample │ ├── HttpOverridesSample.csproj │ ├── Properties │ │ └── launchSettings.json │ └── Startup.cs ├── HttpsPolicySample │ ├── HttpsPolicySample.csproj │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ └── testCert.pfx ├── ResponseBufferingSample │ ├── Properties │ │ └── launchSettings.json │ ├── ResponseBufferingSample.csproj │ └── Startup.cs ├── ResponseCompressionSample │ ├── CustomCompressionProvider.cs │ ├── LoremIpsum.cs │ ├── Properties │ │ └── launchSettings.json │ ├── ResponseCompressionSample.csproj │ ├── Startup.cs │ └── testfile1kb.txt └── RewriteSample │ ├── Properties │ └── launchSettings.json │ ├── Rewrite.txt │ ├── RewriteSample.csproj │ ├── Startup.cs │ ├── UrlRewrite.xml │ └── testCert.pfx ├── src ├── Directory.Build.props ├── Microsoft.AspNetCore.Buffering │ ├── BufferingWriteStream.cs │ ├── HttpBufferingFeature.cs │ ├── Microsoft.AspNetCore.Buffering.csproj │ ├── ResponseBufferingMiddleware.cs │ ├── ResponseBufferingMiddlewareExtensions.cs │ └── SendFileFeatureWrapper.cs ├── Microsoft.AspNetCore.HostFiltering │ ├── HostFilteringBuilderExtensions.cs │ ├── HostFilteringMiddleware.cs │ ├── HostFilteringOptions.cs │ ├── HostFilteringServicesExtensions.cs │ ├── Microsoft.AspNetCore.HostFiltering.csproj │ └── baseline.netcore.json ├── Microsoft.AspNetCore.HttpOverrides │ ├── ForwardedHeaders.cs │ ├── ForwardedHeadersDefaults.cs │ ├── ForwardedHeadersExtensions.cs │ ├── ForwardedHeadersMiddleware.cs │ ├── ForwardedHeadersOptions.cs │ ├── HttpMethodOverrideExtensions.cs │ ├── HttpMethodOverrideMiddleware.cs │ ├── HttpMethodOverrideOptions.cs │ ├── IPNetwork.cs │ ├── Internal │ │ └── IPEndPointParser.cs │ ├── Microsoft.AspNetCore.HttpOverrides.csproj │ ├── baseline.net45.json │ └── baseline.netcore.json ├── Microsoft.AspNetCore.HttpsPolicy │ ├── HstsBuilderExtensions.cs │ ├── HstsMiddleware.cs │ ├── HstsOptions.cs │ ├── HstsServicesExtensions.cs │ ├── HttpsRedirectionBuilderExtensions.cs │ ├── HttpsRedirectionMiddleware.cs │ ├── HttpsRedirectionOptions.cs │ ├── HttpsRedirectionServicesExtensions.cs │ ├── Microsoft.AspNetCore.HttpsPolicy.csproj │ ├── baseline.netcore.json │ └── internal │ │ ├── HstsLoggingExtensions.cs │ │ └── HttpsLoggingExtensions.cs ├── Microsoft.AspNetCore.ResponseCompression │ ├── BodyWrapperStream.cs │ ├── BrotliCompressionProvider.cs │ ├── BrotliCompressionProviderOptions.cs │ ├── CompressionProviderCollection.cs │ ├── CompressionProviderFactory.cs │ ├── GzipCompressionProvider.cs │ ├── GzipCompressionProviderOptions.cs │ ├── ICompressionProvider.cs │ ├── IResponseCompressionProvider.cs │ ├── Microsoft.AspNetCore.ResponseCompression.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── ResponseCompressionBuilderExtensions.cs │ ├── ResponseCompressionDefaults.cs │ ├── ResponseCompressionMiddleware.cs │ ├── ResponseCompressionOptions.cs │ ├── ResponseCompressionProvider.cs │ ├── ResponseCompressionServicesExtensions.cs │ ├── baseline.netcore.json │ ├── baseline.netframework.json │ └── internal │ │ └── ResponseCompressionLoggingExtensions.cs └── Microsoft.AspNetCore.Rewrite │ ├── ApacheModRewriteOptionsExtensions.cs │ ├── Extensions │ └── RewriteMiddlewareLoggingExtensions.cs │ ├── IISUrlRewriteOptionsExtensions.cs │ ├── IRule.cs │ ├── Internal │ ├── ApacheModRewrite │ │ ├── ApacheModRewriteRule.cs │ │ ├── Condition.cs │ │ ├── ConditionEvaluator.cs │ │ ├── ConditionPatternParser.cs │ │ ├── ConditionType.cs │ │ ├── CookieActionFactory.cs │ │ ├── FileParser.cs │ │ ├── FlagParser.cs │ │ ├── FlagType.cs │ │ ├── Flags.cs │ │ ├── OperationType.cs │ │ ├── ParsedModRewriteCondition.cs │ │ ├── RuleBuilder.cs │ │ ├── RuleRegexParser.cs │ │ ├── SegmentType.cs │ │ ├── ServerVariables.cs │ │ ├── TestStringParser.cs │ │ └── Tokenizer.cs │ ├── BackReferenceCollection.cs │ ├── DelegateRule.cs │ ├── IISUrlRewrite │ │ ├── ActionType.cs │ │ ├── Condition.cs │ │ ├── ConditionCollection.cs │ │ ├── ConditionEvaluator.cs │ │ ├── IISRewriteMap.cs │ │ ├── IISRewriteMapCollection.cs │ │ ├── IISUrlRewriteRule.cs │ │ ├── InputParser.cs │ │ ├── InvalidUrlRewriteFormatException.cs │ │ ├── LogicalGrouping.cs │ │ ├── MatchType.cs │ │ ├── PatternSyntax.cs │ │ ├── RedirectType.cs │ │ ├── RewriteMapParser.cs │ │ ├── RewriteTags.cs │ │ ├── ServerVariables.cs │ │ ├── UriMatchCondition.cs │ │ ├── UriMatchPart.cs │ │ ├── UrlRewriteFileParser.cs │ │ └── UrlRewriteRuleBuilder.cs │ ├── MatchResults.cs │ ├── ParserContext.cs │ ├── Pattern.cs │ ├── PatternSegment.cs │ ├── PatternSegments │ │ ├── ConditionMatchSegment.cs │ │ ├── DateTimeSegment.cs │ │ ├── HeaderSegment.cs │ │ ├── IsHttpsModSegment.cs │ │ ├── IsHttpsUrlSegment.cs │ │ ├── IsIPV6Segment.cs │ │ ├── LiteralSegment.cs │ │ ├── LocalAddressSegment.cs │ │ ├── LocalPortSegment.cs │ │ ├── QueryStringSegment.cs │ │ ├── RemoteAddressSegment.cs │ │ ├── RemotePortSegment.cs │ │ ├── RequestFilenameSegment.cs │ │ ├── RequestMethodSegment.cs │ │ ├── RewriteMapSegment.cs │ │ ├── RuleMatchSegment.cs │ │ ├── SchemeSegment.cs │ │ ├── ServerProtocolSegment.cs │ │ ├── ToLowerSegment.cs │ │ ├── UrlEncodeSegment.cs │ │ └── UrlSegment.cs │ ├── RedirectRule.cs │ ├── RedirectToHttpsRule.cs │ ├── RedirectToWwwRule.cs │ ├── RewriteRule.cs │ ├── UrlAction.cs │ ├── UrlActions │ │ ├── AbortAction.cs │ │ ├── ChangeCookieAction.cs │ │ ├── CustomResponseAction.cs │ │ ├── ForbiddenAction.cs │ │ ├── GoneAction.cs │ │ ├── NoneAction.cs │ │ ├── RedirectAction.cs │ │ └── RewriteAction.cs │ ├── UrlMatch.cs │ └── UrlMatches │ │ ├── ExactMatch.cs │ │ ├── FileSizeMatch.cs │ │ ├── IntegerMatch.cs │ │ ├── IntegerOperation.cs │ │ ├── IsDirectoryMatch.cs │ │ ├── IsFileMatch.cs │ │ ├── RegexMatch.cs │ │ ├── StringMatch.cs │ │ └── StringOperation.cs │ ├── Microsoft.AspNetCore.Rewrite.csproj │ ├── Properties │ ├── AssemblyInfo.cs │ └── Resources.Designer.cs │ ├── Resources.resx │ ├── RewriteBuilderExtensions.cs │ ├── RewriteContext.cs │ ├── RewriteMiddleware.cs │ ├── RewriteOptions.cs │ ├── RewriteOptionsExtensions.cs │ ├── RuleResult.cs │ └── baseline.netcore.json ├── test ├── Directory.Build.props ├── Microsoft.AspNetCore.Buffering.Tests │ ├── Microsoft.AspNetCore.Buffering.Tests.csproj │ └── ResponseBufferingMiddlewareTests.cs ├── Microsoft.AspNetCore.HostFiltering.Tests │ ├── HostFilteringMiddlewareTests.cs │ └── Microsoft.AspNetCore.HostFiltering.Tests.csproj ├── Microsoft.AspNetCore.HttpOverrides.Tests │ ├── ForwardedHeadersMiddlewareTest.cs │ ├── HttpMethodOverrideMiddlewareTest.cs │ ├── IPEndPointParserTest.cs │ ├── IPNetworkTest.cs │ └── Microsoft.AspNetCore.HttpOverrides.Tests.csproj ├── Microsoft.AspNetCore.HttpsPolicy.Tests │ ├── HstsMiddlewareTests.cs │ ├── HttpsPolicyTests.cs │ ├── HttpsRedirectionMiddlewareTests.cs │ └── Microsoft.AspNetCore.HttpsPolicy.Tests.csproj ├── Microsoft.AspNetCore.ResponseCompression.Tests │ ├── BodyWrapperStreamTests.cs │ ├── Microsoft.AspNetCore.ResponseCompression.Tests.csproj │ ├── ResponseCompressionMiddlewareTest.cs │ └── testfile1kb.txt └── Microsoft.AspNetCore.Rewrite.Tests │ ├── ApacheModRewrite │ ├── ConditionPatternParserTest.cs │ ├── CookieActionFactoryTest.cs │ ├── FlagParserTest.cs │ ├── FormatExceptionTests.cs │ ├── ModRewriteMiddlewareTest.cs │ ├── RewriteTokenizerTest.cs │ ├── RuleBuilderTest.cs │ ├── RuleRegexParserTest.cs │ └── TestStringParserTests.cs │ ├── IISUrlRewrite │ ├── FileParserTests.cs │ ├── FormatExceptionHandlingTests.cs │ ├── InputParserTests.cs │ ├── InvalidUrlRewriteFormatExceptionHandlingTests.cs │ ├── MiddleWareTests.cs │ ├── RewriteMapParserTests.cs │ ├── ServerVariableTests.cs │ └── UrlRewriteApplicationTests.cs │ ├── Microsoft.AspNetCore.Rewrite.Tests.csproj │ ├── MiddlewareTests.cs │ ├── PatternSegments │ ├── ConditionMatchSegmentTests.cs │ ├── DateTimeSegmentTests.cs │ ├── HeaderSegmentTests.cs │ ├── IsHttpsModSegmentTests.cs │ ├── IsHttpsSegmentTests.cs │ ├── IsIPV6SegmentTests.cs │ ├── LIteralSegmentTests.cs │ ├── LocalAddressSegmentTests.cs │ ├── LocalPortSegmentTests.cs │ ├── QueryStringSegmentTests.cs │ ├── RemoteAddressSegmentTests.cs │ ├── RemotePortSegmentTests.cs │ ├── RequestFilenameSegmentTests.cs │ ├── RequestMethodSegmentTests.cs │ ├── RuleMatchSegmentTests.cs │ ├── SchemeSegmentTests.cs │ ├── ServerProtocolSegmentTests.cs │ ├── ToLowerSegmentTests.cs │ ├── UrlEncodeSegmentTests.cs │ └── UrlSegmentTests.cs │ ├── UrlActions │ ├── AbortActionTests.cs │ ├── ChangeCookieActionTests.cs │ ├── ForbiddenActionTests.cs │ └── GoneActionTests.cs │ └── UrlMatches │ ├── ExactMatchTests.cs │ ├── IntegerMatchTests.cs │ └── StringMatchTests.cs └── version.props /.appveyor.yml: -------------------------------------------------------------------------------- 1 | init: 2 | - git config --global core.autocrlf true 3 | branches: 4 | only: 5 | - master 6 | - /^release\/.*$/ 7 | - /^(.*\/)?ci-.*$/ 8 | build_script: 9 | - ps: .\run.ps1 default-build 10 | clone_depth: 1 11 | environment: 12 | global: 13 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 14 | DOTNET_CLI_TELEMETRY_OPTOUT: 1 15 | test: 'off' 16 | deploy: 'off' 17 | os: Visual Studio 2017 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | 12 | *.jpg binary 13 | *.png binary 14 | *.gif binary 15 | 16 | *.cs text=auto diff=csharp 17 | *.vb text=auto 18 | *.resx text=auto 19 | *.c text=auto 20 | *.cpp text=auto 21 | *.cxx text=auto 22 | *.h text=auto 23 | *.hxx text=auto 24 | *.py text=auto 25 | *.rb text=auto 26 | *.java text=auto 27 | *.html text=auto 28 | *.htm text=auto 29 | *.css text=auto 30 | *.scss text=auto 31 | *.sass text=auto 32 | *.less text=auto 33 | *.js text=auto 34 | *.lisp text=auto 35 | *.clj text=auto 36 | *.sql text=auto 37 | *.php text=auto 38 | *.lua text=auto 39 | *.m text=auto 40 | *.asm text=auto 41 | *.erl text=auto 42 | *.fs text=auto 43 | *.fsx text=auto 44 | *.hs text=auto 45 | 46 | *.csproj text=auto 47 | *.vbproj text=auto 48 | *.fsproj text=auto 49 | *.dbproj text=auto 50 | *.sln text=auto eol=crlf 51 | *.sh eol=lf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj/ 2 | [Bb]in/ 3 | TestResults/ 4 | .nuget/ 5 | *.sln.ide/ 6 | _ReSharper.*/ 7 | packages/ 8 | artifacts/ 9 | PublishProfiles/ 10 | *.user 11 | *.suo 12 | *.cache 13 | *.docstates 14 | _ReSharper.* 15 | nuget.exe 16 | project.lock.json 17 | *net45.csproj 18 | *net451.csproj 19 | *k10.csproj 20 | *.psess 21 | *.vsp 22 | *.pidb 23 | *.userprefs 24 | *DS_Store 25 | *.ncrunchsolution 26 | *.*sdf 27 | *.ipch 28 | .vs/ 29 | .build/ 30 | .testPublish/ 31 | .idea/ 32 | .vscode/ 33 | *.nuget.props 34 | *.nuget.targets 35 | global.json 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | sudo: false 3 | dist: trusty 4 | env: 5 | global: 6 | - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true 7 | - DOTNET_CLI_TELEMETRY_OPTOUT: 1 8 | mono: none 9 | os: 10 | - linux 11 | - osx 12 | osx_image: xcode8.2 13 | addons: 14 | apt: 15 | packages: 16 | - libunwind8 17 | branches: 18 | only: 19 | - master 20 | - /^release\/.*$/ 21 | - /^(.*\/)?ci-.*$/ 22 | before_install: 23 | - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s 24 | /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 25 | /usr/local/lib/; fi 26 | script: 27 | - ./build.sh 28 | -------------------------------------------------------------------------------- /.vsts-pipelines/builds/ci-internal.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | - release/* 4 | 5 | resources: 6 | repositories: 7 | - repository: buildtools 8 | type: git 9 | name: aspnet-BuildTools 10 | ref: refs/heads/master 11 | 12 | phases: 13 | - template: .vsts-pipelines/templates/project-ci.yml@buildtools 14 | -------------------------------------------------------------------------------- /.vsts-pipelines/builds/ci-public.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | - release/* 4 | 5 | # See https://github.com/aspnet/BuildTools 6 | resources: 7 | repositories: 8 | - repository: buildtools 9 | type: github 10 | endpoint: DotNet-Bot GitHub Connection 11 | name: aspnet/BuildTools 12 | ref: refs/heads/master 13 | 14 | phases: 15 | - template: .vsts-pipelines/templates/project-ci.yml@buildtools 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ====== 3 | 4 | Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo. 5 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Microsoft ASP.NET Core 12 | https://github.com/aspnet/BasicMiddleware 13 | git 14 | $(MSBuildThisFileDirectory) 15 | $(MSBuildThisFileDirectory)build\Key.snk 16 | true 17 | true 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | $(MicrosoftNETCoreApp21PackageVersion) 4 | $(MicrosoftNETCoreApp22PackageVersion) 5 | $(NETStandardLibrary20PackageVersion) 6 | 7 | 99.9 8 | 9 | 10 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NuGetPackageVerifier.json: -------------------------------------------------------------------------------- 1 | { 2 | "Default": { 3 | "rules": [ 4 | "DefaultCompositeRule" 5 | ] 6 | } 7 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ASP.NET Core Basic Middleware Components [Archived] 2 | =================================================== 3 | 4 | **This GitHub project has been archived.** Ongoing development on this project can be found in . 5 | 6 | This repo hosts a collection of basic middleware components for ASP.NET Core. This includes Buffering, HTTP Overrides, Response Compression, and URL Rewriting. 7 | The Rewrite middleware can import rules from IIS's UrlRewrite and Apache's mod_rewrite. 8 | 9 | This 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. 10 | -------------------------------------------------------------------------------- /benchmarks/Microsoft.AspNetCore.ResponseCompression.Benchmarks/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | [assembly: BenchmarkDotNet.Attributes.AspNetCoreBenchmark] 5 | -------------------------------------------------------------------------------- /benchmarks/Microsoft.AspNetCore.ResponseCompression.Benchmarks/Microsoft.AspNetCore.ResponseCompression.Benchmarks.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp2.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /benchmarks/Microsoft.AspNetCore.ResponseCompression.Benchmarks/ResponseCompressionProviderBenchmark.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | using BenchmarkDotNet.Attributes; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Options; 10 | using Microsoft.Net.Http.Headers; 11 | 12 | namespace Microsoft.AspNetCore.ResponseCompression.Benchmarks 13 | { 14 | public class ResponseCompressionProviderBenchmark 15 | { 16 | [GlobalSetup] 17 | public void GlobalSetup() 18 | { 19 | var services = new ServiceCollection() 20 | .AddOptions() 21 | .AddResponseCompression() 22 | .BuildServiceProvider(); 23 | 24 | var options = new ResponseCompressionOptions(); 25 | 26 | Provider = new ResponseCompressionProvider(services, Options.Create(options)); 27 | } 28 | 29 | [ParamsSource(nameof(EncodingStrings))] 30 | public string AcceptEncoding { get; set; } 31 | 32 | public static IEnumerable EncodingStrings() 33 | { 34 | return new[] 35 | { 36 | "gzip;q=0.8, compress;q=0.6, br;q=0.4", 37 | "gzip, compress, br", 38 | "br, compress, gzip", 39 | "gzip, compress", 40 | "identity", 41 | "*" 42 | }; 43 | } 44 | 45 | public ResponseCompressionProvider Provider { get; set; } 46 | 47 | [Benchmark] 48 | public ICompressionProvider GetCompressionProvider() 49 | { 50 | var context = new DefaultHttpContext(); 51 | 52 | context.Request.Headers[HeaderNames.AcceptEncoding] = AcceptEncoding; 53 | 54 | return Provider.GetCompressionProvider(context); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE" 3 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | # Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs) 7 | chmod +x "$DIR/run.sh"; sync 8 | "$DIR/run.sh" default-build "$@" 9 | -------------------------------------------------------------------------------- /build/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/BasicMiddleware/87d4df52fa20be378bcd6c15f0eacb972fbac481/build/Key.snk -------------------------------------------------------------------------------- /build/repo.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Internal.AspNetCore.Universe.Lineup 7 | https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /build/sources.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $(DotNetRestoreSources) 6 | 7 | $(RestoreSources); 8 | https://dotnet.myget.org/F/dotnet-core/api/v3/index.json; 9 | https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; 10 | https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; 11 | 12 | 13 | $(RestoreSources); 14 | https://api.nuget.org/v3/index.json; 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /korebuild-lock.txt: -------------------------------------------------------------------------------- 1 | version:3.0.0-alpha1-20181011.3 2 | commithash:e7569d931e994629267ab2646e9926140962b4ac 3 | -------------------------------------------------------------------------------- /korebuild.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json", 3 | "channel": "master" 4 | } 5 | -------------------------------------------------------------------------------- /run.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE" 3 | -------------------------------------------------------------------------------- /samples/HostFilteringSample/HostFilteringSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2;net461 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | PreserveNewest 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /samples/HostFilteringSample/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace HostFilteringSample 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | BuildWebHost(args).Run(); 15 | } 16 | 17 | public static IWebHost BuildWebHost(string[] args) 18 | { 19 | var hostBuilder = new WebHostBuilder() 20 | .ConfigureLogging((_, factory) => 21 | { 22 | factory.SetMinimumLevel(LogLevel.Debug); 23 | factory.AddConsole(); 24 | }) 25 | .ConfigureAppConfiguration((hostingContext, config) => 26 | { 27 | var env = hostingContext.HostingEnvironment; 28 | config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 29 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); 30 | }) 31 | .UseKestrel() 32 | .UseStartup(); 33 | 34 | return hostBuilder.Build(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /samples/HostFilteringSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:14124/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "HostFilteringSample": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:14125/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /samples/HostFilteringSample/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.HostFiltering; 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.AspNetCore.Http; 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Options; 13 | 14 | namespace HostFilteringSample 15 | { 16 | public class Startup 17 | { 18 | public IConfiguration Config { get; } 19 | 20 | public Startup(IConfiguration config) 21 | { 22 | Config = config; 23 | } 24 | 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | services.AddHostFiltering(options => 28 | { 29 | 30 | }); 31 | 32 | // Fallback 33 | services.PostConfigure(options => 34 | { 35 | if (options.AllowedHosts == null || options.AllowedHosts.Count == 0) 36 | { 37 | // "AllowedHosts": "localhost;127.0.0.1;[::1]" 38 | var hosts = Config["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); 39 | // Fall back to "*" to disable. 40 | options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" }); 41 | } 42 | }); 43 | // Change notification 44 | services.AddSingleton>(new ConfigurationChangeTokenSource(Config)); 45 | } 46 | 47 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) 48 | { 49 | app.UseHostFiltering(); 50 | 51 | app.Run(context => 52 | { 53 | return context.Response.WriteAsync("Hello World! " + context.Request.Host); 54 | }); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /samples/HostFilteringSample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "AllowedHosts": "localhost;127.0.0.1;[::1]" 3 | } 4 | -------------------------------------------------------------------------------- /samples/HostFilteringSample/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "AllowedHosts": "example.com;localhost" 3 | } 4 | -------------------------------------------------------------------------------- /samples/HostFilteringSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /samples/HttpOverridesSample/HttpOverridesSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2;net461 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/HttpOverridesSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:1658/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "web": { 19 | "commandName": "web", 20 | "environmentVariables": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /samples/HttpOverridesSample/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.AspNetCore.HttpOverrides; 5 | 6 | namespace HttpOverridesSample 7 | { 8 | public class Startup 9 | { 10 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 11 | public void Configure(IApplicationBuilder app) 12 | { 13 | app.UseForwardedHeaders(new ForwardedHeadersOptions 14 | { 15 | ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto 16 | }); 17 | app.UseHttpMethodOverride(); 18 | 19 | app.Run(async (context) => 20 | { 21 | foreach (var header in context.Request.Headers) 22 | { 23 | await context.Response.WriteAsync($"{header.Key}: {header.Value}\r\n"); 24 | } 25 | await context.Response.WriteAsync($"Method: {context.Request.Method}\r\n"); 26 | await context.Response.WriteAsync($"Scheme: {context.Request.Scheme}\r\n"); 27 | await context.Response.WriteAsync($"RemoteIP: {context.Connection.RemoteIpAddress}\r\n"); 28 | await context.Response.WriteAsync($"RemotePort: {context.Connection.RemotePort}\r\n"); 29 | }); 30 | } 31 | 32 | // Entry point for the application. 33 | public static void Main(string[] args) 34 | { 35 | var host = new WebHostBuilder() 36 | .UseKestrel() 37 | // .UseIIS() // This repo can no longer reference IIS because IISIntegration depends on it. 38 | .UseStartup() 39 | .Build(); 40 | 41 | host.Run(); 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /samples/HttpsPolicySample/HttpsPolicySample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net461;netcoreapp2.2 5 | netcoreapp2.2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/HttpsPolicySample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:31894/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "HttpsSample": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:5000/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /samples/HttpsPolicySample/testCert.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/BasicMiddleware/87d4df52fa20be378bcd6c15f0eacb972fbac481/samples/HttpsPolicySample/testCert.pfx -------------------------------------------------------------------------------- /samples/ResponseBufferingSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:49657/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNET_ENV": "Development" 16 | } 17 | }, 18 | "web": { 19 | "commandName": "web", 20 | "environmentVariables": { 21 | "Hosting:Environment": "Development" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /samples/ResponseBufferingSample/ResponseBufferingSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2;net461 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/ResponseBufferingSample/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace ResponseBufferingSample 7 | { 8 | public class Startup 9 | { 10 | // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 11 | public void ConfigureServices(IServiceCollection services) 12 | { 13 | } 14 | 15 | public void Configure(IApplicationBuilder app) 16 | { 17 | app.UseResponseBuffering(); 18 | app.Run(async (context) => 19 | { 20 | // Write some stuff 21 | context.Response.ContentType = "text/other"; 22 | await context.Response.WriteAsync("Hello World!"); 23 | 24 | // ... more work ... 25 | 26 | // Something went wrong and we want to replace the response 27 | context.Response.StatusCode = 200; 28 | context.Response.Headers.Clear(); 29 | context.Response.Body.SetLength(0); 30 | 31 | // Try again 32 | context.Response.ContentType = "text/plain"; 33 | await context.Response.WriteAsync("Hi Bob!"); 34 | }); 35 | } 36 | 37 | // Entry point for the application. 38 | public static void Main(string[] args) 39 | { 40 | var host = new WebHostBuilder() 41 | .UseKestrel() 42 | // .UseIIS() // This repo can no longer reference IIS because IISIntegration depends on it. 43 | .UseStartup() 44 | .Build(); 45 | 46 | host.Run(); 47 | } 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /samples/ResponseCompressionSample/CustomCompressionProvider.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Microsoft.AspNetCore.ResponseCompression; 3 | 4 | namespace ResponseCompressionSample 5 | { 6 | public class CustomCompressionProvider : ICompressionProvider 7 | { 8 | public string EncodingName => "custom"; 9 | 10 | public bool SupportsFlush => true; 11 | 12 | public Stream CreateStream(Stream outputStream) 13 | { 14 | // Create a custom compression stream wrapper here 15 | return outputStream; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/ResponseCompressionSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:6164/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "ResponseCompressionSample": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "launchUrl": "http://localhost:5000/", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /samples/ResponseCompressionSample/ResponseCompressionSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2;net461 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /samples/ResponseCompressionSample/testfile1kb.txt: -------------------------------------------------------------------------------- 1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -------------------------------------------------------------------------------- /samples/RewriteSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:6156/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "RewriteSample": { 19 | "commandName": "Project" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /samples/RewriteSample/Rewrite.txt: -------------------------------------------------------------------------------- 1 | # Rewrite path with additional sub directory 2 | RewriteCond %{HTTP_HOST} !^www\.example\.com [NC,OR] 3 | RewriteCond %{SERVER_PORT} !^5000$ 4 | RewriteRule ^/(.*) http://www.example.com/$1 [L,R=302] -------------------------------------------------------------------------------- /samples/RewriteSample/RewriteSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.2;net461 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/RewriteSample/UrlRewrite.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /samples/RewriteSample/testCert.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnet/BasicMiddleware/87d4df52fa20be378bcd6c15f0eacb972fbac481/samples/RewriteSample/testCert.pfx -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Buffering/HttpBufferingFeature.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http.Features; 5 | 6 | namespace Microsoft.AspNetCore.Buffering 7 | { 8 | internal class HttpBufferingFeature : IHttpBufferingFeature 9 | { 10 | private readonly BufferingWriteStream _buffer; 11 | private readonly IHttpBufferingFeature _innerFeature; 12 | 13 | internal HttpBufferingFeature(BufferingWriteStream buffer, IHttpBufferingFeature innerFeature) 14 | { 15 | _buffer = buffer; 16 | _innerFeature = innerFeature; 17 | } 18 | 19 | public void DisableRequestBuffering() 20 | { 21 | _innerFeature?.DisableRequestBuffering(); 22 | } 23 | 24 | public void DisableResponseBuffering() 25 | { 26 | _buffer.DisableBuffering(); 27 | _innerFeature?.DisableResponseBuffering(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Buffering/Microsoft.AspNetCore.Buffering.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(ExperimentalVersionPrefix) 5 | $(ExperimentalVersionSuffix) 6 | false 7 | $(ExperimentalPackageVersion) 8 | ASP.NET Core middleware for buffering response bodies. 9 | netstandard2.0 10 | $(NoWarn);CS1591 11 | true 12 | aspnetcore;buffer;buffering 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Buffering/ResponseBufferingMiddlewareExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Buffering; 5 | 6 | namespace Microsoft.AspNetCore.Builder 7 | { 8 | public static class ResponseBufferingMiddlewareExtensions 9 | { 10 | /// 11 | /// Enables full buffering of response bodies. This can be disabled on a per request basis using IHttpBufferingFeature. 12 | /// 13 | /// 14 | /// 15 | public static IApplicationBuilder UseResponseBuffering(this IApplicationBuilder builder) 16 | { 17 | return builder.UseMiddleware(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Buffering/SendFileFeatureWrapper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Http.Features; 7 | 8 | namespace Microsoft.AspNetCore.Buffering 9 | { 10 | internal class SendFileFeatureWrapper : IHttpSendFileFeature 11 | { 12 | private readonly IHttpSendFileFeature _originalSendFileFeature; 13 | private readonly BufferingWriteStream _bufferStream; 14 | 15 | public SendFileFeatureWrapper(IHttpSendFileFeature originalSendFileFeature, BufferingWriteStream bufferStream) 16 | { 17 | _originalSendFileFeature = originalSendFileFeature; 18 | _bufferStream = bufferStream; 19 | } 20 | 21 | // Flush and disable the buffer if anyone tries to call the SendFile feature. 22 | public async Task SendFileAsync(string path, long offset, long? length, CancellationToken cancellation) 23 | { 24 | await _bufferStream.DisableBufferingAsync(cancellation); 25 | await _originalSendFileFeature.SendFileAsync(path, offset, length, cancellation); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HostFiltering/HostFilteringBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.HostFiltering; 6 | 7 | namespace Microsoft.AspNetCore.Builder 8 | { 9 | /// 10 | /// Extension methods for the HostFiltering middleware. 11 | /// 12 | public static class HostFilteringBuilderExtensions 13 | { 14 | /// 15 | /// Adds middleware for filtering requests by allowed host headers. Invalid requests will be rejected with a 16 | /// 400 status code. 17 | /// 18 | /// The instance this method extends. 19 | /// The original . 20 | public static IApplicationBuilder UseHostFiltering(this IApplicationBuilder app) 21 | { 22 | if (app == null) 23 | { 24 | throw new ArgumentNullException(nameof(app)); 25 | } 26 | 27 | app.UseMiddleware(); 28 | 29 | return app; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HostFiltering/HostFilteringServicesExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.HostFiltering; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace Microsoft.AspNetCore.Builder 9 | { 10 | /// 11 | /// Extension methods for the host filtering middleware. 12 | /// 13 | public static class HostFilteringServicesExtensions 14 | { 15 | /// 16 | /// Adds services and options for the host filtering middleware. 17 | /// 18 | /// The for adding services. 19 | /// A delegate to configure the . 20 | /// 21 | public static IServiceCollection AddHostFiltering(this IServiceCollection services, Action configureOptions) 22 | { 23 | if (services == null) 24 | { 25 | throw new ArgumentNullException(nameof(services)); 26 | } 27 | if (configureOptions == null) 28 | { 29 | throw new ArgumentNullException(nameof(configureOptions)); 30 | } 31 | 32 | services.Configure(configureOptions); 33 | return services; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HostFiltering/Microsoft.AspNetCore.HostFiltering.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ASP.NET Core middleware for filtering out requests with unknown HTTP host headers. 6 | 7 | netstandard2.0 8 | true 9 | aspnetcore 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpOverrides/ForwardedHeaders.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.AspNetCore.HttpOverrides 7 | { 8 | [Flags] 9 | public enum ForwardedHeaders 10 | { 11 | None = 0, 12 | XForwardedFor = 1 << 0, 13 | XForwardedHost = 1 << 1, 14 | XForwardedProto = 1 << 2, 15 | All = XForwardedFor | XForwardedHost | XForwardedProto 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpOverrides/ForwardedHeadersDefaults.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.HttpOverrides 5 | { 6 | /// 7 | /// Default values related to middleware 8 | /// 9 | /// 10 | public static class ForwardedHeadersDefaults 11 | { 12 | /// 13 | /// X-Forwarded-For 14 | /// 15 | public static string XForwardedForHeaderName { get; } = "X-Forwarded-For"; 16 | 17 | /// 18 | /// X-Forwarded-Host 19 | /// 20 | public static string XForwardedHostHeaderName { get; } = "X-Forwarded-Host"; 21 | 22 | /// 23 | /// X-Forwarded-Proto 24 | /// 25 | public static string XForwardedProtoHeaderName { get; } = "X-Forwarded-Proto"; 26 | 27 | /// 28 | /// X-Original-For 29 | /// 30 | public static string XOriginalForHeaderName { get; } = "X-Original-For"; 31 | 32 | /// 33 | /// X-Original-Host 34 | /// 35 | public static string XOriginalHostHeaderName { get; } = "X-Original-Host"; 36 | 37 | /// 38 | /// X-Original-Proto 39 | /// 40 | public static string XOriginalProtoHeaderName { get; } = "X-Original-Proto"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpOverrides/ForwardedHeadersExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.HttpOverrides; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Microsoft.AspNetCore.Builder 9 | { 10 | public static class ForwardedHeadersExtensions 11 | { 12 | /// 13 | /// Forwards proxied headers onto current request 14 | /// 15 | /// 16 | /// 17 | public static IApplicationBuilder UseForwardedHeaders(this IApplicationBuilder builder) 18 | { 19 | if (builder == null) 20 | { 21 | throw new ArgumentNullException(nameof(builder)); 22 | } 23 | 24 | return builder.UseMiddleware(); 25 | } 26 | 27 | /// 28 | /// Forwards proxied headers onto current request 29 | /// 30 | /// 31 | /// Enables the different forwarding options. 32 | /// 33 | public static IApplicationBuilder UseForwardedHeaders(this IApplicationBuilder builder, ForwardedHeadersOptions options) 34 | { 35 | if (builder == null) 36 | { 37 | throw new ArgumentNullException(nameof(builder)); 38 | } 39 | if (options == null) 40 | { 41 | throw new ArgumentNullException(nameof(options)); 42 | } 43 | 44 | return builder.UseMiddleware(Options.Create(options)); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpOverrides/HttpMethodOverrideExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.HttpOverrides; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Microsoft.AspNetCore.Builder 9 | { 10 | public static class HttpMethodOverrideExtensions 11 | { 12 | /// 13 | /// Allows incoming POST request to override method type with type specified in header. 14 | /// 15 | /// The instance this method extends. 16 | public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder) 17 | { 18 | if (builder == null) 19 | { 20 | throw new ArgumentNullException(nameof(builder)); 21 | } 22 | 23 | return builder.UseMiddleware(); 24 | } 25 | 26 | /// 27 | /// Allows incoming POST request to override method type with type specified in form. 28 | /// 29 | /// The instance this method extends. 30 | /// The . 31 | public static IApplicationBuilder UseHttpMethodOverride(this IApplicationBuilder builder, HttpMethodOverrideOptions options) 32 | { 33 | if (builder == null) 34 | { 35 | throw new ArgumentNullException(nameof(builder)); 36 | } 37 | if (options == null) 38 | { 39 | throw new ArgumentNullException(nameof(options)); 40 | } 41 | 42 | return builder.UseMiddleware(Options.Create(options)); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpOverrides/HttpMethodOverrideOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Builder 5 | { 6 | public class HttpMethodOverrideOptions 7 | { 8 | /// 9 | /// Denotes the form element that contains the name of the resulting method type. 10 | /// If not set the X-Http-Method-Override header will be used. 11 | /// 12 | public string FormFieldName { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpOverrides/IPNetwork.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Net; 5 | 6 | namespace Microsoft.AspNetCore.HttpOverrides 7 | { 8 | public class IPNetwork 9 | { 10 | public IPNetwork(IPAddress prefix, int prefixLength) 11 | { 12 | Prefix = prefix; 13 | PrefixLength = prefixLength; 14 | PrefixBytes = Prefix.GetAddressBytes(); 15 | Mask = CreateMask(); 16 | } 17 | 18 | public IPAddress Prefix { get; } 19 | 20 | private byte[] PrefixBytes { get; } 21 | 22 | /// 23 | /// The CIDR notation of the subnet mask 24 | /// 25 | public int PrefixLength { get; } 26 | 27 | private byte[] Mask { get; } 28 | 29 | public bool Contains(IPAddress address) 30 | { 31 | if (Prefix.AddressFamily != address.AddressFamily) 32 | { 33 | return false; 34 | } 35 | 36 | var addressBytes = address.GetAddressBytes(); 37 | for (int i = 0; i < PrefixBytes.Length && Mask[i] != 0; i++) 38 | { 39 | if (PrefixBytes[i] != (addressBytes[i] & Mask[i])) 40 | { 41 | return false; 42 | } 43 | } 44 | 45 | return true; 46 | } 47 | 48 | private byte[] CreateMask() 49 | { 50 | var mask = new byte[PrefixBytes.Length]; 51 | int remainingBits = PrefixLength; 52 | int i = 0; 53 | while (remainingBits >= 8) 54 | { 55 | mask[i] = 0xFF; 56 | i++; 57 | remainingBits -= 8; 58 | } 59 | if (remainingBits > 0) 60 | { 61 | mask[i] = (byte)(0xFF << (8 - remainingBits)); 62 | } 63 | 64 | return mask; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpOverrides/Microsoft.AspNetCore.HttpOverrides.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ASP.NET Core basic middleware for supporting HTTP method overrides. Includes: 5 | * X-Forwarded-* headers to forward headers from a proxy. 6 | * HTTP method override header. 7 | netstandard2.0 8 | $(NoWarn);CS1591 9 | true 10 | aspnetcore;proxy;headers;xforwarded 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpsPolicy/HstsBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.HttpsPolicy; 7 | using Microsoft.Extensions.Options; 8 | 9 | namespace Microsoft.AspNetCore.Builder 10 | { 11 | /// 12 | /// Extension methods for the HSTS middleware. 13 | /// 14 | public static class HstsBuilderExtensions 15 | { 16 | /// 17 | /// Adds middleware for using HSTS, which adds the Strict-Transport-Security header. 18 | /// 19 | /// The instance this method extends. 20 | public static IApplicationBuilder UseHsts(this IApplicationBuilder app) 21 | { 22 | if (app == null) 23 | { 24 | throw new ArgumentNullException(nameof(app)); 25 | } 26 | 27 | return app.UseMiddleware(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpsPolicy/HstsOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.AspNetCore.HttpsPolicy 8 | { 9 | /// 10 | /// Options for the Hsts Middleware 11 | /// 12 | public class HstsOptions 13 | { 14 | /// 15 | /// Sets the max-age parameter of the Strict-Transport-Security header. 16 | /// 17 | /// 18 | /// Max-age is required; defaults to 30 days. 19 | /// See: https://tools.ietf.org/html/rfc6797#section-6.1.1 20 | /// 21 | public TimeSpan MaxAge { get; set; } = TimeSpan.FromDays(30); 22 | 23 | /// 24 | /// Enables includeSubDomain parameter of the Strict-Transport-Security header. 25 | /// 26 | /// 27 | /// See: https://tools.ietf.org/html/rfc6797#section-6.1.2 28 | /// 29 | public bool IncludeSubDomains { get; set; } 30 | 31 | /// 32 | /// Sets the preload parameter of the Strict-Transport-Security header. 33 | /// 34 | /// 35 | /// Preload is not part of the RFC specification, but is supported by web browsers 36 | /// to preload HSTS sites on fresh install. See https://hstspreload.org/. 37 | /// 38 | public bool Preload { get; set; } 39 | 40 | /// 41 | /// A list of host names that will not add the HSTS header. 42 | /// 43 | public IList ExcludedHosts { get; } = new List 44 | { 45 | "localhost", 46 | "127.0.0.1", // ipv4 47 | "[::1]" // ipv6 48 | }; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpsPolicy/HstsServicesExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.HttpsPolicy; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace Microsoft.AspNetCore.Builder 9 | { 10 | /// 11 | /// Extension methods for the HSTS middleware. 12 | /// 13 | public static class HstsServicesExtensions 14 | { 15 | /// 16 | /// Adds HSTS services. 17 | /// 18 | /// The for adding services. 19 | /// A delegate to configure the . 20 | /// 21 | public static IServiceCollection AddHsts(this IServiceCollection services, Action configureOptions) 22 | { 23 | if (services == null) 24 | { 25 | throw new ArgumentNullException(nameof(services)); 26 | } 27 | if (configureOptions == null) 28 | { 29 | throw new ArgumentNullException(nameof(configureOptions)); 30 | } 31 | 32 | services.Configure(configureOptions); 33 | return services; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpsPolicy/HttpsRedirectionBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.AspNetCore.Hosting.Server.Features; 7 | using Microsoft.AspNetCore.HttpsPolicy; 8 | 9 | namespace Microsoft.AspNetCore.Builder 10 | { 11 | /// 12 | /// Extension methods for the HttpsRedirection middleware. 13 | /// 14 | public static class HttpsPolicyBuilderExtensions 15 | { 16 | /// 17 | /// Adds middleware for redirecting HTTP Requests to HTTPS. 18 | /// 19 | /// The instance this method extends. 20 | /// The for HttpsRedirection. 21 | public static IApplicationBuilder UseHttpsRedirection(this IApplicationBuilder app) 22 | { 23 | if (app == null) 24 | { 25 | throw new ArgumentNullException(nameof(app)); 26 | } 27 | 28 | var serverAddressFeature = app.ServerFeatures.Get(); 29 | if (serverAddressFeature != null) 30 | { 31 | app.UseMiddleware(serverAddressFeature); 32 | } 33 | else 34 | { 35 | app.UseMiddleware(); 36 | } 37 | return app; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpsPolicy/HttpsRedirectionOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | 6 | namespace Microsoft.AspNetCore.HttpsPolicy 7 | { 8 | /// 9 | /// Options for the HttpsRedirection middleware 10 | /// 11 | public class HttpsRedirectionOptions 12 | { 13 | /// 14 | /// The status code used for the redirect response. The default is 307. 15 | /// 16 | public int RedirectStatusCode { get; set; } = StatusCodes.Status307TemporaryRedirect; 17 | 18 | /// 19 | /// The HTTPS port to be added to the redirected URL. 20 | /// 21 | /// 22 | /// If the HttpsPort is not set, we will try to get the HttpsPort from the following: 23 | /// 1. HTTPS_PORT environment variable 24 | /// 2. IServerAddressesFeature 25 | /// If that fails then the middleware will log a warning and turn off. 26 | /// 27 | public int? HttpsPort { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpsPolicy/HttpsRedirectionServicesExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.HttpsPolicy; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace Microsoft.AspNetCore.Builder 9 | { 10 | /// 11 | /// Extension methods for the HttpsRedirection middleware. 12 | /// 13 | public static class HttpsRedirectionServicesExtensions 14 | { 15 | /// 16 | /// Adds HTTPS redirection services. 17 | /// 18 | /// The for adding services. 19 | /// A delegate to configure the . 20 | /// 21 | public static IServiceCollection AddHttpsRedirection(this IServiceCollection services, Action configureOptions) 22 | { 23 | if (services == null) 24 | { 25 | throw new ArgumentNullException(nameof(services)); 26 | } 27 | if (configureOptions == null) 28 | { 29 | throw new ArgumentNullException(nameof(configureOptions)); 30 | } 31 | services.Configure(configureOptions); 32 | return services; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpsPolicy/Microsoft.AspNetCore.HttpsPolicy.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ASP.NET Core basic middleware for supporting HTTPS Redirection and HTTP Strict-Transport-Security. 6 | 7 | netstandard2.0 8 | $(NoWarn);CS1591 9 | true 10 | aspnetcore;https;hsts 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.HttpsPolicy/internal/HstsLoggingExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace Microsoft.AspNetCore.HttpsPolicy.Internal 8 | { 9 | internal static class HstsLoggingExtensions 10 | { 11 | private static readonly Action _notSecure; 12 | private static readonly Action _excludedHost; 13 | private static readonly Action _addingHstsHeader; 14 | 15 | static HstsLoggingExtensions() 16 | { 17 | _notSecure = LoggerMessage.Define(LogLevel.Debug, 1, "The request is insecure. Skipping HSTS header."); 18 | _excludedHost = LoggerMessage.Define(LogLevel.Debug, 2, "The host '{host}' is excluded. Skipping HSTS header."); 19 | _addingHstsHeader = LoggerMessage.Define(LogLevel.Trace, 3, "Adding HSTS header to response."); 20 | } 21 | 22 | public static void SkippingInsecure(this ILogger logger) 23 | { 24 | _notSecure(logger, null); 25 | } 26 | 27 | public static void SkippingExcludedHost(this ILogger logger, string host) 28 | { 29 | _excludedHost(logger, host, null); 30 | } 31 | 32 | public static void AddingHstsHeader(this ILogger logger) 33 | { 34 | _addingHstsHeader(logger, null); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/BrotliCompressionProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using System.IO.Compression; 7 | using Microsoft.Extensions.Options; 8 | 9 | namespace Microsoft.AspNetCore.ResponseCompression 10 | { 11 | /// 12 | /// Brotli compression provider. 13 | /// 14 | public class BrotliCompressionProvider : ICompressionProvider 15 | { 16 | /// 17 | /// Creates a new instance of with options. 18 | /// 19 | /// 20 | public BrotliCompressionProvider(IOptions options) 21 | { 22 | if (options == null) 23 | { 24 | throw new ArgumentNullException(nameof(options)); 25 | } 26 | 27 | Options = options.Value; 28 | } 29 | 30 | private BrotliCompressionProviderOptions Options { get; } 31 | 32 | /// 33 | public string EncodingName => "br"; 34 | 35 | /// 36 | public bool SupportsFlush => true; 37 | 38 | /// 39 | public Stream CreateStream(Stream outputStream) 40 | { 41 | #if NETCOREAPP2_1 42 | return new BrotliStream(outputStream, Options.Level, leaveOpen: true); 43 | #elif NET461 || NETSTANDARD2_0 44 | // Brotli is only supported in .NET Core 2.1+ 45 | throw new PlatformNotSupportedException(); 46 | #else 47 | #error Target frameworks need to be updated. 48 | #endif 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/BrotliCompressionProviderOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.IO.Compression; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Microsoft.AspNetCore.ResponseCompression 8 | { 9 | /// 10 | /// Options for the 11 | /// 12 | public class BrotliCompressionProviderOptions : IOptions 13 | { 14 | /// 15 | /// What level of compression to use for the stream. The default is . 16 | /// 17 | public CompressionLevel Level { get; set; } = CompressionLevel.Fastest; 18 | 19 | /// 20 | BrotliCompressionProviderOptions IOptions.Value => this; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/CompressionProviderCollection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.ObjectModel; 6 | 7 | namespace Microsoft.AspNetCore.ResponseCompression 8 | { 9 | /// 10 | /// A Collection of ICompressionProvider's that also allows them to be instantiated from an . 11 | /// 12 | public class CompressionProviderCollection : Collection 13 | { 14 | /// 15 | /// Adds a type representing an . 16 | /// 17 | /// 18 | /// Provider instances will be created using an . 19 | /// 20 | public void Add() where TCompressionProvider : ICompressionProvider 21 | { 22 | Add(typeof(TCompressionProvider)); 23 | } 24 | 25 | /// 26 | /// Adds a type representing an . 27 | /// 28 | /// Type representing an . 29 | /// 30 | /// Provider instances will be created using an . 31 | /// 32 | public void Add(Type providerType) 33 | { 34 | if (providerType == null) 35 | { 36 | throw new ArgumentNullException(nameof(providerType)); 37 | } 38 | 39 | if (!typeof(ICompressionProvider).IsAssignableFrom(providerType)) 40 | { 41 | throw new ArgumentException($"The provider must implement {nameof(ICompressionProvider)}.", nameof(providerType)); 42 | } 43 | 44 | var factory = new CompressionProviderFactory(providerType); 45 | Add(factory); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/CompressionProviderFactory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace Microsoft.AspNetCore.ResponseCompression 9 | { 10 | /// 11 | /// This is a placeholder for the CompressionProviderCollection that allows creating the given type via 12 | /// an . 13 | /// 14 | internal class CompressionProviderFactory : ICompressionProvider 15 | { 16 | public CompressionProviderFactory(Type providerType) 17 | { 18 | ProviderType = providerType; 19 | } 20 | 21 | private Type ProviderType { get; } 22 | 23 | public ICompressionProvider CreateInstance(IServiceProvider serviceProvider) 24 | { 25 | if (serviceProvider == null) 26 | { 27 | throw new ArgumentNullException(nameof(serviceProvider)); 28 | } 29 | 30 | return (ICompressionProvider)ActivatorUtilities.CreateInstance(serviceProvider, ProviderType, Type.EmptyTypes); 31 | } 32 | 33 | string ICompressionProvider.EncodingName 34 | { 35 | get { throw new NotSupportedException(); } 36 | } 37 | 38 | bool ICompressionProvider.SupportsFlush 39 | { 40 | get { throw new NotSupportedException(); } 41 | } 42 | 43 | Stream ICompressionProvider.CreateStream(Stream outputStream) 44 | { 45 | throw new NotSupportedException(); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/GzipCompressionProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using System.IO.Compression; 7 | using Microsoft.Extensions.Options; 8 | 9 | namespace Microsoft.AspNetCore.ResponseCompression 10 | { 11 | /// 12 | /// GZIP compression provider. 13 | /// 14 | public class GzipCompressionProvider : ICompressionProvider 15 | { 16 | /// 17 | /// Creates a new instance of GzipCompressionProvider with options. 18 | /// 19 | /// 20 | public GzipCompressionProvider(IOptions options) 21 | { 22 | if (options == null) 23 | { 24 | throw new ArgumentNullException(nameof(options)); 25 | } 26 | 27 | Options = options.Value; 28 | } 29 | 30 | private GzipCompressionProviderOptions Options { get; } 31 | 32 | /// 33 | public string EncodingName => "gzip"; 34 | 35 | /// 36 | public bool SupportsFlush 37 | { 38 | get 39 | { 40 | #if NET461 41 | return false; 42 | #elif NETSTANDARD2_0 || NETCOREAPP2_1 43 | return true; 44 | #else 45 | #error target frameworks need to be updated 46 | #endif 47 | } 48 | } 49 | 50 | /// 51 | public Stream CreateStream(Stream outputStream) 52 | { 53 | return new GZipStream(outputStream, Options.Level, leaveOpen: true); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/GzipCompressionProviderOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.IO.Compression; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Microsoft.AspNetCore.ResponseCompression 9 | { 10 | /// 11 | /// Options for the GzipCompressionProvider 12 | /// 13 | public class GzipCompressionProviderOptions : IOptions 14 | { 15 | /// 16 | /// What level of compression to use for the stream. The default is Fastest. 17 | /// 18 | public CompressionLevel Level { get; set; } = CompressionLevel.Fastest; 19 | 20 | /// 21 | GzipCompressionProviderOptions IOptions.Value => this; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/ICompressionProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.IO; 5 | 6 | namespace Microsoft.AspNetCore.ResponseCompression 7 | { 8 | /// 9 | /// Provides a specific compression implementation to compress HTTP responses. 10 | /// 11 | public interface ICompressionProvider 12 | { 13 | /// 14 | /// The encoding name used in the 'Accept-Encoding' request header and 'Content-Encoding' response header. 15 | /// 16 | string EncodingName { get; } 17 | 18 | /// 19 | /// Indicates if the given provider supports Flush and FlushAsync. If not, compression may be disabled in some scenarios. 20 | /// 21 | bool SupportsFlush { get; } 22 | 23 | /// 24 | /// Create a new compression stream. 25 | /// 26 | /// The stream where the compressed data have to be written. 27 | /// The compression stream. 28 | Stream CreateStream(Stream outputStream); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/IResponseCompressionProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | 6 | namespace Microsoft.AspNetCore.ResponseCompression 7 | { 8 | /// 9 | /// Used to examine requests and responses to see if compression should be enabled. 10 | /// 11 | public interface IResponseCompressionProvider 12 | { 13 | /// 14 | /// Examines the request and selects an acceptable compression provider, if any. 15 | /// 16 | /// 17 | /// A compression provider or null if compression should not be used. 18 | ICompressionProvider GetCompressionProvider(HttpContext context); 19 | 20 | /// 21 | /// Examines the response on first write to see if compression should be used. 22 | /// 23 | /// 24 | /// 25 | bool ShouldCompressResponse(HttpContext context); 26 | 27 | /// 28 | /// Examines the request to see if compression should be used for response. 29 | /// 30 | /// 31 | /// 32 | bool CheckRequestAcceptsCompression(HttpContext context); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/Microsoft.AspNetCore.ResponseCompression.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ASP.NET Core middleware for HTTP Response compression. 5 | net461;netstandard2.0;netcoreapp2.1 6 | true 7 | aspnetcore 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.AspNetCore.ResponseCompression.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.ResponseCompression; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.DependencyInjection.Extensions; 8 | 9 | namespace Microsoft.AspNetCore.Builder 10 | { 11 | /// 12 | /// Extension methods for the ResponseCompression middleware. 13 | /// 14 | public static class ResponseCompressionBuilderExtensions 15 | { 16 | /// 17 | /// Adds middleware for dynamically compressing HTTP Responses. 18 | /// 19 | /// The instance this method extends. 20 | public static IApplicationBuilder UseResponseCompression(this IApplicationBuilder builder) 21 | { 22 | if (builder == null) 23 | { 24 | throw new ArgumentNullException(nameof(builder)); 25 | } 26 | 27 | return builder.UseMiddleware(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionDefaults.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.AspNetCore.ResponseCompression 7 | { 8 | /// 9 | /// Defaults for the ResponseCompressionMiddleware 10 | /// 11 | public class ResponseCompressionDefaults 12 | { 13 | /// 14 | /// Default MIME types to compress responses for. 15 | /// 16 | // This list is not intended to be exhaustive, it's a baseline for the 90% case. 17 | public static readonly IEnumerable MimeTypes = new[] 18 | { 19 | // General 20 | "text/plain", 21 | // Static files 22 | "text/css", 23 | "application/javascript", 24 | // MVC 25 | "text/html", 26 | "application/xml", 27 | "text/xml", 28 | "application/json", 29 | "text/json", 30 | // WebAssembly 31 | "application/wasm", 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.ResponseCompression/ResponseCompressionOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.AspNetCore.ResponseCompression 7 | { 8 | /// 9 | /// Options for the HTTP response compression middleware. 10 | /// 11 | public class ResponseCompressionOptions 12 | { 13 | /// 14 | /// Response Content-Type MIME types to compress. 15 | /// 16 | public IEnumerable MimeTypes { get; set; } 17 | 18 | /// 19 | /// Response Content-Type MIME types to not compress. 20 | /// 21 | public IEnumerable ExcludedMimeTypes { get; set; } 22 | 23 | /// 24 | /// Indicates if responses over HTTPS connections should be compressed. The default is 'false'. 25 | /// Enabling compression on HTTPS connections may expose security problems. 26 | /// 27 | public bool EnableForHttps { get; set; } = false; 28 | 29 | /// 30 | /// The types to use for responses. 31 | /// Providers are prioritized based on the order they are added. 32 | /// 33 | public CompressionProviderCollection Providers { get; } = new CompressionProviderCollection(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/IRule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite 5 | { 6 | /// 7 | /// Represents a rule. 8 | /// 9 | public interface IRule 10 | { 11 | /// 12 | /// Applies the rule. 13 | /// Implementations of ApplyRule should set the value for 14 | /// (defaults to RuleResult.ContinueRules) 15 | /// 16 | /// 17 | void ApplyRule(RewriteContext context); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ApacheModRewriteRule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | using Microsoft.AspNetCore.Rewrite.Logging; 6 | 7 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 8 | { 9 | public class ApacheModRewriteRule : IRule 10 | { 11 | public UrlMatch InitialMatch { get; } 12 | public IList Conditions { get; } 13 | public IList Actions { get; } 14 | 15 | public ApacheModRewriteRule(UrlMatch initialMatch, IList conditions, IList urlActions) 16 | { 17 | Conditions = conditions; 18 | InitialMatch = initialMatch; 19 | Actions = urlActions; 20 | } 21 | 22 | public virtual void ApplyRule(RewriteContext context) 23 | { 24 | // 1. Figure out which section of the string to match for the initial rule. 25 | var initMatchRes = InitialMatch.Evaluate(context.HttpContext.Request.Path, context); 26 | 27 | if (!initMatchRes.Success) 28 | { 29 | context.Logger?.ModRewriteDidNotMatchRule(); 30 | return; 31 | } 32 | 33 | BackReferenceCollection condBackReferences = null; 34 | if (Conditions != null) 35 | { 36 | var condResult = ConditionEvaluator.Evaluate(Conditions, context, initMatchRes.BackReferences); 37 | if (!condResult.Success) 38 | { 39 | context.Logger?.ModRewriteDidNotMatchRule(); 40 | return; 41 | } 42 | } 43 | 44 | // At this point, we know our rule passed, first apply pre conditions, 45 | // which can modify things like the cookie or env, and then apply the action 46 | context.Logger?.ModRewriteMatchedRule(); 47 | 48 | foreach (var action in Actions) 49 | { 50 | action.ApplyAction(context, initMatchRes?.BackReferences, condBackReferences); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/Condition.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 5 | { 6 | public class Condition 7 | { 8 | public Pattern Input { get; set; } 9 | public UrlMatch Match { get; set; } 10 | public bool OrNext { get; set; } 11 | 12 | public MatchResults Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 13 | { 14 | var pattern = Input.Evaluate(context, ruleBackReferences, conditionBackReferences); 15 | return Match.Evaluate(pattern, context); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ConditionEvaluator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 7 | { 8 | public static class ConditionEvaluator 9 | { 10 | public static MatchResults Evaluate(IEnumerable conditions, RewriteContext context, BackReferenceCollection backReferences) 11 | { 12 | return Evaluate(conditions, context, backReferences, trackAllCaptures: false); 13 | } 14 | 15 | public static MatchResults Evaluate(IEnumerable conditions, RewriteContext context, BackReferenceCollection backReferences, bool trackAllCaptures) 16 | { 17 | BackReferenceCollection prevBackReferences = null; 18 | MatchResults condResult = null; 19 | var orSucceeded = false; 20 | foreach (var condition in conditions) 21 | { 22 | if (orSucceeded && condition.OrNext) 23 | { 24 | continue; 25 | } 26 | else if (orSucceeded) 27 | { 28 | orSucceeded = false; 29 | continue; 30 | } 31 | 32 | condResult = condition.Evaluate(context, backReferences, prevBackReferences); 33 | var currentBackReferences = condResult.BackReferences; 34 | if (condition.OrNext) 35 | { 36 | orSucceeded = condResult.Success; 37 | } 38 | else if (!condResult.Success) 39 | { 40 | return condResult; 41 | } 42 | 43 | if (condResult.Success && trackAllCaptures && prevBackReferences != null) 44 | { 45 | prevBackReferences.Add(currentBackReferences); 46 | currentBackReferences = prevBackReferences; 47 | } 48 | 49 | prevBackReferences = currentBackReferences; 50 | } 51 | 52 | return new MatchResults { BackReferences = prevBackReferences, Success = condResult.Success }; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ConditionType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 5 | { 6 | public enum ConditionType 7 | { 8 | Regex, 9 | PropertyTest, 10 | StringComp, 11 | IntComp 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/FlagType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 5 | { 6 | public enum FlagType 7 | { 8 | EscapeBackreference, 9 | Chain, 10 | Cookie, 11 | DiscardPath, 12 | Env, 13 | End, 14 | Forbidden, 15 | Gone, 16 | Handler, 17 | Last, 18 | Next, 19 | NoCase, 20 | NoEscape, 21 | NoSubReq, 22 | NoVary, 23 | Or, 24 | Proxy, 25 | PassThrough, 26 | QSAppend, 27 | QSDiscard, 28 | QSLast, 29 | Redirect, 30 | Skip, 31 | Type 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/Flags.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 7 | { 8 | // For more information of flags, and what flags we currently support: 9 | // https://github.com/aspnet/BasicMiddleware/issues/66 10 | // http://httpd.apache.org/docs/current/expr.html#vars 11 | public class Flags 12 | { 13 | public IDictionary FlagDictionary { get; } 14 | 15 | public Flags(IDictionary flags) 16 | { 17 | FlagDictionary = flags; 18 | } 19 | 20 | public Flags() 21 | { 22 | FlagDictionary = new Dictionary(); 23 | } 24 | 25 | public void SetFlag(FlagType flag, string value) 26 | { 27 | if (value == null) 28 | { 29 | value = string.Empty; 30 | } 31 | FlagDictionary[flag] = value; 32 | } 33 | 34 | public bool GetValue(FlagType flag, out string value) 35 | { 36 | string res; 37 | if (!FlagDictionary.TryGetValue(flag, out res)) 38 | { 39 | value = null; 40 | return false; 41 | } 42 | value = res; 43 | return true; 44 | } 45 | 46 | public string this[FlagType flag] 47 | { 48 | get 49 | { 50 | string res; 51 | if (!FlagDictionary.TryGetValue(flag, out res)) 52 | { 53 | return null; 54 | } 55 | return res; 56 | } 57 | set 58 | { 59 | FlagDictionary[flag] = value ?? string.Empty; 60 | } 61 | } 62 | 63 | public bool HasFlag(FlagType flag) 64 | { 65 | string res; 66 | return FlagDictionary.TryGetValue(flag, out res); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/OperationType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 5 | { 6 | public enum OperationType 7 | { 8 | None, 9 | Equal, 10 | Greater, 11 | GreaterEqual, 12 | Less, 13 | LessEqual, 14 | NotEqual, 15 | Directory, 16 | RegularFile, 17 | ExistingFile, 18 | SymbolicLink, 19 | Size, 20 | ExistingUrl, 21 | Executable 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/ParsedModRewriteCondition.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 5 | { 6 | public class ParsedModRewriteInput 7 | { 8 | public bool Invert { get; set; } 9 | public ConditionType ConditionType { get; set; } 10 | public OperationType OperationType { get; set; } 11 | public string Operand { get; set; } 12 | 13 | public ParsedModRewriteInput() { } 14 | 15 | public ParsedModRewriteInput(bool invert, ConditionType conditionType, OperationType operationType, string operand) 16 | { 17 | Invert = invert; 18 | ConditionType = conditionType; 19 | OperationType = operationType; 20 | Operand = operand; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/RuleRegexParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 7 | { 8 | public class RuleRegexParser 9 | { 10 | public ParsedModRewriteInput ParseRuleRegex(string regex) 11 | { 12 | if (string.IsNullOrEmpty(regex)) 13 | { 14 | throw new FormatException("Regex expression is null"); 15 | } 16 | if (regex[0] == '!') 17 | { 18 | return new ParsedModRewriteInput { Invert = true, Operand = regex.Substring(1) }; 19 | } 20 | else 21 | { 22 | return new ParsedModRewriteInput { Invert = false, Operand = regex }; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ApacheModRewrite/SegmentType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite 5 | { 6 | public enum SegmentType 7 | { 8 | Literal, 9 | ServerParameter, 10 | ConditionParameter, 11 | RuleParameter 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/BackReferenceCollection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text.RegularExpressions; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Internal 9 | { 10 | public class BackReferenceCollection 11 | { 12 | private List _backReferences = new List(); 13 | 14 | public BackReferenceCollection(GroupCollection references) 15 | { 16 | if (references != null) 17 | { 18 | for (var i = 0; i < references.Count; i++) 19 | { 20 | _backReferences.Add(references[i].Value); 21 | } 22 | } 23 | } 24 | 25 | public BackReferenceCollection(string reference) 26 | { 27 | _backReferences.Add(reference); 28 | } 29 | 30 | public string this[int index] 31 | { 32 | get 33 | { 34 | if (index < _backReferences.Count) 35 | { 36 | return _backReferences[index]; 37 | } 38 | else 39 | { 40 | throw new IndexOutOfRangeException($"Cannot access back reference at index {index}. Only {_backReferences.Count} back references were captured."); 41 | } 42 | } 43 | } 44 | 45 | public void Add(BackReferenceCollection references) 46 | { 47 | if (references != null) 48 | { 49 | _backReferences.AddRange(references._backReferences); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/DelegateRule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal 7 | { 8 | public class DelegateRule : IRule 9 | { 10 | private readonly Action _onApplyRule; 11 | 12 | public DelegateRule(Action onApplyRule) 13 | { 14 | _onApplyRule = onApplyRule; 15 | } 16 | public void ApplyRule(RewriteContext context) => _onApplyRule(context); 17 | } 18 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/ActionType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 5 | { 6 | public enum ActionType 7 | { 8 | None, 9 | Rewrite, 10 | Redirect, 11 | CustomResponse, 12 | AbortRequest 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/Condition.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 5 | { 6 | public class Condition 7 | { 8 | public Pattern Input { get; set; } 9 | public UrlMatch Match { get; set; } 10 | 11 | public MatchResults Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 12 | { 13 | var pattern = Input.Evaluate(context, ruleBackReferences, conditionBackReferences); 14 | return Match.Evaluate(pattern, context); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/ConditionCollection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 9 | { 10 | public class ConditionCollection : IEnumerable 11 | { 12 | private readonly List _conditions = new List(); 13 | 14 | public LogicalGrouping Grouping { get; } 15 | public bool TrackAllCaptures { get; } 16 | 17 | public ConditionCollection() 18 | :this(LogicalGrouping.MatchAll, trackAllCaptures: false) 19 | { 20 | } 21 | 22 | public ConditionCollection(LogicalGrouping grouping, bool trackAllCaptures) 23 | { 24 | Grouping = grouping; 25 | TrackAllCaptures = trackAllCaptures; 26 | } 27 | 28 | public int Count => _conditions.Count; 29 | 30 | public Condition this[int index] 31 | { 32 | get 33 | { 34 | if (index < _conditions.Count) 35 | { 36 | return _conditions[index]; 37 | } 38 | throw new IndexOutOfRangeException($"Cannot access condition at index {index}. Only {_conditions.Count} conditions were captured."); 39 | } 40 | } 41 | 42 | public void Add(Condition condition) 43 | { 44 | if (condition != null) 45 | { 46 | _conditions.Add(condition); 47 | } 48 | } 49 | 50 | public void AddConditions(IEnumerable conditions) 51 | { 52 | if (conditions != null) 53 | { 54 | _conditions.AddRange(conditions); 55 | } 56 | } 57 | 58 | IEnumerator IEnumerable.GetEnumerator() 59 | { 60 | return _conditions.GetEnumerator(); 61 | } 62 | 63 | public IEnumerator GetEnumerator() 64 | { 65 | return _conditions.GetEnumerator(); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/ConditionEvaluator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 5 | { 6 | public static class ConditionEvaluator 7 | { 8 | public static MatchResults Evaluate(ConditionCollection conditions, RewriteContext context, BackReferenceCollection backReferences) 9 | { 10 | BackReferenceCollection prevBackReferences = null; 11 | MatchResults condResult = null; 12 | var orSucceeded = false; 13 | foreach (var condition in conditions) 14 | { 15 | if (orSucceeded && conditions.Grouping == LogicalGrouping.MatchAny) 16 | { 17 | continue; 18 | } 19 | 20 | if (orSucceeded) 21 | { 22 | orSucceeded = false; 23 | continue; 24 | } 25 | 26 | condResult = condition.Evaluate(context, backReferences, prevBackReferences); 27 | var currentBackReferences = condResult.BackReferences; 28 | if (conditions.Grouping == LogicalGrouping.MatchAny) 29 | { 30 | orSucceeded = condResult.Success; 31 | } 32 | else if (!condResult.Success) 33 | { 34 | return condResult; 35 | } 36 | 37 | if (condResult.Success && conditions.TrackAllCaptures && prevBackReferences!= null) 38 | { 39 | prevBackReferences.Add(currentBackReferences); 40 | currentBackReferences = prevBackReferences; 41 | } 42 | 43 | prevBackReferences = currentBackReferences; 44 | } 45 | 46 | return new MatchResults { BackReferences = prevBackReferences, Success = condResult.Success }; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/IISRewriteMap.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 8 | { 9 | public class IISRewriteMap 10 | { 11 | private readonly Dictionary _map = new Dictionary(); 12 | 13 | public IISRewriteMap(string name) 14 | { 15 | if (string.IsNullOrEmpty(name)) 16 | { 17 | throw new ArgumentException(nameof(name)); 18 | } 19 | Name = name; 20 | } 21 | 22 | public string Name { get; } 23 | 24 | public string this[string key] 25 | { 26 | get 27 | { 28 | string value; 29 | return _map.TryGetValue(key, out value) ? value : null; 30 | } 31 | set 32 | { 33 | if (string.IsNullOrEmpty(key)) 34 | { 35 | throw new ArgumentException(nameof(key)); 36 | } 37 | if (string.IsNullOrEmpty(value)) 38 | { 39 | throw new ArgumentException(nameof(value)); 40 | } 41 | _map[key] = value; 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/IISRewriteMapCollection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 8 | { 9 | public class IISRewriteMapCollection : IEnumerable 10 | { 11 | private readonly Dictionary _rewriteMaps = new Dictionary(); 12 | 13 | public void Add(IISRewriteMap rewriteMap) 14 | { 15 | if (rewriteMap != null) 16 | { 17 | _rewriteMaps[rewriteMap.Name] = rewriteMap; 18 | } 19 | } 20 | 21 | public int Count => _rewriteMaps.Count; 22 | 23 | public IISRewriteMap this[string key] 24 | { 25 | get 26 | { 27 | IISRewriteMap value; 28 | return _rewriteMaps.TryGetValue(key, out value) ? value : null; 29 | } 30 | } 31 | 32 | IEnumerator IEnumerable.GetEnumerator() 33 | { 34 | return _rewriteMaps.Values.GetEnumerator(); 35 | } 36 | 37 | public IEnumerator GetEnumerator() 38 | { 39 | return _rewriteMaps.Values.GetEnumerator(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/InvalidUrlRewriteFormatException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Xml; 6 | using System.Xml.Linq; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 9 | { 10 | public class InvalidUrlRewriteFormatException : FormatException 11 | { 12 | public int LineNumber { get; } 13 | public int LinePosition { get; } 14 | 15 | public InvalidUrlRewriteFormatException(XElement element, string message) 16 | : base(FormatMessage(element, message)) 17 | { 18 | } 19 | 20 | public InvalidUrlRewriteFormatException(XElement element, string message, Exception innerException) 21 | : base(FormatMessage(element, message), innerException) 22 | { 23 | var xmlLineInfo = (IXmlLineInfo)element; 24 | LineNumber = xmlLineInfo.LineNumber; 25 | LinePosition = xmlLineInfo.LinePosition; 26 | } 27 | 28 | private static string FormatMessage(XElement element, string message) 29 | { 30 | var xmlLineInfo = (IXmlLineInfo)element; 31 | return Resources.FormatError_UrlRewriteParseError(message, xmlLineInfo.LineNumber, xmlLineInfo.LinePosition); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/LogicalGrouping.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 5 | { 6 | public enum LogicalGrouping 7 | { 8 | MatchAll, 9 | MatchAny 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/MatchType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 5 | { 6 | public enum MatchType 7 | { 8 | Pattern, 9 | IsFile, 10 | IsDirectory 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/PatternSyntax.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 5 | { 6 | public enum PatternSyntax 7 | { 8 | ECMAScript, 9 | Wildcard, 10 | ExactMatch 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/RedirectType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 7 | { 8 | public enum RedirectType 9 | { 10 | Permanent = StatusCodes.Status301MovedPermanently, 11 | Found = StatusCodes.Status302Found, 12 | SeeOther = StatusCodes.Status303SeeOther, 13 | Temporary = StatusCodes.Status307TemporaryRedirect 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/RewriteMapParser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Linq; 6 | using System.Xml.Linq; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 9 | { 10 | public static class RewriteMapParser 11 | { 12 | public static IISRewriteMapCollection Parse(XElement xmlRoot) 13 | { 14 | if (xmlRoot == null) 15 | { 16 | throw new ArgumentNullException(nameof(xmlRoot)); 17 | } 18 | 19 | var mapsElement = xmlRoot.Descendants(RewriteTags.RewriteMaps).SingleOrDefault(); 20 | if (mapsElement == null) 21 | { 22 | return null; 23 | } 24 | 25 | var rewriteMaps = new IISRewriteMapCollection(); 26 | foreach (var mapElement in mapsElement.Elements(RewriteTags.RewriteMap)) 27 | { 28 | var map = new IISRewriteMap(mapElement.Attribute(RewriteTags.Name)?.Value); 29 | foreach (var addElement in mapElement.Elements(RewriteTags.Add)) 30 | { 31 | map[addElement.Attribute(RewriteTags.Key).Value.ToLowerInvariant()] = addElement.Attribute(RewriteTags.Value).Value; 32 | } 33 | rewriteMaps.Add(map); 34 | } 35 | 36 | return rewriteMaps; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/RewriteTags.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 5 | { 6 | public static class RewriteTags 7 | { 8 | public const string Action = "action"; 9 | public const string Add = "add"; 10 | public const string AppendQueryString = "appendQueryString"; 11 | public const string Conditions = "conditions"; 12 | public const string Enabled = "enabled"; 13 | public const string GlobalRules = "globalRules"; 14 | public const string IgnoreCase = "ignoreCase"; 15 | public const string Input = "input"; 16 | public const string Key = "key"; 17 | public const string LogicalGrouping = "logicalGrouping"; 18 | public const string LogRewrittenUrl = "logRewrittenUrl"; 19 | public const string Match = "match"; 20 | public const string MatchPattern = "matchPattern"; 21 | public const string MatchType = "matchType"; 22 | public const string Name = "name"; 23 | public const string Negate = "negate"; 24 | public const string Pattern = "pattern"; 25 | public const string PatternSyntax = "patternSyntax"; 26 | public const string RedirectType = "redirectType"; 27 | public const string Rewrite = "rewrite"; 28 | public const string RewriteMap = "rewriteMap"; 29 | public const string RewriteMaps = "rewriteMaps"; 30 | public const string Rule = "rule"; 31 | public const string Rules = "rules"; 32 | public const string StatusCode = "statusCode"; 33 | public const string SubStatusCode = "subStatusCode"; 34 | public const string StatusDescription = "statusDescription"; 35 | public const string StatusReason = "statusReason"; 36 | public const string StopProcessing = "stopProcessing"; 37 | public const string TrackAllCaptures = "trackAllCaptures"; 38 | public const string Type = "type"; 39 | public const string Url = "url"; 40 | public const string Value = "value"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/UriMatchCondition.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Text.RegularExpressions; 6 | using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 9 | { 10 | public class UriMatchCondition : Condition 11 | { 12 | private TimeSpan _regexTimeout = TimeSpan.FromSeconds(1); 13 | 14 | public UriMatchCondition(InputParser inputParser, string input, string pattern, UriMatchPart uriMatchPart, bool ignoreCase, bool negate) 15 | { 16 | var regexOptions = RegexOptions.CultureInvariant | RegexOptions.Compiled; 17 | regexOptions = ignoreCase ? regexOptions | RegexOptions.IgnoreCase : regexOptions; 18 | var regex = new Regex( 19 | pattern, 20 | regexOptions, 21 | _regexTimeout 22 | ); 23 | Input = inputParser.ParseInputString(input, uriMatchPart); 24 | Match = new RegexMatch(regex, negate); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/IISUrlRewrite/UriMatchPart.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite 5 | { 6 | public enum UriMatchPart 7 | { 8 | Full, 9 | Path 10 | } 11 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/MatchResults.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text.RegularExpressions; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal 7 | { 8 | public class MatchResults 9 | { 10 | public static readonly MatchResults EmptySuccess = new MatchResults { Success = true }; 11 | public static readonly MatchResults EmptyFailure = new MatchResults { Success = false }; 12 | 13 | public bool Success { get; set; } 14 | public BackReferenceCollection BackReferences { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/ParserContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal 5 | { 6 | /// 7 | /// Represents a string iterator, with captures. 8 | /// 9 | public class ParserContext 10 | { 11 | public readonly string Template; 12 | public int Index { get; set; } 13 | private int? _mark; 14 | 15 | public ParserContext(string condition) 16 | { 17 | Template = condition; 18 | Index = -1; 19 | } 20 | 21 | public char Current => (Index < Template.Length && Index >= 0) ? Template[Index] : (char)0; 22 | 23 | public bool Back() 24 | { 25 | return --Index >= 0; 26 | } 27 | 28 | public bool Next() 29 | { 30 | return ++Index < Template.Length; 31 | } 32 | 33 | public bool HasNext() 34 | { 35 | return (Index + 1) < Template.Length; 36 | } 37 | 38 | public void Mark() 39 | { 40 | _mark = Index; 41 | } 42 | 43 | public int GetIndex() 44 | { 45 | return Index; 46 | } 47 | 48 | public string Capture() 49 | { 50 | // TODO make this return a range rather than a string. 51 | if (_mark.HasValue) 52 | { 53 | var value = Template.Substring(_mark.Value, Index - _mark.Value); 54 | _mark = null; 55 | return value; 56 | } 57 | else 58 | { 59 | return null; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/Pattern.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal 7 | { 8 | public class Pattern 9 | { 10 | public IList PatternSegments { get; } 11 | public Pattern(IList patternSegments) 12 | { 13 | PatternSegments = patternSegments; 14 | } 15 | 16 | public string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 17 | { 18 | foreach (var pattern in PatternSegments) 19 | { 20 | context.Builder.Append(pattern.Evaluate(context, ruleBackReferences, conditionBackReferences)); 21 | } 22 | var retVal = context.Builder.ToString(); 23 | context.Builder.Clear(); 24 | return retVal; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal 5 | { 6 | public abstract class PatternSegment 7 | { 8 | public abstract string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/ConditionMatchSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class ConditionMatchSegment : PatternSegment 7 | { 8 | private readonly int _index; 9 | 10 | public ConditionMatchSegment(int index) 11 | { 12 | _index = index; 13 | } 14 | 15 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 16 | { 17 | return conditionBackReferences?[_index]; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/HeaderSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class HeaderSegment : PatternSegment 7 | { 8 | private readonly string _header; 9 | 10 | public HeaderSegment(string header) 11 | { 12 | _header = header; 13 | } 14 | 15 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 16 | { 17 | return context.HttpContext.Request.Headers[_header]; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/IsHttpsModSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class IsHttpsModSegment : PatternSegment 7 | { 8 | // Note: Mod rewrite pattern matches on lower case "on" and "off" 9 | // while IIS looks for capitalized "ON" and "OFF" 10 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 11 | { 12 | return context.HttpContext.Request.IsHttps ? "on" : "off"; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/IsHttpsUrlSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class IsHttpsUrlSegment : PatternSegment 7 | { 8 | // Note: Mod rewrite pattern matches on lower case "on" and "off" 9 | // while IIS looks for capitalized "ON" and "OFF" 10 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 11 | { 12 | return context.HttpContext.Request.IsHttps ? "ON" : "OFF"; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/IsIPV6Segment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Net.Sockets; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 7 | { 8 | 9 | public class IsIPV6Segment : PatternSegment 10 | { 11 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 12 | { 13 | if (context.HttpContext.Connection.RemoteIpAddress == null) 14 | { 15 | return "off"; 16 | } 17 | return context.HttpContext.Connection.RemoteIpAddress.AddressFamily == AddressFamily.InterNetworkV6 ? "on" : "off"; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/LiteralSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class LiteralSegment : PatternSegment 7 | { 8 | private readonly string _literal; 9 | 10 | public LiteralSegment(string literal) 11 | { 12 | _literal = literal; 13 | } 14 | 15 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 16 | { 17 | return _literal; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/LocalAddressSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class LocalAddressSegment : PatternSegment 7 | { 8 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 9 | { 10 | return context.HttpContext.Connection.LocalIpAddress?.ToString(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/LocalPortSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Globalization; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 7 | { 8 | public class LocalPortSegment : PatternSegment 9 | { 10 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 11 | { 12 | return context.HttpContext.Connection.LocalPort.ToString(CultureInfo.InvariantCulture); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/QueryStringSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class QueryStringSegment : PatternSegment 7 | { 8 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackRefernces, BackReferenceCollection conditionBackReferences) 9 | { 10 | var queryString = context.HttpContext.Request.QueryString.ToString(); 11 | 12 | if (!string.IsNullOrEmpty(queryString)) 13 | { 14 | return queryString.Substring(1); 15 | } 16 | 17 | return queryString; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RemoteAddressSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class RemoteAddressSegment : PatternSegment 7 | { 8 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 9 | { 10 | return context.HttpContext.Connection.RemoteIpAddress?.ToString(); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RemotePortSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Globalization; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 7 | { 8 | public class RemotePortSegment : PatternSegment 9 | { 10 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 11 | { 12 | return context.HttpContext.Connection.RemotePort.ToString(CultureInfo.InvariantCulture); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RequestFilenameSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class RequestFileNameSegment : PatternSegment 7 | { 8 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 9 | { 10 | return context.HttpContext.Request.Path; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RequestMethodSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class RequestMethodSegment : PatternSegment 7 | { 8 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 9 | { 10 | return context.HttpContext.Request.Method; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RewriteMapSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 7 | { 8 | public class RewriteMapSegment : PatternSegment 9 | { 10 | private readonly IISRewriteMap _rewriteMap; 11 | private readonly Pattern _pattern; 12 | 13 | public RewriteMapSegment(IISRewriteMap rewriteMap, Pattern pattern) 14 | { 15 | _rewriteMap = rewriteMap; 16 | _pattern = pattern; 17 | } 18 | 19 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 20 | { 21 | var key = _pattern.Evaluate(context, ruleBackReferences, conditionBackReferences).ToLowerInvariant(); 22 | return _rewriteMap[key]; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/RuleMatchSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class RuleMatchSegment : PatternSegment 7 | { 8 | private readonly int _index; 9 | 10 | public RuleMatchSegment(int index) 11 | { 12 | _index = index; 13 | } 14 | 15 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 16 | { 17 | return ruleBackReferences[_index]; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/SchemeSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 5 | { 6 | public class SchemeSegment : PatternSegment 7 | { 8 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 9 | { 10 | return context.HttpContext.Request.Scheme; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/ServerProtocolSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http.Features; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 7 | { 8 | public class ServerProtocolSegment : PatternSegment 9 | { 10 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 11 | { 12 | return context.HttpContext.Features.Get()?.Protocol; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/ToLowerSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 7 | { 8 | public class ToLowerSegment : PatternSegment 9 | { 10 | private readonly Pattern _pattern; 11 | 12 | public ToLowerSegment(Pattern pattern) 13 | { 14 | _pattern = pattern; 15 | } 16 | 17 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 18 | { 19 | // PERF as we share the string builder across the context, we need to make a new one here to evaluate 20 | // lowercase segments. 21 | var tempBuilder = context.Builder; 22 | context.Builder = new StringBuilder(64); 23 | var pattern = _pattern.Evaluate(context, ruleBackReferences, conditionBackReferences); 24 | context.Builder = tempBuilder; 25 | return pattern.ToLowerInvariant(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/UrlEncodeSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text; 5 | using System.Text.Encodings.Web; 6 | 7 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 8 | { 9 | public class UrlEncodeSegment : PatternSegment 10 | { 11 | private readonly Pattern _pattern; 12 | 13 | public UrlEncodeSegment(Pattern pattern) 14 | { 15 | _pattern = pattern; 16 | } 17 | 18 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 19 | { 20 | var oldBuilder = context.Builder; 21 | // PERF 22 | // Because we need to be able to evaluate multiple nested patterns, 23 | // we provided a new string builder and evaluate the new pattern, 24 | // and restore it after evaluation. 25 | context.Builder = new StringBuilder(64); 26 | var pattern = _pattern.Evaluate(context, ruleBackReferences, conditionBackReferences); 27 | context.Builder = oldBuilder; 28 | return UrlEncoder.Default.Encode(pattern); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/PatternSegments/UrlSegment.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http.Extensions; 5 | using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite; 6 | 7 | namespace Microsoft.AspNetCore.Rewrite.Internal.PatternSegments 8 | { 9 | public class UrlSegment : PatternSegment 10 | { 11 | private readonly UriMatchPart _uriMatchPart; 12 | 13 | public UrlSegment() 14 | : this(UriMatchPart.Path) 15 | { 16 | } 17 | 18 | public UrlSegment(UriMatchPart uriMatchPart) 19 | { 20 | _uriMatchPart = uriMatchPart; 21 | } 22 | 23 | public override string Evaluate(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 24 | { 25 | return _uriMatchPart == UriMatchPart.Full ? context.HttpContext.Request.GetEncodedUrl() : (string)context.HttpContext.Request.Path; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/RedirectToHttpsRule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Rewrite.Logging; 7 | using Microsoft.Net.Http.Headers; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Internal 10 | { 11 | public class RedirectToHttpsRule : IRule 12 | { 13 | public int? SSLPort { get; set; } 14 | public int StatusCode { get; set; } 15 | 16 | public virtual void ApplyRule(RewriteContext context) 17 | { 18 | if (!context.HttpContext.Request.IsHttps) 19 | { 20 | var host = context.HttpContext.Request.Host; 21 | if (SSLPort.HasValue && SSLPort.Value > 0) 22 | { 23 | // a specific SSL port is specified 24 | host = new HostString(host.Host, SSLPort.Value); 25 | } 26 | else 27 | { 28 | // clear the port 29 | host = new HostString(host.Host); 30 | } 31 | 32 | var req = context.HttpContext.Request; 33 | var newUrl = new StringBuilder().Append("https://").Append(host).Append(req.PathBase).Append(req.Path).Append(req.QueryString); 34 | var response = context.HttpContext.Response; 35 | response.StatusCode = StatusCode; 36 | response.Headers[HeaderNames.Location] = newUrl.ToString(); 37 | context.Result = RuleResult.EndResponse; 38 | context.Logger?.RedirectedToHttps(); 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/RedirectToWwwRule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Http.Extensions; 7 | using Microsoft.AspNetCore.Rewrite.Logging; 8 | using Microsoft.Net.Http.Headers; 9 | 10 | namespace Microsoft.AspNetCore.Rewrite.Internal 11 | { 12 | public class RedirectToWwwRule : IRule 13 | { 14 | public readonly int _statusCode; 15 | 16 | public RedirectToWwwRule(int statusCode) 17 | { 18 | _statusCode = statusCode; 19 | } 20 | 21 | public virtual void ApplyRule(RewriteContext context) 22 | { 23 | var req = context.HttpContext.Request; 24 | if (req.Host.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase)) 25 | { 26 | context.Result = RuleResult.ContinueRules; 27 | return; 28 | } 29 | 30 | if (req.Host.Value.StartsWith("www.", StringComparison.OrdinalIgnoreCase)) 31 | { 32 | context.Result = RuleResult.ContinueRules; 33 | return; 34 | } 35 | 36 | var wwwHost = new HostString($"www.{req.Host.Value}"); 37 | var newUrl = UriHelper.BuildAbsolute(req.Scheme, wwwHost, req.PathBase, req.Path, req.QueryString); 38 | var response = context.HttpContext.Response; 39 | response.StatusCode = _statusCode; 40 | response.Headers[HeaderNames.Location] = newUrl; 41 | context.Result = RuleResult.EndResponse; 42 | context.Logger?.RedirectedToWww(); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlAction.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal 5 | { 6 | public abstract class UrlAction 7 | { 8 | protected Pattern Url { get; set; } 9 | public abstract void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/AbortAction.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Rewrite.Logging; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions 7 | { 8 | public class AbortAction : UrlAction 9 | { 10 | public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 11 | { 12 | context.HttpContext.Abort(); 13 | context.Result = RuleResult.EndResponse; 14 | context.Logger?.AbortedRequest(context.HttpContext.Request.Path + context.HttpContext.Request.QueryString); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/CustomResponseAction.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text; 5 | using Microsoft.AspNetCore.Http.Extensions; 6 | using Microsoft.AspNetCore.Http.Features; 7 | using Microsoft.AspNetCore.Rewrite.Logging; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions 10 | { 11 | public class CustomResponseAction : UrlAction 12 | { 13 | public int StatusCode { get; } 14 | public string StatusReason { get; set; } 15 | public string StatusDescription { get; set; } 16 | 17 | public CustomResponseAction(int statusCode) 18 | { 19 | StatusCode = statusCode; 20 | } 21 | 22 | public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 23 | { 24 | var response = context.HttpContext.Response; 25 | response.StatusCode = StatusCode; 26 | 27 | if (!string.IsNullOrEmpty(StatusReason)) 28 | { 29 | context.HttpContext.Features.Get().ReasonPhrase = StatusReason; 30 | } 31 | 32 | if (!string.IsNullOrEmpty(StatusDescription)) 33 | { 34 | var content = Encoding.UTF8.GetBytes(StatusDescription); 35 | response.ContentLength = content.Length; 36 | response.ContentType = "text/plain; charset=utf-8"; 37 | response.Body.Write(content, 0, content.Length); 38 | } 39 | 40 | context.Result = RuleResult.EndResponse; 41 | 42 | context.Logger?.CustomResponse(context.HttpContext.Request.GetEncodedUrl()); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/ForbiddenAction.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions 7 | { 8 | public class ForbiddenAction : UrlAction 9 | { 10 | public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 11 | { 12 | context.HttpContext.Response.StatusCode = StatusCodes.Status403Forbidden; 13 | context.Result = RuleResult.EndResponse; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/GoneAction.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions 7 | { 8 | public class GoneAction : UrlAction 9 | { 10 | public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 11 | { 12 | context.HttpContext.Response.StatusCode = StatusCodes.Status410Gone; 13 | context.Result = RuleResult.EndResponse; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlActions/NoneAction.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlActions 5 | { 6 | public class NoneAction : UrlAction 7 | { 8 | public RuleResult Result { get; } 9 | 10 | public NoneAction(RuleResult result) 11 | { 12 | Result = result; 13 | } 14 | // Explicitly say that nothing happens 15 | public override void ApplyAction(RewriteContext context, BackReferenceCollection ruleBackReferences, BackReferenceCollection conditionBackReferences) 16 | { 17 | context.Result = Result; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal 5 | { 6 | public abstract class UrlMatch 7 | { 8 | protected bool Negate { get; set; } 9 | public abstract MatchResults Evaluate(string input, RewriteContext context); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/ExactMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches 5 | { 6 | public class ExactMatch : UrlMatch 7 | { 8 | private readonly bool _ignoreCase; 9 | private readonly string _stringMatch; 10 | 11 | public ExactMatch(bool ignoreCase, string input, bool negate) 12 | { 13 | _ignoreCase = ignoreCase; 14 | _stringMatch = input; 15 | Negate = negate; 16 | } 17 | 18 | public override MatchResults Evaluate(string pattern, RewriteContext context) 19 | { 20 | var pathMatch = string.Compare(pattern, _stringMatch, _ignoreCase); 21 | var success = ((pathMatch == 0) != Negate); 22 | if (success) 23 | { 24 | return new MatchResults { Success = success, BackReferences = new BackReferenceCollection(pattern) }; 25 | } 26 | else 27 | { 28 | return MatchResults.EmptyFailure; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/FileSizeMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches 5 | { 6 | public class FileSizeMatch : UrlMatch 7 | { 8 | public FileSizeMatch(bool negate) 9 | { 10 | Negate = negate; 11 | } 12 | 13 | public override MatchResults Evaluate(string input, RewriteContext context) 14 | { 15 | var fileInfo = context.StaticFileProvider.GetFileInfo(input); 16 | return fileInfo.Exists && fileInfo.Length > 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IntegerOperation.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches 5 | { 6 | public enum IntegerOperationType 7 | { 8 | Equal, 9 | Greater, 10 | GreaterEqual, 11 | Less, 12 | LessEqual, 13 | NotEqual 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsDirectoryMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches 5 | { 6 | public class IsDirectoryMatch : UrlMatch 7 | { 8 | public IsDirectoryMatch(bool negate) 9 | { 10 | Negate = negate; 11 | } 12 | 13 | public override MatchResults Evaluate(string pattern, RewriteContext context) 14 | { 15 | var res = context.StaticFileProvider.GetFileInfo(pattern).IsDirectory; 16 | return new MatchResults { Success = (res != Negate) }; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/IsFileMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches 5 | { 6 | public class IsFileMatch : UrlMatch 7 | { 8 | public IsFileMatch(bool negate) 9 | { 10 | Negate = negate; 11 | } 12 | 13 | public override MatchResults Evaluate(string pattern, RewriteContext context) 14 | { 15 | var res = context.StaticFileProvider.GetFileInfo(pattern).Exists; 16 | return new MatchResults { Success = (res != Negate) }; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/RegexMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text.RegularExpressions; 5 | 6 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches 7 | { 8 | public class RegexMatch : UrlMatch 9 | { 10 | private readonly Regex _match; 11 | 12 | public RegexMatch(Regex match, bool negate) 13 | { 14 | _match = match; 15 | Negate = negate; 16 | } 17 | 18 | public override MatchResults Evaluate(string pattern, RewriteContext context) 19 | { 20 | var res = _match.Match(pattern); 21 | return new MatchResults { BackReferences = new BackReferenceCollection(res.Groups), Success = (res.Success != Negate) }; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/StringMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches 5 | { 6 | public class StringMatch : UrlMatch 7 | { 8 | private readonly string _value; 9 | private readonly StringOperationType _operation; 10 | private readonly bool _ignoreCase; 11 | 12 | public StringMatch(string value, StringOperationType operation, bool ignoreCase) 13 | { 14 | _value = value; 15 | _operation = operation; 16 | _ignoreCase = ignoreCase; 17 | } 18 | 19 | public override MatchResults Evaluate(string input, RewriteContext context) 20 | { 21 | switch (_operation) 22 | { 23 | case StringOperationType.Equal: 24 | return string.Compare(input, _value, _ignoreCase) == 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure; 25 | case StringOperationType.Greater: 26 | return string.Compare(input, _value, _ignoreCase) > 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure; 27 | case StringOperationType.GreaterEqual: 28 | return string.Compare(input, _value, _ignoreCase) >= 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure; 29 | case StringOperationType.Less: 30 | return string.Compare(input, _value, _ignoreCase) < 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure; 31 | case StringOperationType.LessEqual: 32 | return string.Compare(input, _value, _ignoreCase) <= 0 ? MatchResults.EmptySuccess : MatchResults.EmptyFailure; 33 | default: 34 | return null; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Internal/UrlMatches/StringOperation.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite.Internal.UrlMatches 5 | { 6 | public enum StringOperationType 7 | { 8 | Equal, 9 | Greater, 10 | GreaterEqual, 11 | Less, 12 | LessEqual 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Microsoft.AspNetCore.Rewrite.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ASP.NET Core basic middleware for rewriting URLs. Includes: 5 | * Support for custom URL rewrite rules 6 | * Support for running IIS URL Rewrite module rules 7 | * Support for running Apache mod_rewrite rules. 8 | netstandard2.0 9 | $(NoWarn);CS1591 10 | true 11 | aspnetcore;urlrewrite;mod_rewrite 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Microsoft.AspNetCore.Rewrite.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] 7 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/RewriteBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Rewrite; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Microsoft.AspNetCore.Builder 9 | { 10 | /// 11 | /// Extension methods for the 12 | /// 13 | public static class RewriteBuilderExtensions 14 | { 15 | /// 16 | /// Checks if a given Url matches rules and conditions, and modifies the HttpContext on match. 17 | /// 18 | /// The 19 | /// 20 | public static IApplicationBuilder UseRewriter(this IApplicationBuilder app) 21 | { 22 | if (app == null) 23 | { 24 | throw new ArgumentNullException(nameof(app)); 25 | } 26 | 27 | return app.UseMiddleware(); 28 | } 29 | 30 | /// 31 | /// Checks if a given Url matches rules and conditions, and modifies the HttpContext on match. 32 | /// 33 | /// The 34 | /// Options for rewrite. 35 | /// 36 | public static IApplicationBuilder UseRewriter(this IApplicationBuilder app, RewriteOptions options) 37 | { 38 | if (app == null) 39 | { 40 | throw new ArgumentNullException(nameof(app)); 41 | } 42 | 43 | if (options == null) 44 | { 45 | throw new ArgumentNullException(nameof(options)); 46 | } 47 | 48 | // put middleware in pipeline 49 | return app.UseMiddleware(Options.Create(options)); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/RewriteContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.Extensions.FileProviders; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite 10 | { 11 | /// 12 | /// A context object for 13 | /// 14 | public class RewriteContext 15 | { 16 | /// 17 | /// Gets and sets the 18 | /// 19 | public HttpContext HttpContext { get; set; } 20 | 21 | /// 22 | /// Gets and sets the File Provider for file and directory checks. 23 | /// 24 | public IFileProvider StaticFileProvider { get; set; } 25 | 26 | /// 27 | /// Gets and sets the logger 28 | /// 29 | public ILogger Logger { get; set; } 30 | 31 | /// 32 | /// A shared result that is set appropriately by each rule for the next action that 33 | /// should be taken. See 34 | /// 35 | public RuleResult Result { get; set; } 36 | 37 | internal StringBuilder Builder { get; set; } = new StringBuilder(64); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/RewriteOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | using Microsoft.Extensions.FileProviders; 6 | using Microsoft.AspNetCore.Hosting; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite 9 | { 10 | /// 11 | /// Options for the 12 | /// 13 | public class RewriteOptions 14 | { 15 | /// 16 | /// A list of that will be applied in order upon a request. 17 | /// 18 | public IList Rules { get; } = new List(); 19 | 20 | /// 21 | /// Gets and sets the File Provider for file and directory checks. Defaults to 22 | /// 23 | public IFileProvider StaticFileProvider { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Microsoft.AspNetCore.Rewrite/RuleResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | namespace Microsoft.AspNetCore.Rewrite 5 | { 6 | /// 7 | /// An enum representing the result of a rule. 8 | /// 9 | public enum RuleResult 10 | { 11 | /// 12 | /// Default value, continue applying rules. 13 | /// 14 | ContinueRules, 15 | /// 16 | /// The rule ended the request by providing a response. 17 | /// 18 | EndResponse, 19 | /// 20 | /// Stop applying rules and send context to the next middleware 21 | /// 22 | SkipRemainingRules 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | netcoreapp2.2 6 | $(DeveloperBuildTestTfms) 7 | 8 | $(StandardTestTfms);net461 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Buffering.Tests/Microsoft.AspNetCore.Buffering.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(StandardTestTfms) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.HostFiltering.Tests/Microsoft.AspNetCore.HostFiltering.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(StandardTestTfms) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.HttpOverrides.Tests/IPEndPointParserTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Net; 5 | using Xunit; 6 | 7 | namespace Microsoft.AspNetCore.HttpOverrides.Internal 8 | { 9 | public class IPEndPointParserTests 10 | { 11 | [Theory] 12 | [InlineData("127.0.0.1", "127.0.0.1", 0)] 13 | [InlineData("127.0.0.1:1", "127.0.0.1", 1)] 14 | [InlineData("1", "0.0.0.1", 0)] 15 | [InlineData("1:1", "0.0.0.1", 1)] 16 | [InlineData("::1", "::1", 0)] 17 | [InlineData("[::1]", "::1", 0)] 18 | [InlineData("[::1]:1", "::1", 1)] 19 | public void ParsesCorrectly(string input, string expectedAddress, int expectedPort) 20 | { 21 | IPEndPoint endpoint; 22 | var success = IPEndPointParser.TryParse(input, out endpoint); 23 | Assert.True(success); 24 | Assert.Equal(expectedAddress, endpoint.Address.ToString()); 25 | Assert.Equal(expectedPort, endpoint.Port); 26 | } 27 | 28 | [Theory] 29 | [InlineData(null)] 30 | [InlineData("[::1]:")] 31 | [InlineData("[::1:")] 32 | [InlineData("::1:")] 33 | [InlineData("127:")] 34 | [InlineData("127.0.0.1:")] 35 | [InlineData("")] 36 | [InlineData("[]")] 37 | [InlineData("]")] 38 | [InlineData("]:1")] 39 | public void ShouldNotParse(string input) 40 | { 41 | IPEndPoint endpoint; 42 | var success = IPEndPointParser.TryParse(input, out endpoint); 43 | Assert.False(success); 44 | Assert.Null(endpoint); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.HttpOverrides.Tests/IPNetworkTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | using System.Net; 4 | using Xunit; 5 | 6 | namespace Microsoft.AspNetCore.HttpOverrides 7 | { 8 | public class IPNetworkTest 9 | { 10 | [Theory] 11 | [InlineData("10.1.1.0", 8, "10.1.1.10")] 12 | [InlineData("174.0.0.0", 7, "175.1.1.10")] 13 | [InlineData("10.174.0.0", 15, "10.175.1.10")] 14 | [InlineData("10.168.0.0", 14, "10.171.1.10")] 15 | public void Contains_Positive(string prefixText, int length, string addressText) 16 | { 17 | var network = new IPNetwork(IPAddress.Parse(prefixText), length); 18 | Assert.True(network.Contains(IPAddress.Parse(addressText))); 19 | } 20 | 21 | [Theory] 22 | [InlineData("10.1.0.0", 16, "10.2.1.10")] 23 | [InlineData("174.0.0.0", 7, "173.1.1.10")] 24 | [InlineData("10.174.0.0", 15, "10.173.1.10")] 25 | [InlineData("10.168.0.0", 14, "10.172.1.10")] 26 | public void Contains_Negative(string prefixText, int length, string addressText) 27 | { 28 | var network = new IPNetwork(IPAddress.Parse(prefixText), length); 29 | Assert.False(network.Contains(IPAddress.Parse(addressText))); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.HttpOverrides.Tests/Microsoft.AspNetCore.HttpOverrides.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(StandardTestTfms) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.HttpsPolicy.Tests/Microsoft.AspNetCore.HttpsPolicy.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.2 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.ResponseCompression.Tests/Microsoft.AspNetCore.ResponseCompression.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(StandardTestTfms) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.ResponseCompression.Tests/testfile1kb.txt: -------------------------------------------------------------------------------- 1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/RuleBuilderTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Rewrite.Internal; 8 | using Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite; 9 | using Microsoft.AspNetCore.Rewrite.Internal.UrlActions; 10 | using Xunit; 11 | 12 | namespace Microsoft.AspNetCore.Rewrite.Tests 13 | { 14 | public class RuleBuilderTest 15 | { 16 | [Fact] 17 | // see https://httpd.apache.org/docs/2.4/rewrite/advanced.html#setenvvars 18 | public void AddAction_Throws_ChangeEnvNotSupported() 19 | { 20 | var builder = new RuleBuilder(); 21 | var flags = new Flags(); 22 | flags.SetFlag(FlagType.Env, "rewritten:1"); 23 | 24 | var ex = Assert.Throws(() => builder.AddAction(null, flags)); 25 | Assert.Equal(Resources.Error_ChangeEnvironmentNotSupported, ex.Message); 26 | } 27 | 28 | [Fact] 29 | public void AddAction_DefaultRedirectStatusCode() 30 | { 31 | var builder = new RuleBuilder(); 32 | var flags = new Flags(); 33 | var pattern = new Pattern(new List()); 34 | flags.SetFlag(FlagType.Redirect, string.Empty); 35 | 36 | builder.AddAction(pattern, flags); 37 | var redirectAction = (RedirectAction)builder._actions[0]; 38 | 39 | Assert.Equal(StatusCodes.Status302Found, redirectAction.StatusCode); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/ApacheModRewrite/RuleRegexParserTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite 9 | { 10 | public class RuleRegexParserTest 11 | { 12 | [Fact] 13 | public void RuleRegexParser_ShouldThrowOnNull() 14 | { 15 | Assert.Throws(() => new RuleRegexParser().ParseRuleRegex(null)); 16 | } 17 | 18 | [Fact] 19 | public void RuleRegexParser_ShouldThrowOnEmpty() 20 | { 21 | Assert.Throws(() => new RuleRegexParser().ParseRuleRegex(string.Empty)); 22 | } 23 | 24 | [Fact] 25 | public void RuleRegexParser_RegularRegexExpression() 26 | { 27 | var results = new RuleRegexParser().ParseRuleRegex("(.*)"); 28 | Assert.False(results.Invert); 29 | Assert.Equal("(.*)", results.Operand); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/IISUrlRewrite/RewriteMapParserTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.IO; 5 | using System.Linq; 6 | using System.Xml.Linq; 7 | using Microsoft.AspNetCore.Rewrite.Internal.IISUrlRewrite; 8 | using Xunit; 9 | 10 | namespace Microsoft.AspNetCore.Rewrite.Tests.IISUrlRewrite 11 | { 12 | public class RewriteMapParserTests 13 | { 14 | [Fact] 15 | public void Should_parse_rewrite_map() 16 | { 17 | // arrange 18 | const string expectedMapName = "apiMap"; 19 | const string expectedKey = "api.test.com"; 20 | const string expectedValue = "test.com/api"; 21 | var xml = $@" 22 | 23 | 24 | 25 | 26 | 27 | "; 28 | 29 | // act 30 | var xmlDoc = XDocument.Load(new StringReader(xml), LoadOptions.SetLineInfo); 31 | var xmlRoot = xmlDoc.Descendants(RewriteTags.Rewrite).FirstOrDefault(); 32 | var actualMaps = RewriteMapParser.Parse(xmlRoot); 33 | 34 | // assert 35 | Assert.Equal(1, actualMaps.Count); 36 | 37 | var actualMap = actualMaps[expectedMapName]; 38 | Assert.NotNull(actualMap); 39 | Assert.Equal(expectedMapName, actualMap.Name); 40 | Assert.Equal(expectedValue, actualMap[expectedKey]); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/Microsoft.AspNetCore.Rewrite.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(StandardTestTfms) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ConditionMatchSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text.RegularExpressions; 5 | using Microsoft.AspNetCore.Rewrite.Internal; 6 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class ConditionMatchSegmentTests 12 | { 13 | 14 | [Theory] 15 | [InlineData(1, "foo")] 16 | [InlineData(2, "bar")] 17 | [InlineData(3, "baz")] 18 | public void ConditionMatch_AssertBackreferencesObtainsCorrectValue(int index, string expected) 19 | { 20 | // Arrange 21 | var condMatch = CreateTestMatch(); 22 | var segment = new ConditionMatchSegment(index); 23 | 24 | // Act 25 | var results = segment.Evaluate(null, null, condMatch.BackReferences); 26 | 27 | // Assert 28 | Assert.Equal(expected, results); 29 | } 30 | 31 | private static MatchResults CreateTestMatch() 32 | { 33 | var match = Regex.Match("foo/bar/baz", "(.*)/(.*)/(.*)"); 34 | return new MatchResults { BackReferences = new BackReferenceCollection(match.Groups), Success = match.Success }; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/DateTimeSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 9 | { 10 | public class DateTimeSegmentTests 11 | { 12 | [Theory] 13 | [InlineData("TIME_YEAR")] 14 | [InlineData("TIME_MON")] 15 | [InlineData("TIME_DAY")] 16 | [InlineData("TIME_HOUR")] 17 | [InlineData("TIME_MIN")] 18 | [InlineData("TIME_SEC")] 19 | [InlineData("TIME_WDAY")] 20 | [InlineData("TIME")] 21 | public void DateTime_AssertDoesntThrowOnCheckOfSegment(string input) 22 | { 23 | // Arrange 24 | var segment = new DateTimeSegment(input); 25 | 26 | // Act 27 | var results = segment.Evaluate(null, null, null); 28 | 29 | // TODO testing dates is hard, could use moq 30 | // currently just assert that the segment doesn't throw. 31 | } 32 | 33 | [Theory] 34 | [InlineData("foo", "Unsupported segment: 'foo'")] 35 | [InlineData("wow", "Unsupported segment: 'wow'")] 36 | public void DateTime_AssertThrowsOnInvalidInput(string input, string expected) 37 | { 38 | // Act And Assert 39 | var ex = Assert.Throws(() => new DateTimeSegment(input)); 40 | Assert.Equal(expected, ex.Message); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/HeaderSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 6 | using Microsoft.Net.Http.Headers; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class HeaderSegmentTests 12 | { 13 | [Fact] 14 | public void HeaderSegment_AssertGettingWithHeaderReturnsCorrectValue() 15 | { 16 | // Arrange 17 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 18 | 19 | context.HttpContext.Request.Headers[HeaderNames.Location] = "foo"; 20 | var segment = new HeaderSegment(HeaderNames.Location); 21 | 22 | // Act 23 | var results = segment.Evaluate(context, null, null); 24 | 25 | // Assert 26 | Assert.Equal("foo", results); 27 | } 28 | 29 | [Fact] 30 | public void HeaderSegment_AssertGettingANonExistantHeaderReturnsNull() 31 | { 32 | // Arrange 33 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 34 | var segment = new HeaderSegment(HeaderNames.Location); 35 | 36 | // Act 37 | var results = segment.Evaluate(context, null, null); 38 | 39 | // Assert 40 | Assert.Null(results); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsModSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class IsHttpsModSegmentTests 12 | { 13 | [Theory] 14 | [InlineData("http", "off")] 15 | [InlineData("https", "on")] 16 | public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected) 17 | { 18 | // Arrange 19 | var segement = new IsHttpsModSegment(); 20 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 21 | context.HttpContext.Request.Scheme = input; 22 | 23 | // Act 24 | var results = segement.Evaluate(context, null, null); 25 | 26 | // Assert 27 | Assert.Equal(expected, results); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsHttpsSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class IsHttpsSegmentTests 12 | { 13 | [Theory] 14 | [InlineData("http", "OFF")] 15 | [InlineData("https", "ON")] 16 | public void IsHttps_AssertCorrectBehaviorWhenProvidedHttpContext(string input, string expected) 17 | { 18 | // Arrange 19 | var segement = new IsHttpsUrlSegment(); 20 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 21 | context.HttpContext.Request.Scheme = input; 22 | 23 | // Act 24 | var results = segement.Evaluate(context, null, null); 25 | 26 | // Assert 27 | Assert.Equal(expected, results); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/IsIPV6SegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | 5 | using System.Net; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 8 | using Xunit; 9 | 10 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 11 | { 12 | public class IsIPV6SegmentTests 13 | { 14 | [Fact] 15 | public void IsIPv6_AssertNullRemoteIpAddressReportsCorrectValue() 16 | { 17 | // Arrange 18 | var segement = new IsIPV6Segment(); 19 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 20 | context.HttpContext.Connection.RemoteIpAddress = null; 21 | 22 | // Act 23 | var results = segement.Evaluate(context, null, null); 24 | 25 | // Assert 26 | Assert.Equal("off", results); 27 | } 28 | 29 | [Fact] 30 | public void IsIPv6_AssertCorrectBehaviorWhenIPv6IsUsed() 31 | { 32 | // Arrange 33 | var segement = new IsIPV6Segment(); 34 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 35 | context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); 36 | 37 | // Act 38 | var results = segement.Evaluate(context, null, null); 39 | 40 | // Assert 41 | Assert.Equal("on", results); 42 | } 43 | 44 | [Fact] 45 | public void IsIPv6_AssertCorrectBehaviorWhenIPv4IsUsed() 46 | { 47 | // Arrange 48 | var segement = new IsIPV6Segment(); 49 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 50 | context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("20.30.40.50"); 51 | 52 | // Act 53 | var results = segement.Evaluate(context, null, null); 54 | 55 | // Assert 56 | Assert.Equal("off", results); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LIteralSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 5 | using Xunit; 6 | 7 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 8 | { 9 | public class LiteralSegmentTests 10 | { 11 | [Fact] 12 | public void LiteralSegment_AssertSegmentIsCorrect() 13 | { 14 | // Arrange 15 | var segement = new LiteralSegment("foo"); 16 | 17 | // Act 18 | var results = segement.Evaluate(null, null, null); 19 | 20 | // Assert 21 | Assert.Equal("foo", results); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalAddressSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | 5 | using System.Net; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 8 | using Xunit; 9 | 10 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 11 | { 12 | public class LocalAddressSegmentTests 13 | { 14 | [Fact] 15 | public void LocalAddress_AssertSegmentIsCorrect() 16 | { 17 | // Arrange 18 | var segement = new LocalAddressSegment(); 19 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 20 | context.HttpContext.Connection.LocalIpAddress = IPAddress.Parse("20.30.40.50"); 21 | // Act 22 | var results = segement.Evaluate(context, null, null); 23 | 24 | // Assert 25 | Assert.Equal("20.30.40.50", results); 26 | } 27 | 28 | [Fact] 29 | public void LocalAddress_AssertNullLocalIpAddressReturnsNull() 30 | { 31 | var segement = new LocalAddressSegment(); 32 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 33 | context.HttpContext.Connection.LocalIpAddress = null; 34 | // Act 35 | var results = segement.Evaluate(context, null, null); 36 | 37 | // Assert 38 | Assert.Null( results); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/LocalPortSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | 5 | using System.Globalization; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 8 | using Xunit; 9 | 10 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 11 | { 12 | public class LocalPortSegmentTests 13 | { 14 | [Fact] 15 | public void LocalPortSegment_AssertSegmentIsCorrect() 16 | { 17 | // Arrange 18 | var segement = new LocalPortSegment(); 19 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 20 | context.HttpContext.Connection.LocalPort = 800; 21 | // Act 22 | var results = segement.Evaluate(context, null, null); 23 | 24 | // Assert 25 | Assert.Equal("800", results); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/QueryStringSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 9 | { 10 | public class QueryStringSegmentTests 11 | { 12 | [Fact] 13 | public void QueryString_AssertSegmentIsCorrect() 14 | { 15 | var segement = new QueryStringSegment(); 16 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 17 | context.HttpContext.Request.QueryString = new QueryString("?hey=1"); 18 | 19 | var results = segement.Evaluate(context, null, null); 20 | 21 | Assert.Equal("hey=1", results); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemoteAddressSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Net; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class RemoteAddressSegmentTests 12 | { 13 | [Fact] 14 | public void RemoteAddress_AssertSegmentIsCorrect() 15 | { 16 | // Arrange 17 | var segement = new RemoteAddressSegment(); 18 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 19 | context.HttpContext.Connection.RemoteIpAddress = IPAddress.Parse("20.30.40.50"); 20 | // Act 21 | var results = segement.Evaluate(context, null, null); 22 | 23 | // Assert 24 | Assert.Equal("20.30.40.50", results); 25 | } 26 | 27 | [Fact] 28 | public void RemoteAddress_AssertNullLocalIpAddressReturnsNull() 29 | { 30 | var segement = new RemoteAddressSegment(); 31 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 32 | context.HttpContext.Connection.RemoteIpAddress = null; 33 | // Act 34 | var results = segement.Evaluate(context, null, null); 35 | 36 | // Assert 37 | Assert.Null(results); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RemotePortSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 9 | { 10 | public class RemotePortSegmentTests 11 | { 12 | [Fact] 13 | public void RemotePort_AssertSegmentIsCorrect() 14 | { 15 | // Arrange 16 | var segement = new RemotePortSegment(); 17 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 18 | context.HttpContext.Connection.RemotePort = 800; 19 | // Act 20 | var results = segement.Evaluate(context, null, null); 21 | 22 | // Assert 23 | Assert.Equal("800", results); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestFilenameSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 9 | { 10 | public class RequestFilenameSegmentTests 11 | { 12 | [Fact] 13 | public void RequestFilename_AssertSegmentIsCorrect() 14 | { 15 | // Arrange 16 | var segement = new RequestFileNameSegment(); 17 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 18 | context.HttpContext.Request.Path = new PathString("/foo/bar"); 19 | // Act 20 | var results = segement.Evaluate(context, null, null); 21 | 22 | // Assert 23 | Assert.Equal("/foo/bar", results); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RequestMethodSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 9 | { 10 | public class RequestMethodSegmentTests 11 | { 12 | [Fact] 13 | public void RequestMethod_AssertSegmentIsCorrect() 14 | { 15 | // Arrange 16 | var segement = new RequestMethodSegment(); 17 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 18 | context.HttpContext.Request.Method = HttpMethods.Get; 19 | // Act 20 | var results = segement.Evaluate(context, null, null); 21 | 22 | // Assert 23 | Assert.Equal(HttpMethods.Get, results); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/RuleMatchSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Text.RegularExpressions; 5 | using Microsoft.AspNetCore.Rewrite.Internal; 6 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class RuleMatchSegmentTests 12 | { 13 | [Theory] 14 | [InlineData(1, "foo")] 15 | [InlineData(2, "bar")] 16 | [InlineData(3, "baz")] 17 | public void RuleMatch_AssertBackreferencesObtainsCorrectValue(int index, string expected) 18 | { 19 | // Arrange 20 | var ruleMatch = CreateTestMatch(); 21 | var segment = new RuleMatchSegment(index); 22 | 23 | // Act 24 | var results = segment.Evaluate(null, ruleMatch.BackReferences, null); 25 | 26 | // Assert 27 | Assert.Equal(expected, results); 28 | } 29 | 30 | private static MatchResults CreateTestMatch() 31 | { 32 | var match = Regex.Match("foo/bar/baz", "(.*)/(.*)/(.*)"); 33 | return new MatchResults { BackReferences = new BackReferenceCollection(match.Groups), Success = match.Success }; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/SchemeSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 9 | { 10 | public class SchemeSegmentTests 11 | { 12 | [Fact] 13 | public void SchemeSegment_AssertSegmentIsCorrect() 14 | { 15 | // Arrange 16 | var segement = new SchemeSegment(); 17 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 18 | context.HttpContext.Request.Scheme = "http"; 19 | // Act 20 | var results = segement.Evaluate(context, null, null); 21 | 22 | // Assert 23 | Assert.Equal("http", results); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ServerProtocolSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Http.Features; 6 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class ServerProtocolSegmentTests 12 | { 13 | [Fact] 14 | public void ServerProtocol_AssertSegmentIsCorrect() 15 | { 16 | // Arrange 17 | var segement = new ServerProtocolSegment(); 18 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 19 | context.HttpContext.Features.Set(new HttpRequestFeature { Protocol = "http" }); 20 | 21 | // Act 22 | var results = segement.Evaluate(context, null, null); 23 | 24 | // Assert 25 | Assert.Equal("http", results); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/ToLowerSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | using Microsoft.AspNetCore.Rewrite.Internal; 6 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class ToLowerSegmentTests 12 | { 13 | [Theory] 14 | [InlineData("Hello", "hello")] 15 | [InlineData("WHAT", "what")] 16 | [InlineData("hey", "hey")] 17 | public void ToLower_AssertLowerCaseWorksAppropriately(string input, string expected) 18 | { 19 | // Arrange 20 | var pattern = new Pattern(new List()); 21 | pattern.PatternSegments.Add(new LiteralSegment(input)); 22 | var segement = new ToLowerSegment(pattern); 23 | var context = new RewriteContext(); 24 | 25 | // Act 26 | var results = segement.Evaluate(context, null, null); 27 | 28 | // Assert 29 | Assert.Equal(expected, results); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/PatternSegments/UrlEncodeSegmentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | using Microsoft.AspNetCore.Rewrite.Internal; 6 | using Microsoft.AspNetCore.Rewrite.Internal.PatternSegments; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.PatternSegments 10 | { 11 | public class UrlEncodeSegmentTests 12 | { 13 | [Theory] 14 | [InlineData(" ", "%20")] 15 | [InlineData("x&y", "x%26y")] 16 | [InlineData("hey", "hey")] 17 | public void ToLower_AssertLowerCaseWorksAppropriately(string input, string expected) 18 | { 19 | // Arrange 20 | var pattern = new Pattern(new List()); 21 | pattern.PatternSegments.Add(new LiteralSegment(input)); 22 | var segement = new UrlEncodeSegment(pattern); 23 | var context = new RewriteContext(); 24 | 25 | // Act 26 | var results = segement.Evaluate(context, null, null); 27 | 28 | // Assert 29 | Assert.Equal(expected, results); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/AbortActionTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.UrlActions; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions 9 | { 10 | public class AbortActionTests 11 | { 12 | public void AbortAction_VerifyEndResponseResult() 13 | { 14 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 15 | var action = new AbortAction(); 16 | 17 | action.ApplyAction(context, null, null); 18 | 19 | Assert.Equal(RuleResult.EndResponse, context.Result); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/ForbiddenActionTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.UrlActions; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions 9 | { 10 | public class ForbiddenActionTests 11 | { 12 | [Fact] 13 | public void Forbidden_Verify403IsInStatusCode() 14 | { 15 | 16 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 17 | var action = new ForbiddenAction(); 18 | 19 | action.ApplyAction(context, null, null); 20 | 21 | Assert.Equal(RuleResult.EndResponse, context.Result); 22 | Assert.Equal(StatusCodes.Status403Forbidden, context.HttpContext.Response.StatusCode); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/UrlActions/GoneActionTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal.UrlActions; 6 | using Xunit; 7 | 8 | namespace Microsoft.AspNetCore.Rewrite.Tests.UrlActions 9 | { 10 | public class GoneActionTests 11 | { 12 | [Fact] 13 | public void Gone_Verify410IsInStatusCode() 14 | { 15 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 16 | var action = new GoneAction(); 17 | 18 | action.ApplyAction(context, null, null); 19 | 20 | Assert.Equal(RuleResult.EndResponse, context.Result); 21 | Assert.Equal(StatusCodes.Status410Gone, context.HttpContext.Response.StatusCode); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/UrlMatches/ExactMatchTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Rewrite.Internal; 6 | using Microsoft.AspNetCore.Rewrite.Internal.UrlActions; 7 | using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches; 8 | using Xunit; 9 | 10 | namespace Microsoft.AspNetCore.Rewrite.Tests.UrlMatches 11 | { 12 | public class ExactMatchTests 13 | { 14 | [Theory] 15 | [InlineDataAttribute(true,"string",false,"string",true)] 16 | [InlineDataAttribute(true, "string", true, "string", false)] 17 | [InlineDataAttribute(false, "STRING", false, "string",false)] 18 | [InlineDataAttribute(false, "STRING", true, "string", true)] 19 | public void ExactMatch_Case_Sensitivity_Negate_Tests(bool ignoreCase, string inputString, bool negate, string pattern, bool expectedResult) 20 | { 21 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 22 | var Match = new ExactMatch(ignoreCase, inputString, negate); 23 | var matchResults = Match.Evaluate(pattern, context); 24 | Assert.Equal(expectedResult, matchResults.Success); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/UrlMatches/IntegerMatchTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) .NET Foundation. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Http; 6 | using Microsoft.AspNetCore.Rewrite; 7 | using Microsoft.AspNetCore.Rewrite.Internal; 8 | using Microsoft.AspNetCore.Rewrite.Internal.UrlActions; 9 | using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches; 10 | using Xunit; 11 | 12 | namespace Microsoft.AspNetCore.Rewrite.Tests.UrlMatches 13 | { 14 | public class IntegerMatchTests 15 | { 16 | [Fact] 17 | public void IntegerMatch_Constructor_Integer_Parse_Excetion() 18 | { 19 | var ex = Assert.Throws(() => new IntegerMatch("Not an int", IntegerOperationType.Equal)); 20 | Assert.Equal(ex.Message, Resources.Error_IntegerMatch_FormatExceptionMessage); 21 | } 22 | 23 | [Theory] 24 | [InlineData(1,IntegerOperationType.Equal,"1",true)] 25 | [InlineData(1, IntegerOperationType.NotEqual, "2", true)] 26 | [InlineData(2, IntegerOperationType.Less, "1", true)] 27 | [InlineData(1, IntegerOperationType.LessEqual, "2", false)] 28 | [InlineData(1, IntegerOperationType.Greater, "2", true)] 29 | [InlineData(2, IntegerOperationType.GreaterEqual, "1", false)] 30 | [InlineData(1, IntegerOperationType.Equal, "Not an int", false)] 31 | [InlineData(1, IntegerOperationType.Equal, "", false)] 32 | [InlineData(1, IntegerOperationType.Equal, "2147483648", false)] 33 | public void IntegerMatch_Evaluation_Cases_Tests(int value,IntegerOperationType operation, string input,bool expectedResult) 34 | { 35 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 36 | var integerMatch = new IntegerMatch(value, operation); 37 | var matchResult = integerMatch.Evaluate(input, context); 38 | Assert.Equal(expectedResult, matchResult.Success); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/Microsoft.AspNetCore.Rewrite.Tests/UrlMatches/StringMatchTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Rewrite.Internal.UrlMatches; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Xunit; 8 | 9 | namespace Microsoft.AspNetCore.Rewrite.Tests.UrlMatches 10 | { 11 | public class StringMatchTests 12 | { 13 | [Theory] 14 | [InlineData("hi", StringOperationType.Equal,true,"hi",true)] 15 | [InlineData("a", StringOperationType.Greater, true, "b", true)] 16 | [InlineData("a", StringOperationType.GreaterEqual, true, "b", true)] 17 | [InlineData("b", StringOperationType.Less,true, "a", true)] 18 | [InlineData("b", StringOperationType.LessEqual, true, "a", true)] 19 | [InlineData("", StringOperationType.Equal, true, "", true)] 20 | [InlineData(null, StringOperationType.Equal, true, null, true)] 21 | public void StringMatch_Evaluation_Check_Cases(string value, StringOperationType operation, bool ignoreCase, string input, bool expectedResult) 22 | { 23 | var context = new RewriteContext { HttpContext = new DefaultHttpContext() }; 24 | var stringMatch = new StringMatch(value, operation, ignoreCase); 25 | var matchResult = stringMatch.Evaluate(input, context); 26 | Assert.Equal(expectedResult, matchResult.Success); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /version.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 3.0.0 4 | alpha1 5 | $(VersionPrefix) 6 | $(VersionPrefix)-$(VersionSuffix)-final 7 | t000 8 | a- 9 | $(FeatureBranchVersionPrefix)$(VersionSuffix)-$([System.Text.RegularExpressions.Regex]::Replace('$(FeatureBranchVersionSuffix)', '[^\w-]', '-')) 10 | $(VersionSuffix)-$(BuildNumber) 11 | 12 | 0.6.0 13 | alpha1 14 | $(ExperimentalVersionPrefix) 15 | $(ExperimentalVersionPrefix)-$(ExperimentalVersionSuffix)-final 16 | $(ExperimentalVersionSuffix)-$(BuildNumber) 17 | 18 | 19 | --------------------------------------------------------------------------------