diff --git a/src/Microsoft.AspNet.TestHost/ClientHandler.cs b/src/Microsoft.AspNet.TestHost/ClientHandler.cs index 29400083e8..b23dffbe70 100644 --- a/src/Microsoft.AspNet.TestHost/ClientHandler.cs +++ b/src/Microsoft.AspNet.TestHost/ClientHandler.cs @@ -24,12 +24,13 @@ namespace Microsoft.AspNet.TestHost public class ClientHandler : HttpMessageHandler { private readonly Func _next; + private readonly PathString _pathBase; /// /// Create a new handler. /// /// The pipeline entry point. - public ClientHandler(Func next) + public ClientHandler(Func next, PathString pathBase) { if (next == null) { @@ -37,6 +38,7 @@ namespace Microsoft.AspNet.TestHost } _next = next; + _pathBase = pathBase; } /// @@ -55,7 +57,7 @@ namespace Microsoft.AspNet.TestHost throw new ArgumentNullException("request"); } - var state = new RequestState(request, cancellationToken); + var state = new RequestState(request, _pathBase, cancellationToken); var requestContent = request.Content ?? new StreamContent(Stream.Null); var body = await requestContent.ReadAsStreamAsync(); if (body.CanSeek) @@ -95,7 +97,7 @@ namespace Microsoft.AspNet.TestHost private ResponseStream _responseStream; private ResponseFeature _responseFeature; - internal RequestState(HttpRequestMessage request, CancellationToken cancellationToken) + internal RequestState(HttpRequestMessage request, PathString pathBase, CancellationToken cancellationToken) { _request = request; _responseTcs = new TaskCompletionSource(); @@ -118,8 +120,20 @@ namespace Microsoft.AspNet.TestHost serverRequest.Protocol = "HTTP/" + request.Version.ToString(2); serverRequest.Scheme = request.RequestUri.Scheme; serverRequest.Method = request.Method.ToString(); - serverRequest.Path = PathString.FromUriComponent(request.RequestUri); - serverRequest.PathBase = PathString.Empty; + + var fullPath = PathString.FromUriComponent(request.RequestUri); + PathString remainder; + if (fullPath.StartsWithSegments(pathBase, out remainder)) + { + serverRequest.PathBase = pathBase; + serverRequest.Path = remainder; + } + else + { + serverRequest.PathBase = PathString.Empty; + serverRequest.Path = fullPath; + } + serverRequest.QueryString = QueryString.FromUriComponent(request.RequestUri); // TODO: serverRequest.CallCancelled = cancellationToken; diff --git a/src/Microsoft.AspNet.TestHost/TestServer.cs b/src/Microsoft.AspNet.TestHost/TestServer.cs index 977623c3d0..8a98adb5ad 100644 --- a/src/Microsoft.AspNet.TestHost/TestServer.cs +++ b/src/Microsoft.AspNet.TestHost/TestServer.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Hosting.Server; +using Microsoft.AspNet.Http; using Microsoft.Framework.ConfigurationModel; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection.Fallback; @@ -41,6 +42,8 @@ namespace Microsoft.AspNet.TestHost _appInstance = engine.Start(hostContext); } + public Uri BaseAddress { get; set; } = new Uri("http://localhost/"); + public static TestServer Create(Action app) { return Create(provider: CallContextServiceLocator.Locator.ServiceProvider, app: app); @@ -68,12 +71,13 @@ namespace Microsoft.AspNet.TestHost public HttpMessageHandler CreateHandler() { - return new ClientHandler(Invoke); + var pathBase = BaseAddress == null ? PathString.Empty : PathString.FromUriComponent(BaseAddress); + return new ClientHandler(Invoke, pathBase); } public HttpClient CreateClient() { - return new HttpClient(CreateHandler()) { BaseAddress = new Uri("http://localhost/") }; + return new HttpClient(CreateHandler()) { BaseAddress = BaseAddress }; } /// diff --git a/test/Microsoft.AspNet.TestHost.Tests/ClientHandlerTests.cs b/test/Microsoft.AspNet.TestHost.Tests/ClientHandlerTests.cs index 623a0bc395..13b6f085c7 100644 --- a/test/Microsoft.AspNet.TestHost.Tests/ClientHandlerTests.cs +++ b/test/Microsoft.AspNet.TestHost.Tests/ClientHandlerTests.cs @@ -28,8 +28,8 @@ namespace Microsoft.AspNet.TestHost Assert.Equal("HTTP/1.1", context.Request.Protocol); Assert.Equal("GET", context.Request.Method); Assert.Equal("https", context.Request.Scheme); - Assert.Equal(string.Empty, context.Request.PathBase.Value); - Assert.Equal("/A/Path/and/file.txt", context.Request.Path.Value); + Assert.Equal("/A/Path", context.Request.PathBase.Value); + Assert.Equal("/and/file.txt", context.Request.Path.Value); Assert.Equal("?and=query", context.Request.QueryString.Value); Assert.NotNull(context.Request.Body); Assert.NotNull(context.Request.Headers); @@ -40,7 +40,7 @@ namespace Microsoft.AspNet.TestHost Assert.Equal("example.com", context.Request.Host.Value); return Task.FromResult(0); - }); + }, new PathString("/A/Path")); var httpClient = new HttpClient(handler); return httpClient.GetAsync("https://example.com/A/Path/and/file.txt?and=query"); } @@ -57,7 +57,7 @@ namespace Microsoft.AspNet.TestHost context.Response.Headers["TestHeader"] = "TestValue:" + requestCount++; return Task.FromResult(0); - }); + }, PathString.Empty); HttpMessageInvoker invoker = new HttpMessageInvoker(handler); HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, "https://example.com/"); @@ -79,7 +79,7 @@ namespace Microsoft.AspNet.TestHost context.Response.Headers["TestHeader"] = "TestValue"; return Task.FromResult(0); - }); + }, PathString.Empty); var httpClient = new HttpClient(handler); HttpResponseMessage response = await httpClient.GetAsync("https://example.com/"); Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First()); @@ -93,7 +93,7 @@ namespace Microsoft.AspNet.TestHost { block.WaitOne(); return Task.FromResult(0); - }); + }, PathString.Empty); var httpClient = new HttpClient(handler); Task task = httpClient.GetAsync("https://example.com/"); Assert.False(task.IsCompleted); @@ -113,7 +113,7 @@ namespace Microsoft.AspNet.TestHost await context.Response.WriteAsync("BodyStarted,"); block.WaitOne(); await context.Response.WriteAsync("BodyFinished"); - }); + }, PathString.Empty); var httpClient = new HttpClient(handler); HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpCompletionOption.ResponseHeadersRead); @@ -133,7 +133,7 @@ namespace Microsoft.AspNet.TestHost context.Response.Body.Flush(); block.WaitOne(); await context.Response.WriteAsync("BodyFinished"); - }); + }, PathString.Empty); var httpClient = new HttpClient(handler); HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpCompletionOption.ResponseHeadersRead); @@ -153,7 +153,7 @@ namespace Microsoft.AspNet.TestHost context.Response.Body.Flush(); block.WaitOne(); return Task.FromResult(0); - }); + }, PathString.Empty); var httpClient = new HttpClient(handler); HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpCompletionOption.ResponseHeadersRead); @@ -179,7 +179,7 @@ namespace Microsoft.AspNet.TestHost context.Response.Body.Flush(); block.WaitOne(); return Task.FromResult(0); - }); + }, PathString.Empty); var httpClient = new HttpClient(handler); HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpCompletionOption.ResponseHeadersRead); @@ -201,7 +201,7 @@ namespace Microsoft.AspNet.TestHost var handler = new ClientHandler(env => { throw new InvalidOperationException("Test Exception"); - }); + }, PathString.Empty); var httpClient = new HttpClient(handler); return Assert.ThrowsAsync(() => httpClient.GetAsync("https://example.com/", HttpCompletionOption.ResponseHeadersRead)); @@ -218,7 +218,7 @@ namespace Microsoft.AspNet.TestHost await context.Response.WriteAsync("BodyStarted"); block.WaitOne(); throw new InvalidOperationException("Test Exception"); - }); + }, PathString.Empty); var httpClient = new HttpClient(handler); HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpCompletionOption.ResponseHeadersRead);