Skip to content

Commit 56d402a

Browse files
Merge pull request #14 from Workiva/fix_hostname_bug
CPLAT-15165 Fix bug when using `--hostname` option
2 parents e7e5d77 + 0bb7bb4 commit 56d402a

19 files changed

+225
-111
lines changed

.github/workflows/dart_ci.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Dart CI
2+
3+
on:
4+
push:
5+
branches:
6+
- 'master'
7+
- 'test_consume_*'
8+
pull_request:
9+
branches:
10+
- '*'
11+
12+
jobs:
13+
build:
14+
runs-on: ubuntu-latest
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
sdk: [ stable, dev ]
19+
steps:
20+
- uses: actions/checkout@v2
21+
- uses: dart-lang/[email protected]
22+
with:
23+
sdk: ${{ matrix.sdk }}
24+
25+
- name: Install dependencies
26+
run: dart pub get
27+
28+
- name: Formatting
29+
run: dart format --output=none --set-exit-if-changed .
30+
if: always() && ${{ matrix.sdk }} == 'stable'
31+
32+
- name: Analysis
33+
run: dart analyze
34+
35+
- name: Tests
36+
run: dart test

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
## 0.1.1
2+
3+
- Fix bug when using `--hostname` that would cause the build daemon to fail to
4+
start.
5+
16
## 0.1.0
27

38
- Initial release!
4-

Dockerfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
FROM google/dart:2.3
2-
RUN apt-get update -qq && rm -rf /var/lib/apt/lists/*
1+
FROM google/dart:2.13
32
WORKDIR /build/
43
ADD pubspec.yaml .
54
RUN pub get
6-
ARG BUILD_ARTIFACTS_BUILD=/build/pubspec.lock
75
FROM scratch

dart_test.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
concurrency: 1
22
reporter: expanded
3-
retry: 2
3+
retry: 2
4+
timeout: 60s

lib/src/command_runner.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class WebdevProxy extends CommandRunner<int> {
2626
WebdevProxy()
2727
: super('webdev_proxy',
2828
'A simple dart proxy for `webdev serve` (uses the `shelf_proxy` package).') {
29-
addCommand(new ServeCommand());
29+
addCommand(ServeCommand());
3030
argParser.addFlag(verboseFlag, abbr: 'v', help: 'Enable verbose output.');
3131
}
3232

lib/src/command_utils.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import 'package:args/args.dart';
1919
void assertNoPositionalArgsBeforeSeparator(
2020
String command,
2121
ArgResults argResults,
22-
void usageException(String msg),
22+
void Function(String msg) usageException,
2323
) {
2424
if (argResults.rest.isEmpty) {
2525
return;

lib/src/logging.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ StringBuffer colorLog(LogRecord record, {bool verbose}) {
5050
}
5151

5252
if (record.stackTrace != null && verbose) {
53-
final trace = new Trace.from(record.stackTrace).terse;
53+
final trace = Trace.from(record.stackTrace).terse;
5454
lines.add(trace);
5555
}
5656

@@ -100,7 +100,7 @@ String humanReadable(Duration duration) {
100100
Future<T> logTimedAsync<T>(
101101
Logger logger,
102102
String description,
103-
Future<T> action(), {
103+
Future<T> Function() action, {
104104
Level level = Level.INFO,
105105
}) async {
106106
final watch = Stopwatch()..start();
@@ -118,7 +118,7 @@ Future<T> logTimedAsync<T>(
118118
T logTimedSync<T>(
119119
Logger logger,
120120
String description,
121-
T action(), {
121+
T Function() action, {
122122
Level level = Level.INFO,
123123
}) {
124124
final watch = Stopwatch()..start();

lib/src/port_utils.dart

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,20 @@
1414

1515
import 'dart:io';
1616

17-
/// Returns a Future that completes with an open port that should be available
18-
/// for binding.
19-
Future<int> findAndReleaseOpenPort() async {
20-
final socket = await ServerSocket.bind('localhost', 0);
21-
final port = socket.port;
17+
/// Returns a port that is probably, but not definitely, not in use.
18+
///
19+
/// This has a built-in race condition: another process may bind this port at
20+
/// any time after this call has returned.
21+
Future<int> findUnusedPort() async {
22+
int port;
23+
ServerSocket socket;
24+
try {
25+
socket =
26+
await ServerSocket.bind(InternetAddress.loopbackIPv6, 0, v6Only: true);
27+
} on SocketException {
28+
socket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
29+
}
30+
port = socket.port;
2231
await socket.close();
2332
return port;
2433
}

lib/src/serve_command.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,22 +137,23 @@ class ServeCommand extends Command<int> {
137137
});
138138

139139
// Parse the hostname to serve each dir on (defaults to 0.0.0.0)
140-
final hostname = parseHostname(argResults.rest);
140+
final hostnameResults = parseHostname(argResults.rest);
141+
final hostname = hostnameResults.hostname;
142+
final remainingArgs = hostnameResults.remainingArgs;
141143

142144
// Parse the directory:port mappings that will be used by the proxy servers.
143145
// Each proxy will be mapped to a `webdev serve` instance on another port.
144146
final portsToServeByDir = parseDirectoryArgs(argResults.rest);
145147

146148
// Find open ports for each of the directories to be served by webdev.
147149
final portsToProxyByDir = {
148-
for (final dir in portsToServeByDir.keys)
149-
dir: await findAndReleaseOpenPort()
150+
for (final dir in portsToServeByDir.keys) dir: await findUnusedPort()
150151
};
151152

152153
// Start the underlying `webdev serve` process.
153154
webdevServer = await WebdevServer.start([
154-
...argResults.rest,
155155
if (hostname != 'localhost') '--hostname=$hostname',
156+
...remainingArgs,
156157
for (final dir in portsToServeByDir.keys)
157158
'$dir:${portsToProxyByDir[dir]}',
158159
]);

lib/src/webdev_arg_utils.dart

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,34 @@ Map<String, int> parseDirectoryArgs(List<String> args) {
5353
/// [args] only if it is specified.
5454
///
5555
/// Otherwise, returns a default of `'localhost'`.
56-
String parseHostname(List<String> args) {
56+
ParseHostnameResults parseHostname(List<String> args) {
57+
var hostname = 'localhost';
58+
final remainingArgs = <String>[];
59+
var skipNext = false;
5760
for (var i = 0; i < args.length; i++) {
58-
if (!args[i].startsWith('--hostname')) {
61+
if (skipNext) {
62+
skipNext = false;
5963
continue;
60-
}
61-
if (args[i].contains('=')) {
64+
} else if (!args[i].startsWith('--hostname')) {
65+
remainingArgs.add(args[i]);
66+
} else if (args[i].contains('=')) {
6267
// --hostname=<value>
63-
return args[i].split('=')[1];
64-
}
65-
if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
68+
hostname = args[i].split('=')[1];
69+
} else if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
6670
// --hostname <value>
67-
return args[i + 1];
71+
hostname = args[i + 1];
72+
skipNext = true;
6873
}
6974
}
70-
return 'localhost';
75+
return ParseHostnameResults(hostname, remainingArgs);
7176

7277
// TODO: Use when webdev `--hostname=any` support is released
7378
// HttpMultiServer supports `any` as a more flexible localhost.
7479
// return 'any';
7580
}
81+
82+
class ParseHostnameResults {
83+
final String hostname;
84+
final List<String> remainingArgs;
85+
ParseHostnameResults(this.hostname, this.remainingArgs);
86+
}

0 commit comments

Comments
 (0)