File tree Expand file tree Collapse file tree 2 files changed +60
-4
lines changed
Expand file tree Collapse file tree 2 files changed +60
-4
lines changed Original file line number Diff line number Diff line change @@ -213,4 +213,42 @@ describe('port detection', () => {
213213 `Port ${ BASE_PORT } is already in use` ,
214214 )
215215 } )
216+
217+ test ( 'allows binding to specific host with strictPort when wildcard port is in use' , async ( ) => {
218+ await using _wildcardServer = await createSimpleServer ( BASE_PORT , '0.0.0.0' )
219+
220+ const warnMessages : string [ ] = [ ]
221+ viteServer = await createServer ( {
222+ root : import . meta. dirname ,
223+ customLogger : {
224+ info : ( ) => { } ,
225+ warn : ( msg ) => warnMessages . push ( msg ) ,
226+ warnOnce : ( ) => { } ,
227+ error : ( ) => { } ,
228+ clearScreen : ( ) => { } ,
229+ hasErrorLogged : ( ) => false ,
230+ hasWarned : false ,
231+ } ,
232+ server : {
233+ port : BASE_PORT ,
234+ host : '127.0.0.1' ,
235+ strictPort : true ,
236+ ws : false ,
237+ } ,
238+ } )
239+
240+ try {
241+ await viteServer . listen ( )
242+ } catch ( e ) {
243+ // it may not be allowed to bind to specific host when wildcard port is in use
244+ expect ( ( ) => {
245+ throw e
246+ } ) . toThrow ( `Port ${ BASE_PORT } is already in use` )
247+ return
248+ }
249+
250+ const address = viteServer . httpServer ! . address ( )
251+ expect ( address ) . toStrictEqual ( expect . objectContaining ( { port : BASE_PORT } ) )
252+ expect ( warnMessages ) . toContainEqual ( expect . stringContaining ( 'wildcard' ) )
253+ } )
216254} )
Original file line number Diff line number Diff line change @@ -229,20 +229,38 @@ export async function httpServerStart(
229229 for ( let port = startPort ; port <= MAX_PORT ; port ++ ) {
230230 // Pre-check port availability on wildcard addresses (0.0.0.0, ::)
231231 // so that we avoid conflicts with other servers listening on all interfaces
232- if ( await isPortAvailable ( port ) ) {
232+ const portAvailableOnWildcard = await isPortAvailable ( port )
233+
234+ // If port is not available on a wildcard address but strictPort is set,
235+ // we still try binding directly before giving up.
236+ if ( strictPort ) {
233237 const result = await tryBindServer ( httpServer , port , host )
234238 if ( result . success ) {
239+ if ( ! portAvailableOnWildcard ) {
240+ logger . warn (
241+ colors . yellow (
242+ `Port ${ port } is in use on a wildcard address, but ${ host ?? 'localhost' } :${ port } is available. ` +
243+ `There may be another server running on a wildcard IP on port ${ port } .` ,
244+ ) ,
245+ )
246+ }
235247 return port
236248 }
237249 if ( result . error . code !== 'EADDRINUSE' ) {
238250 throw result . error
239251 }
240- }
241-
242- if ( strictPort ) {
243252 throw new Error ( `Port ${ port } is already in use` )
244253 }
245254
255+ if ( portAvailableOnWildcard ) {
256+ const result = await tryBindServer ( httpServer , port , host )
257+ if ( result . success ) {
258+ return port
259+ }
260+ if ( result . error . code !== 'EADDRINUSE' ) {
261+ throw result . error
262+ }
263+ }
246264 logger . info ( `Port ${ port } is in use, trying another one...` )
247265 }
248266 throw new Error (
You can’t perform that action at this time.
0 commit comments