4
4
using System ;
5
5
using System . Collections ;
6
6
using System . Collections . Generic ;
7
+ using System . Diagnostics . CodeAnalysis ;
7
8
using System . IO ;
9
+ using System . Linq ;
8
10
using System . Net . WebSockets ;
9
11
using System . Text ;
10
12
using System . Threading ;
11
13
using System . Threading . Tasks ;
12
14
using System . Web ;
13
15
using Microsoft . AspNetCore . Hosting ;
14
16
using Microsoft . Extensions . Logging ;
17
+ using Microsoft . WebAssembly . AppHost . DevServer ;
15
18
using Microsoft . WebAssembly . Diagnostics ;
16
19
17
20
#nullable enable
@@ -44,7 +47,7 @@ public static async Task<int> InvokeAsync(CommonConfiguration commonArgs,
44
47
45
48
private async Task RunAsync ( ILoggerFactory loggerFactory , CancellationToken token )
46
49
{
47
- if ( _args . CommonConfig . Debugging )
50
+ if ( _args . CommonConfig . Debugging && ! _args . CommonConfig . UseStaticWebAssets )
48
51
{
49
52
ProxyOptions options = _args . CommonConfig . ToProxyOptions ( ) ;
50
53
_ = Task . Run ( ( ) => DebugProxyHost . RunDebugProxyAsync ( options , Array . Empty < string > ( ) , loggerFactory , token ) , token )
@@ -75,8 +78,7 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke
75
78
? aspnetUrls . Split ( ';' , StringSplitOptions . RemoveEmptyEntries )
76
79
: new string [ ] { $ "http://127.0.0.1:{ _args . CommonConfig . HostProperties . WebServerPort } ", "https://127.0.0.1:0" } ;
77
80
78
- ( ServerURLs serverURLs , IWebHost host ) = await StartWebServerAsync ( _args . CommonConfig . AppPath ,
79
- _args . ForwardConsoleOutput ?? false ,
81
+ ( ServerURLs serverURLs , IWebHost host ) = await StartWebServerAsync ( _args ,
80
82
urls ,
81
83
token ) ;
82
84
@@ -85,32 +87,104 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke
85
87
foreach ( string url in fullUrls )
86
88
Console . WriteLine ( $ "App url: { url } ") ;
87
89
90
+ if ( serverURLs . DebugPath != null )
91
+ {
92
+ Console . WriteLine ( $ "Debug at url: { BuildUrl ( serverURLs . Http , serverURLs . DebugPath , string . Empty ) } ") ;
93
+
94
+ if ( serverURLs . Https != null )
95
+ Console . WriteLine ( $ "Debug at url: { BuildUrl ( serverURLs . Https , serverURLs . DebugPath , string . Empty ) } ") ;
96
+ }
97
+
88
98
await host . WaitForShutdownAsync ( token ) ;
89
99
}
90
100
91
- private async Task < ( ServerURLs , IWebHost ) > StartWebServerAsync ( string appPath , bool forwardConsole , string [ ] urls , CancellationToken token )
101
+ private async Task < ( ServerURLs , IWebHost ) > StartWebServerAsync ( BrowserArguments args , string [ ] urls , CancellationToken token )
92
102
{
93
- WasmTestMessagesProcessor ? logProcessor = null ;
94
- if ( forwardConsole )
103
+ Func < WebSocket , Task > ? onConsoleConnected = null ;
104
+ if ( args . ForwardConsoleOutput ?? false )
95
105
{
96
- logProcessor = new ( _logger ) ;
106
+ WasmTestMessagesProcessor logProcessor = new ( _logger ) ;
107
+ onConsoleConnected = socket => RunConsoleMessagesPump ( socket , logProcessor ! , token ) ;
97
108
}
98
109
99
- WebServerOptions options = new
100
- (
101
- OnConsoleConnected : forwardConsole
102
- ? socket => RunConsoleMessagesPump ( socket , logProcessor ! , token )
103
- : null ,
104
- ContentRootPath : Path . GetFullPath ( appPath ) ,
105
- WebServerUseCors : true ,
106
- WebServerUseCrossOriginPolicy : true ,
107
- Urls : urls
108
- ) ;
109
-
110
- ( ServerURLs serverURLs , IWebHost host ) = await WebServer . StartAsync ( options , _logger , token ) ;
111
- return ( serverURLs , host ) ;
110
+ // If we are using new browser template, use dev server
111
+ if ( args . CommonConfig . UseStaticWebAssets )
112
+ {
113
+ DevServerOptions devServerOptions = CreateDevServerOptions ( args , urls , onConsoleConnected ) ;
114
+ return await DevServer . DevServer . StartAsync ( devServerOptions , _logger , token ) ;
115
+ }
116
+
117
+ // Otherwise for old template, use web server
118
+ WebServerOptions webServerOptions = CreateWebServerOptions ( urls , args . CommonConfig . AppPath , onConsoleConnected ) ;
119
+ return await WebServer . StartAsync ( webServerOptions , _logger , token ) ;
112
120
}
113
121
122
+ private static WebServerOptions CreateWebServerOptions ( string [ ] urls , string appPath , Func < WebSocket , Task > ? onConsoleConnected ) => new
123
+ (
124
+ OnConsoleConnected : onConsoleConnected ,
125
+ ContentRootPath : Path . GetFullPath ( appPath ) ,
126
+ WebServerUseCors : true ,
127
+ WebServerUseCrossOriginPolicy : true ,
128
+ Urls : urls
129
+ ) ;
130
+
131
+ private static DevServerOptions CreateDevServerOptions ( BrowserArguments args , string [ ] urls , Func < WebSocket , Task > ? onConsoleConnected )
132
+ {
133
+ const string staticWebAssetsV1Extension = ".StaticWebAssets.xml" ;
134
+ const string staticWebAssetsV2Extension = ".staticwebassets.runtime.json" ;
135
+
136
+ DevServerOptions ? devServerOptions = null ;
137
+
138
+ string appPath = args . CommonConfig . AppPath ;
139
+ if ( args . CommonConfig . HostProperties . MainAssembly != null )
140
+ {
141
+ // If we have main assembly name, try to find static web assets manifest by precise name.
142
+
143
+ var mainAssemblyPath = Path . Combine ( appPath , args . CommonConfig . HostProperties . MainAssembly ) ;
144
+ var staticWebAssetsPath = Path . ChangeExtension ( mainAssemblyPath , staticWebAssetsV2Extension ) ;
145
+ if ( File . Exists ( staticWebAssetsPath ) )
146
+ {
147
+ devServerOptions = CreateDevServerOptions ( urls , staticWebAssetsPath , onConsoleConnected ) ;
148
+ }
149
+ else
150
+ {
151
+ staticWebAssetsPath = Path . ChangeExtension ( mainAssemblyPath , staticWebAssetsV1Extension ) ;
152
+ if ( File . Exists ( staticWebAssetsPath ) )
153
+ devServerOptions = CreateDevServerOptions ( urls , staticWebAssetsPath , onConsoleConnected ) ;
154
+ }
155
+
156
+ if ( devServerOptions == null )
157
+ devServerOptions = CreateDevServerOptions ( urls , mainAssemblyPath , onConsoleConnected ) ;
158
+ }
159
+ else
160
+ {
161
+ // If we don't have main assembly name, try to find static web assets manifest by search in the directory.
162
+
163
+ var staticWebAssetsPath = FindFirstFileWithExtension ( appPath , staticWebAssetsV2Extension )
164
+ ?? FindFirstFileWithExtension ( appPath , staticWebAssetsV1Extension ) ;
165
+
166
+ if ( staticWebAssetsPath != null )
167
+ devServerOptions = CreateDevServerOptions ( urls , staticWebAssetsPath , onConsoleConnected ) ;
168
+
169
+ if ( devServerOptions == null )
170
+ throw new CommandLineException ( "Please, provide mainAssembly in hostProperties of runtimeconfig" ) ;
171
+ }
172
+
173
+ return devServerOptions ;
174
+ }
175
+
176
+ private static DevServerOptions CreateDevServerOptions ( string [ ] urls , string staticWebAssetsPath , Func < WebSocket , Task > ? onConsoleConnected ) => new
177
+ (
178
+ OnConsoleConnected : onConsoleConnected ,
179
+ StaticWebAssetsPath : staticWebAssetsPath ,
180
+ WebServerUseCors : true ,
181
+ WebServerUseCrossOriginPolicy : true ,
182
+ Urls : urls
183
+ ) ;
184
+
185
+ private static string ? FindFirstFileWithExtension ( string directory , string extension )
186
+ => Directory . EnumerateFiles ( directory , "*" + extension ) . First ( ) ;
187
+
114
188
private async Task RunConsoleMessagesPump ( WebSocket socket , WasmTestMessagesProcessor messagesProcessor , CancellationToken token )
115
189
{
116
190
byte [ ] buff = new byte [ 4000 ] ;
@@ -169,7 +243,7 @@ private string[] BuildUrls(ServerURLs serverURLs, IEnumerable<string> passThroug
169
243
}
170
244
171
245
string query = sb . ToString ( ) ;
172
- string filename = Path . GetFileName ( _args . HTMLPath ! ) ;
246
+ string ? filename = _args . HTMLPath != null ? Path . GetFileName ( _args . HTMLPath ) : null ;
173
247
string httpUrl = BuildUrl ( serverURLs . Http , filename , query ) ;
174
248
175
249
return string . IsNullOrEmpty ( serverURLs . Https )
@@ -179,12 +253,18 @@ private string[] BuildUrls(ServerURLs serverURLs, IEnumerable<string> passThroug
179
253
httpUrl ,
180
254
BuildUrl ( serverURLs . Https ! , filename , query )
181
255
} ) ;
256
+ }
182
257
183
- static string BuildUrl ( string baseUrl , string htmlFileName , string query )
184
- => new UriBuilder ( baseUrl )
185
- {
186
- Query = query ,
187
- Path = htmlFileName
188
- } . ToString ( ) ;
258
+ private static string BuildUrl ( string baseUrl , string ? htmlFileName , string query )
259
+ {
260
+ var uriBuilder = new UriBuilder ( baseUrl )
261
+ {
262
+ Query = query
263
+ } ;
264
+
265
+ if ( htmlFileName != null )
266
+ uriBuilder . Path = htmlFileName ;
267
+
268
+ return uriBuilder . ToString ( ) ;
189
269
}
190
270
}
0 commit comments