waitUntilReady method
Polls the HTTP endpoint until an acceptable response is received.
The URL is {http|https}://{host}:{mappedPort}{path}. Throws
TimeoutException when startupTimeout elapses without success.
Implementation
@override
Future<void> waitUntilReady(WaitStrategyTarget target) async {
final host = await target.containerHostIp();
final mappedPort = await target.exposedPort(port);
final scheme = _tls ? 'https' : 'http';
final uri = Uri.parse('$scheme://$host:$mappedPort$path');
// Created once and reused across all poll attempts. Must be closed
// after polling regardless of outcome to avoid a connection leak.
HttpClient? insecureClient;
if (_insecureTls) {
insecureClient = HttpClient()
..badCertificateCallback = (_, __, ___) => true;
}
final bool ready;
try {
ready = await poll(
() async {
try {
http.Response response;
if (insecureClient != null) {
final req = await insecureClient.openUrl(_method, uri);
for (final entry in _headers.entries) {
req.headers.set(entry.key, entry.value);
}
if (_body != null) {
req.write(_body);
}
final ioResp = await req.close().timeout(
const Duration(seconds: 1),
);
final bodyBytes = await ioResp.fold<List<int>>(
[],
(prev, elem) => prev..addAll(elem),
);
response = http.Response.bytes(
Uint8List.fromList(bodyBytes),
ioResp.statusCode,
);
} else {
final client = http.Client();
try {
final request = http.Request(_method, uri);
request.headers.addAll(_headers);
final body = _body;
if (body != null) {
request.body = body;
}
final streamed = await client
.send(request)
.timeout(const Duration(seconds: 1));
response = await http.Response.fromStream(streamed);
} finally {
client.close();
}
}
final statusOk = _statusCodeMatcher != null
? _statusCodeMatcher!(response.statusCode)
: _statusCodes.contains(response.statusCode);
if (!statusOk) {
return false;
}
if (_responsePredicate != null) {
return _responsePredicate!(response.body);
}
return true;
} on TimeoutException {
return false;
} on SocketException {
return false;
} on http.ClientException {
return false;
}
},
transientExceptions: [SocketException, TimeoutException],
);
} finally {
// Release the insecure HttpClient regardless of poll outcome or any
// unexpected exception thrown by a non-transient error in the loop.
insecureClient?.close(force: true);
}
if (!ready) {
throw TimeoutException(
'HTTP endpoint not ready within $startupTimeout',
);
}
}