11// Copyright (c) Martin Costello, 2024. All rights reserved. 
22// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. 
33
4+ using  System . Net ; 
45using  System . Security . Cryptography . X509Certificates ; 
56using  Microsoft . AspNetCore . Hosting ; 
6- using  Microsoft . AspNetCore . Hosting . Server ; 
7- using  Microsoft . AspNetCore . Hosting . Server . Features ; 
8- using  Microsoft . Extensions . DependencyInjection ; 
9- using  Microsoft . Extensions . Hosting ; 
107
118namespace  TodoApp ; 
129
@@ -16,98 +13,22 @@ namespace TodoApp;
1613/// </summary> 
1714public  sealed  class  HttpServerFixture  :  TodoAppFixture 
1815{ 
19-     private  bool  _disposed ; 
20-     private  IHost ?  _host ; 
21- 
22-     public  string  ServerAddress 
16+     public  HttpServerFixture ( ) 
2317    { 
24-         get 
25-         { 
26-             EnsureServer ( ) ; 
27-             return  ClientOptions . BaseAddress . ToString ( ) ; 
28-         } 
18+         // Configure the address for the server to listen on for HTTPS 
19+         // requests on a dynamic port. with a self-signed TLS certificate. 
20+         UseKestrel ( 
21+             ( server )  =>  server . Listen ( 
22+                 IPAddress . Loopback ,  0 ,  ( listener )  =>  listener . UseHttps ( 
23+                     ( https )  =>  https . ServerCertificate  =  X509CertificateLoader . LoadPkcs12FromFile ( "localhost-dev.pfx" ,  "Pa55w0rd!" ) ) ) ) ; 
2924    } 
3025
31-     public  override   IServiceProvider   Services 
26+     public  string   ServerAddress 
3227    { 
3328        get 
3429        { 
35-             EnsureServer ( ) ; 
36-             return  _host ! . Services ! ; 
37-         } 
38-     } 
39- 
40-     protected  override  void  ConfigureWebHost ( IWebHostBuilder  builder ) 
41-     { 
42-         base . ConfigureWebHost ( builder ) ; 
43- 
44-         // Configure a self-signed TLS certificate for HTTPS 
45-         builder . ConfigureKestrel ( 
46-             serverOptions =>  serverOptions . ConfigureHttpsDefaults ( 
47-                 httpsOptions =>  X509CertificateLoader . LoadPkcs12FromFile ( "localhost-dev.pfx" ,  "Pa55w0rd!" ) ) ) ; 
48- 
49-         // Configure the server address for the server to 
50-         // listen on for HTTPS requests on a dynamic port. 
51-         builder . UseUrls ( "https://127.0.0.1:0" ) ; 
52-     } 
53- 
54-     protected  override  IHost  CreateHost ( IHostBuilder  builder ) 
55-     { 
56-         // Create the host for TestServer now before we 
57-         // modify the builder to use Kestrel instead. 
58-         var  testHost  =  builder . Build ( ) ; 
59- 
60-         // Modify the host builder to use Kestrel instead 
61-         // of TestServer so we can listen on a real address. 
62-         builder . ConfigureWebHost ( webHostBuilder =>  webHostBuilder . UseKestrel ( ) ) ; 
63- 
64-         // Create and start the Kestrel server before the test server, 
65-         // otherwise due to the way the deferred host builder works 
66-         // for minimal hosting, the server will not get "initialized 
67-         // enough" for the address it is listening on to be available. 
68-         // See https://github.com/dotnet/aspnetcore/issues/33846. 
69-         _host  =  builder . Build ( ) ; 
70-         _host . Start ( ) ; 
71- 
72-         // Extract the selected dynamic port out of the Kestrel server 
73-         // and assign it onto the client options for convenience so it 
74-         // "just works" as otherwise it'll be the default http://localhost 
75-         // URL, which won't route to the Kestrel-hosted HTTP server. 
76-         var  server  =  _host . Services . GetRequiredService < IServer > ( ) ; 
77-         var  addresses  =  server . Features . Get < IServerAddressesFeature > ( ) ; 
78- 
79-         ClientOptions . BaseAddress  =  addresses ! . Addresses 
80-             . Select ( x =>  new  Uri ( x ) ) 
81-             . Last ( ) ; 
82- 
83-         // Return the host that uses TestServer, rather than the real one. 
84-         // Otherwise the internals will complain about the host's server 
85-         // not being an instance of the concrete type TestServer. 
86-         // See https://github.com/dotnet/aspnetcore/pull/34702. 
87-         return  testHost ; 
88-     } 
89- 
90-     protected  override  void  Dispose ( bool  disposing ) 
91-     { 
92-         base . Dispose ( disposing ) ; 
93- 
94-         if  ( ! _disposed ) 
95-         { 
96-             if  ( disposing ) 
97-             { 
98-                 _host ? . Dispose ( ) ; 
99-             } 
100- 
101-             _disposed  =  true ; 
102-         } 
103-     } 
104- 
105-     private  void  EnsureServer ( ) 
106-     { 
107-         if  ( _host  is  null ) 
108-         { 
109-             // This forces WebApplicationFactory to bootstrap the server 
110-             using  var  _  =  CreateDefaultClient ( ) ; 
30+             StartServer ( ) ; 
31+             return  ClientOptions . BaseAddress . ToString ( ) ; 
11132        } 
11233    } 
11334} 
0 commit comments