mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[flutter_tools] retry sever socket setup (and port selection if port is unspecified) (#69351)
Fixes #69348 If the web development server fails to bind, then retry up to 5 times. If a port was not provided, select a new free port each time.
This commit is contained in:
parent
44d0e52d20
commit
a0860f6e87
@ -136,6 +136,8 @@ class WebAssetServer implements AssetReader {
|
||||
final Map<String, String> _modules;
|
||||
final Map<String, String> _digests;
|
||||
|
||||
int get selectedPort => _httpServer.port;
|
||||
|
||||
void performRestart(List<String> modules) {
|
||||
for (final String module in modules) {
|
||||
// We skip computing the digest by using the hashCode of the underlying buffer.
|
||||
@ -171,14 +173,27 @@ class WebAssetServer implements AssetReader {
|
||||
bool testMode = false,
|
||||
DwdsLauncher dwdsLauncher = Dwds.start,
|
||||
}) async {
|
||||
try {
|
||||
InternetAddress address;
|
||||
if (hostname == 'any') {
|
||||
address = InternetAddress.anyIPv4;
|
||||
} else {
|
||||
address = (await InternetAddress.lookup(hostname)).first;
|
||||
}
|
||||
final HttpServer httpServer = await HttpServer.bind(address, port);
|
||||
HttpServer httpServer;
|
||||
dynamic lastError;
|
||||
for (int i = 0; i < 5; i += 1) {
|
||||
try {
|
||||
httpServer = await HttpServer.bind(address, port ?? await globals.os.findFreePort());
|
||||
break;
|
||||
} on SocketException catch (error) {
|
||||
lastError = error;
|
||||
await Future<void>.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
}
|
||||
if (httpServer == null) {
|
||||
throwToolExit('Failed to bind web development server:\n$lastError');
|
||||
}
|
||||
|
||||
// Allow rendering in a iframe.
|
||||
httpServer.defaultResponseHeaders.remove('x-frame-options', 'SAMEORIGIN');
|
||||
|
||||
@ -257,10 +272,13 @@ class WebAssetServer implements AssetReader {
|
||||
useSseForDebugBackend: useSseForDebugBackend,
|
||||
serveDevTools: false,
|
||||
loadStrategy: FrontendServerRequireStrategyProvider(
|
||||
ReloadConfiguration.none, server, _digestProvider)
|
||||
.strategy,
|
||||
ReloadConfiguration.none,
|
||||
server,
|
||||
_digestProvider,
|
||||
).strategy,
|
||||
expressionCompiler: expressionCompiler,
|
||||
spawnDds: true);
|
||||
spawnDds: true,
|
||||
);
|
||||
shelf.Pipeline pipeline = const shelf.Pipeline();
|
||||
if (enableDwds) {
|
||||
pipeline = pipeline.addMiddleware(middleware);
|
||||
@ -273,11 +291,6 @@ class WebAssetServer implements AssetReader {
|
||||
shelf.serveRequests(httpServer, cascade.handler);
|
||||
server.dwds = dwds;
|
||||
return server;
|
||||
} on SocketException catch (err) {
|
||||
throwToolExit('Failed to bind web development server:\n$err');
|
||||
}
|
||||
assert(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
final BuildInfo _buildInfo;
|
||||
@ -709,7 +722,7 @@ class WebDevFS implements DevFS {
|
||||
/// server.
|
||||
WebDevFS({
|
||||
@required this.hostname,
|
||||
@required this.port,
|
||||
@required int port,
|
||||
@required this.packagesFilePath,
|
||||
@required this.urlTunneller,
|
||||
@required this.useSseForDebugProxy,
|
||||
@ -721,11 +734,10 @@ class WebDevFS implements DevFS {
|
||||
@required this.chromiumLauncher,
|
||||
@required this.nullAssertions,
|
||||
this.testMode = false,
|
||||
});
|
||||
}) : _port = port;
|
||||
|
||||
final Uri entrypoint;
|
||||
final String hostname;
|
||||
final int port;
|
||||
final String packagesFilePath;
|
||||
final UrlTunneller urlTunneller;
|
||||
final bool useSseForDebugProxy;
|
||||
@ -736,6 +748,7 @@ class WebDevFS implements DevFS {
|
||||
final ExpressionCompiler expressionCompiler;
|
||||
final ChromiumLauncher chromiumLauncher;
|
||||
final bool nullAssertions;
|
||||
final int _port;
|
||||
|
||||
WebAssetServer webAssetServer;
|
||||
|
||||
@ -800,7 +813,7 @@ class WebDevFS implements DevFS {
|
||||
webAssetServer = await WebAssetServer.start(
|
||||
chromiumLauncher,
|
||||
hostname,
|
||||
port,
|
||||
_port,
|
||||
urlTunneller,
|
||||
useSseForDebugProxy,
|
||||
useSseForDebugBackend,
|
||||
@ -810,15 +823,16 @@ class WebDevFS implements DevFS {
|
||||
expressionCompiler,
|
||||
testMode: testMode,
|
||||
);
|
||||
final int selectedPort = webAssetServer.selectedPort;
|
||||
if (buildInfo.dartDefines.contains('FLUTTER_WEB_AUTO_DETECT=true')) {
|
||||
webAssetServer.webRenderer = WebRendererMode.autoDetect;
|
||||
} else if (buildInfo.dartDefines.contains('FLUTTER_WEB_USE_SKIA=true')) {
|
||||
webAssetServer.webRenderer = WebRendererMode.canvaskit;
|
||||
}
|
||||
if (hostname == 'any') {
|
||||
_baseUri = Uri.http('localhost:$port', '');
|
||||
_baseUri = Uri.http('localhost:$selectedPort', '');
|
||||
} else {
|
||||
_baseUri = Uri.http('$hostname:$port', '');
|
||||
_baseUri = Uri.http('$hostname:$selectedPort', '');
|
||||
}
|
||||
return _baseUri;
|
||||
}
|
||||
|
@ -483,11 +483,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
'Launching ${globals.fsUtils.getDisplayPath(target)} '
|
||||
'on ${device.device.name} in $modeName mode...',
|
||||
);
|
||||
final String effectiveHostname = debuggingOptions.hostname ?? 'localhost';
|
||||
final int hostPort = debuggingOptions.port == null
|
||||
? await globals.os.findFreePort()
|
||||
: int.tryParse(debuggingOptions.port);
|
||||
|
||||
if (device.device is ChromiumDevice) {
|
||||
_chromiumLauncher = (device.device as ChromiumDevice).chromeLauncher;
|
||||
}
|
||||
@ -498,10 +493,11 @@ class _ResidentWebRunner extends ResidentWebRunner {
|
||||
debuggingOptions.webEnableExpressionEvaluation
|
||||
? WebExpressionCompiler(device.generator)
|
||||
: null;
|
||||
|
||||
device.devFS = WebDevFS(
|
||||
hostname: effectiveHostname,
|
||||
port: hostPort,
|
||||
hostname: debuggingOptions.hostname ?? 'localhost',
|
||||
port: debuggingOptions.port != null
|
||||
? int.tryParse(debuggingOptions.port)
|
||||
: null,
|
||||
packagesFilePath: packagesFilePath,
|
||||
urlTunneller: urlTunneller,
|
||||
useSseForDebugProxy: debuggingOptions.webUseSseForDebugProxy,
|
||||
|
@ -699,7 +699,7 @@ void main() {
|
||||
contains('GENERATED'));
|
||||
|
||||
// served on localhost
|
||||
expect(uri, Uri.http('localhost:0', ''));
|
||||
expect(uri.host, 'localhost');
|
||||
|
||||
await webDevFS.destroy();
|
||||
}, overrides: <Type, Generator>{
|
||||
@ -813,7 +813,7 @@ void main() {
|
||||
contains('GENERATED'));
|
||||
|
||||
// served on localhost
|
||||
expect(uri, Uri.http('localhost:0', ''));
|
||||
expect(uri.host, 'localhost');
|
||||
|
||||
await webDevFS.destroy();
|
||||
}, overrides: <Type, Generator>{
|
||||
@ -859,7 +859,7 @@ void main() {
|
||||
|
||||
final Uri uri = await webDevFS.create();
|
||||
|
||||
expect(uri, Uri.http('localhost:0', ''));
|
||||
expect(uri.host, 'localhost');
|
||||
await webDevFS.destroy();
|
||||
}));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user