@@ -9,6 +9,8 @@ import serveStatic from "serve-static";
9
9
import { DEFAULT_CONFIG } from "../../config" ;
10
10
import { findSWAConfigFile , logger , logRequest } from "../../core" ;
11
11
import { AUTH_STATUS , CUSTOM_URL_SCHEME , IS_APP_DEV_SERVER , SWA_PUBLIC_DIR } from "../../core/constants" ;
12
+ import { parseUrl } from "../../core/utils/net" ;
13
+ import waitOn from "wait-on" ;
12
14
import { getAuthBlockResponse , handleAuthRequest , isAuthRequest , isLoginRequest , isLogoutRequest } from "../handlers/auth.handler" ;
13
15
import { isDataApiRequest } from "../handlers/dab.handler" ;
14
16
import { handleErrorPage } from "../handlers/error-page.handler" ;
@@ -67,7 +69,7 @@ export async function handleUserConfig(appLocation: string | undefined): Promise
67
69
* @param proxyApp An `http-proxy` instance.
68
70
* @param target The root folder of the static app (ie. `output_location`). Or, the HTTP host target, if connecting to a dev server, or
69
71
*/
70
- function serveStaticOrProxyResponse ( req : http . IncomingMessage , res : http . ServerResponse , proxyApp : httpProxy , target : string | undefined ) {
72
+ async function serveStaticOrProxyResponse ( req : http . IncomingMessage , res : http . ServerResponse , proxyApp : httpProxy , target : string | undefined ) {
71
73
if ( [ 301 , 302 ] . includes ( res . statusCode ) ) {
72
74
res . end ( ) ;
73
75
return ;
@@ -100,6 +102,42 @@ function serveStaticOrProxyResponse(req: http.IncomingMessage, res: http.ServerR
100
102
target = DEFAULT_CONFIG . outputLocation ;
101
103
logRequest ( req , target ) ;
102
104
105
+ let { protocol, hostname, port } = parseUrl ( target ) ;
106
+
107
+ if ( hostname === "localhost" ) {
108
+ let waitOnOneOfResources = [ `tcp:127.0.0.1:${ port } ` , `tcp:localhost:${ port } ` ] ;
109
+ let promises = waitOnOneOfResources . map ( ( resource ) => {
110
+ return waitOn ( {
111
+ resources : [ resource ] ,
112
+ delay : 1000 , // initial delay in ms, default 0
113
+ interval : 100 , // poll interval in ms, default 250ms
114
+ simultaneous : 1 , // limit to 1 connection per resource at a time
115
+ timeout : 60000 , // timeout in ms, default Infinity
116
+ tcpTimeout : 1000 , // tcp timeout in ms, default 300ms
117
+ window : 1000 , // stabilization time in ms, default 750ms
118
+ strictSSL : false ,
119
+ verbose : false , // force disable verbose logs even if SWA_CLI_DEBUG is enabled
120
+ } )
121
+ . then ( ( ) => {
122
+ logger . silly ( `Connected to ${ resource } successfully` ) ;
123
+ return resource ;
124
+ } )
125
+ . catch ( ( err ) => {
126
+ logger . silly ( `Could not connect to ${ resource } ` ) ;
127
+ logger . warn ( err . message ) ;
128
+ throw err ;
129
+ } ) ;
130
+ } ) ;
131
+
132
+ try {
133
+ const availableUrl = await Promise . any ( promises ) ;
134
+ logger . silly ( `${ target } validated successfully` ) ;
135
+ target = protocol + "//" + availableUrl . slice ( 4 ) ;
136
+ } catch {
137
+ logger . error ( `Could not connect to "${ target } ". Is the server up and running?` ) ;
138
+ }
139
+ }
140
+
103
141
proxyApp . web (
104
142
req ,
105
143
res ,
@@ -209,7 +247,7 @@ export async function requestMiddleware(
209
247
210
248
if ( isWebsocketRequest ( req ) ) {
211
249
logger . silly ( `websocket request detected` ) ;
212
- return serveStaticOrProxyResponse ( req , res , proxyApp , DEFAULT_CONFIG . outputLocation ) ;
250
+ return await serveStaticOrProxyResponse ( req , res , proxyApp , DEFAULT_CONFIG . outputLocation ) ;
213
251
}
214
252
215
253
let target = DEFAULT_CONFIG . outputLocation ;
@@ -224,7 +262,7 @@ export async function requestMiddleware(
224
262
logger . silly ( ` - ${ statusCodeToServe } code detected. Exit` ) ;
225
263
226
264
handleErrorPage ( req , res , statusCodeToServe , userConfig ?. responseOverrides ) ;
227
- return serveStaticOrProxyResponse ( req , res , proxyApp , target ) ;
265
+ return await serveStaticOrProxyResponse ( req , res , proxyApp , target ) ;
228
266
}
229
267
}
230
268
@@ -280,7 +318,7 @@ export async function requestMiddleware(
280
318
281
319
if ( ! isRouteRequiringUserRolesCheck ( req , matchingRouteRule , isFunctionReq , authStatus ) ) {
282
320
handleErrorPage ( req , res , 401 , userConfig ?. responseOverrides ) ;
283
- return serveStaticOrProxyResponse ( req , res , proxyApp , target ) ;
321
+ return await serveStaticOrProxyResponse ( req , res , proxyApp , target ) ;
284
322
}
285
323
286
324
if ( authStatus != AUTH_STATUS . NoAuth && ( authStatus != AUTH_STATUS . HostNameAuthLogin || ! urlPathnameWithQueryParams ) ) {
@@ -295,6 +333,6 @@ export async function requestMiddleware(
295
333
logger . silly ( ` - url: ${ chalk . yellow ( req . url ) } ` ) ;
296
334
logger . silly ( ` - target: ${ chalk . yellow ( target ) } ` ) ;
297
335
298
- serveStaticOrProxyResponse ( req , res , proxyApp , target ) ;
336
+ await serveStaticOrProxyResponse ( req , res , proxyApp , target ) ;
299
337
}
300
338
}
0 commit comments