// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Reflection; 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; using Microsoft.Framework.Runtime; using Microsoft.Framework.Runtime.Infrastructure; namespace Microsoft.AspNet.TestHost { public class TestServer : IServerFactory, IDisposable { private const string DefaultEnvironmentName = "Development"; private const string ServerName = nameof(TestServer); private static readonly ServerInformation ServerInfo = new ServerInformation(); private Func _appDelegate; private IDisposable _appInstance; private bool _disposed = false; public TestServer(IConfiguration config, IServiceProvider serviceProvider, Action appStartup) { var appEnv = serviceProvider.GetRequiredService(); HostingContext hostContext = new HostingContext() { ApplicationName = appEnv.ApplicationName, Configuration = config, ServerFactory = this, Services = serviceProvider, ApplicationStartup = appStartup }; var engine = serviceProvider.GetRequiredService(); _appInstance = engine.Start(hostContext); } public Uri BaseAddress { get; set; } = new Uri("http://localhost/"); public static TestServer Create(Action app) { return Create(CallContextServiceLocator.Locator.ServiceProvider, app); } public static TestServer Create(IServiceProvider serviceProvider, Action app) { var services = HostingServices.Create(serviceProvider); services.AddSingleton(); var appServices = services.BuildServiceProvider(); var config = new Configuration(); return new TestServer(config, appServices, app); } public HttpMessageHandler CreateHandler() { var pathBase = BaseAddress == null ? PathString.Empty : PathString.FromUriComponent(BaseAddress); if (pathBase.Equals(new PathString("/"))) { // When we just have http://host/ the trailing slash is really part of the Path, not the PathBase. pathBase = PathString.Empty; } return new ClientHandler(Invoke, pathBase); } public HttpClient CreateClient() { return new HttpClient(CreateHandler()) { BaseAddress = BaseAddress }; } /// /// Begins constructing a request message for submission. /// /// /// to use in constructing additional request details. public RequestBuilder CreateRequest(string path) { return new RequestBuilder(this, path); } public IServerInformation Initialize(IConfiguration configuration) { return ServerInfo; } public IDisposable Start(IServerInformation serverInformation, Func application) { if (!(serverInformation.GetType() == typeof(ServerInformation))) { throw new ArgumentException(string.Format("The server must be {0}", ServerName), "serverInformation"); } _appDelegate = application; return this; } public Task Invoke(object env) { if (_disposed) { throw new ObjectDisposedException(GetType().FullName); } return _appDelegate(env); } public void Dispose() { _disposed = true; _appInstance.Dispose(); } private class ServerInformation : IServerInformation { public string Name { get { return TestServer.ServerName; } } } private class ConfigureTestHostingEnvironment : ConfigureHostingEnvironment { public ConfigureTestHostingEnvironment() : base(env => env.EnvironmentName = DefaultEnvironmentName) { } } } }