| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT license.
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Http.Features;
- using Microsoft.AspNetCore.TestHost;
- namespace Microsoft.AspNetCore.Builder.Extensions;
- public class UsePathBaseExtensionsTests
- {
- [Theory]
- [InlineData(null)]
- [InlineData("")]
- [InlineData("/")]
- public void EmptyOrNullPathBase_DoNotAddMiddleware(string? pathBase)
- {
- // Arrange
- var useCalled = false;
- var builder = new ApplicationBuilderWrapper(CreateBuilder(), () => useCalled = true)
- .UsePathBase(pathBase);
- // Act
- builder.Build();
- // Assert
- Assert.False(useCalled);
- }
- private class ApplicationBuilderWrapper : IApplicationBuilder
- {
- private readonly IApplicationBuilder _wrappedBuilder;
- private readonly Action _useCallback;
- public ApplicationBuilderWrapper(IApplicationBuilder applicationBuilder, Action useCallback)
- {
- _wrappedBuilder = applicationBuilder;
- _useCallback = useCallback;
- }
- public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
- {
- _useCallback();
- return _wrappedBuilder.Use(middleware);
- }
- public IServiceProvider ApplicationServices
- {
- get { return _wrappedBuilder.ApplicationServices; }
- set { _wrappedBuilder.ApplicationServices = value; }
- }
- public IDictionary<string, object?> Properties => _wrappedBuilder.Properties;
- public IFeatureCollection ServerFeatures => _wrappedBuilder.ServerFeatures;
- public RequestDelegate Build() => _wrappedBuilder.Build();
- public IApplicationBuilder New() => _wrappedBuilder.New();
- }
- [Theory]
- [InlineData("/base", "", "/base", "/base", "")]
- [InlineData("/base", "", "/base/", "/base", "/")]
- [InlineData("/base", "", "/base/something", "/base", "/something")]
- [InlineData("/base", "", "/base/something/", "/base", "/something/")]
- [InlineData("/base/more", "", "/base/more", "/base/more", "")]
- [InlineData("/base/more", "", "/base/more/something", "/base/more", "/something")]
- [InlineData("/base/more", "", "/base/more/something/", "/base/more", "/something/")]
- [InlineData("/base", "/oldbase", "/base", "/oldbase/base", "")]
- [InlineData("/base", "/oldbase", "/base/", "/oldbase/base", "/")]
- [InlineData("/base", "/oldbase", "/base/something", "/oldbase/base", "/something")]
- [InlineData("/base", "/oldbase", "/base/something/", "/oldbase/base", "/something/")]
- [InlineData("/base/more", "/oldbase", "/base/more", "/oldbase/base/more", "")]
- [InlineData("/base/more", "/oldbase", "/base/more/something", "/oldbase/base/more", "/something")]
- [InlineData("/base/more", "/oldbase", "/base/more/something/", "/oldbase/base/more", "/something/")]
- public Task RequestPathBaseContainingPathBase_IsSplit(string registeredPathBase, string pathBase, string requestPath, string expectedPathBase, string expectedPath)
- {
- return TestPathBase(registeredPathBase, pathBase, requestPath, expectedPathBase, expectedPath);
- }
- [Theory]
- [InlineData("/base", "", "/something", "", "/something")]
- [InlineData("/base", "", "/baseandsomething", "", "/baseandsomething")]
- [InlineData("/base", "", "/ba", "", "/ba")]
- [InlineData("/base", "", "/ba/se", "", "/ba/se")]
- [InlineData("/base", "/oldbase", "/something", "/oldbase", "/something")]
- [InlineData("/base", "/oldbase", "/baseandsomething", "/oldbase", "/baseandsomething")]
- [InlineData("/base", "/oldbase", "/ba", "/oldbase", "/ba")]
- [InlineData("/base", "/oldbase", "/ba/se", "/oldbase", "/ba/se")]
- public Task RequestPathBaseNotContainingPathBase_IsNotSplit(string registeredPathBase, string pathBase, string requestPath, string expectedPathBase, string expectedPath)
- {
- return TestPathBase(registeredPathBase, pathBase, requestPath, expectedPathBase, expectedPath);
- }
- [Theory]
- [InlineData("", "", "/", "", "/")]
- [InlineData("/", "", "/", "", "/")]
- [InlineData("/base", "", "/base/", "/base", "/")]
- [InlineData("/base/", "", "/base", "/base", "")]
- [InlineData("/base/", "", "/base/", "/base", "/")]
- [InlineData("", "/oldbase", "/", "/oldbase", "/")]
- [InlineData("/", "/oldbase", "/", "/oldbase", "/")]
- [InlineData("/base", "/oldbase", "/base/", "/oldbase/base", "/")]
- [InlineData("/base/", "/oldbase", "/base", "/oldbase/base", "")]
- [InlineData("/base/", "/oldbase", "/base/", "/oldbase/base", "/")]
- public Task PathBaseNeverEndsWithSlash(string registeredPathBase, string pathBase, string requestPath, string expectedPathBase, string expectedPath)
- {
- return TestPathBase(registeredPathBase, pathBase, requestPath, expectedPathBase, expectedPath);
- }
- [Theory]
- [InlineData("/base", "", "/Base/Something", "/Base", "/Something")]
- [InlineData("/base", "/OldBase", "/Base/Something", "/OldBase/Base", "/Something")]
- public Task PathBaseAndPathPreserveRequestCasing(string registeredPathBase, string pathBase, string requestPath, string expectedPathBase, string expectedPath)
- {
- return TestPathBase(registeredPathBase, pathBase, requestPath, expectedPathBase, expectedPath);
- }
- [Theory]
- [InlineData("/b♫se", "", "/b♫se/something", "/b♫se", "/something")]
- [InlineData("/b♫se", "", "/B♫se/something", "/B♫se", "/something")]
- [InlineData("/b♫se", "", "/b♫se/Something", "/b♫se", "/Something")]
- [InlineData("/b♫se", "/oldb♫se", "/b♫se/something", "/oldb♫se/b♫se", "/something")]
- [InlineData("/b♫se", "/oldb♫se", "/b♫se/Something", "/oldb♫se/b♫se", "/Something")]
- [InlineData("/b♫se", "/oldb♫se", "/B♫se/something", "/oldb♫se/B♫se", "/something")]
- public Task PathBaseCanHaveUnicodeCharacters(string registeredPathBase, string pathBase, string requestPath, string expectedPathBase, string expectedPath)
- {
- return TestPathBase(registeredPathBase, pathBase, requestPath, expectedPathBase, expectedPath);
- }
- [Theory]
- [InlineData("/b%42", "", "/b%42/something%42", "/b%42", "/something%42")]
- [InlineData("/b%42", "", "/B%42/something%42", "/B%42", "/something%42")]
- [InlineData("/b%42", "", "/b%42/Something%42", "/b%42", "/Something%42")]
- [InlineData("/b%42", "/oldb%42", "/b%42/something%42", "/oldb%42/b%42", "/something%42")]
- [InlineData("/b%42", "/oldb%42", "/b%42/Something%42", "/oldb%42/b%42", "/Something%42")]
- [InlineData("/b%42", "/oldb%42", "/B%42/something%42", "/oldb%42/B%42", "/something%42")]
- public Task PathBaseCanHavePercentCharacters(string registeredPathBase, string pathBase, string requestPath, string expectedPathBase, string expectedPath)
- {
- return TestPathBase(registeredPathBase, pathBase, requestPath, expectedPathBase, expectedPath);
- }
- [Fact]
- public async Task PathBaseWorksAfterUseRoutingIfGlobalRouteBuilderUsed()
- {
- var builder = WebApplication.CreateBuilder();
- builder.WebHost.UseTestServer();
- await using var app = builder.Build();
- app.UseRouting();
- app.UsePathBase("/base");
- app.UseEndpoints(endpoints =>
- {
- endpoints.Map("/path", context => context.Response.WriteAsync("Response"));
- });
- await app.StartAsync();
- using var server = app.GetTestServer();
- var response = await server.CreateClient().GetStringAsync("/base/path");
- Assert.Equal("Response", response);
- }
- [Fact]
- public async Task PathBaseWorksBeforeUseRoutingIfGlobalRouteBuilderUsed()
- {
- var builder = WebApplication.CreateBuilder();
- builder.WebHost.UseTestServer();
- await using var app = builder.Build();
- app.UsePathBase("/base");
- app.UseRouting();
- app.MapGet("/path", context => context.Response.WriteAsync("Response"));
- await app.StartAsync();
- using var server = app.GetTestServer();
- var response = await server.CreateClient().GetStringAsync("/base/path");
- Assert.Equal("Response", response);
- }
- [Fact]
- public async Task PathBaseWorksWithoutUseRoutingWithWebApplication()
- {
- var builder = WebApplication.CreateBuilder();
- builder.WebHost.UseTestServer();
- await using var app = builder.Build();
- app.UsePathBase("/base");
- app.MapGet("/path", context => context.Response.WriteAsync("Response"));
- await app.StartAsync();
- using var server = app.GetTestServer();
- var response = await server.CreateClient().GetStringAsync("/base/path");
- Assert.Equal("Response", response);
- }
- private static async Task TestPathBase(string registeredPathBase, string pathBase, string requestPath, string expectedPathBase, string expectedPath)
- {
- HttpContext requestContext = CreateRequest(pathBase, requestPath);
- var builder = CreateBuilder()
- .UsePathBase(new PathString(registeredPathBase));
- builder.Run(context =>
- {
- context.Items["test.Path"] = context.Request.Path;
- context.Items["test.PathBase"] = context.Request.PathBase;
- return Task.FromResult(0);
- });
- await builder.Build().Invoke(requestContext);
- // Assert path and pathBase are split after middleware
- Assert.Equal(expectedPath, ((PathString?)requestContext.Items["test.Path"])!.Value.Value);
- Assert.Equal(expectedPathBase, ((PathString?)requestContext.Items["test.PathBase"])!.Value.Value);
- // Assert path and pathBase are reset after request
- Assert.Equal(pathBase, requestContext.Request.PathBase.Value);
- Assert.Equal(requestPath, requestContext.Request.Path.Value);
- }
- private static HttpContext CreateRequest(string pathBase, string requestPath)
- {
- HttpContext context = new DefaultHttpContext();
- context.Request.PathBase = new PathString(pathBase);
- context.Request.Path = new PathString(requestPath);
- return context;
- }
- private static ApplicationBuilder CreateBuilder()
- {
- return new ApplicationBuilder(new DummyServiceProvider());
- }
- private class DummyServiceProvider : IServiceProvider
- {
- private readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
- public void AddService(Type type, object value) => _services[type] = value;
- public object? GetService(Type serviceType)
- {
- if (serviceType == typeof(IServiceProvider))
- {
- return this;
- }
- if (_services.TryGetValue(serviceType, out var value))
- {
- return value;
- }
- return null;
- }
- }
- }
|