isReachable method
Checks if a URL is reachable.
First attempts a HEAD request, but if it fails with 403/405/501 (common for servers that block HEAD), falls back to a GET request.
A URL is considered reachable if we get ANY response from the server, even error responses like 404 or 500 - because that means the server is online and responding. Only connection failures return false.
Implementation
Future<bool> isReachable(String url,
{Duration? timeout, ClientType? clientType}) async {
final effectiveTimeout = timeout ?? const Duration(seconds: 10);
// First try HEAD request (lighter weight)
final (headResponse, headError) = await head(
url: url,
timeout: effectiveTimeout,
clientType: clientType,
);
// If HEAD succeeded with any response, the server is reachable
if (headError == null && headResponse != null) {
return true;
}
// If HEAD returned 403, 405, or 501, the server blocked HEAD but is reachable
// Try a GET request to confirm
if (headResponse != null &&
(headResponse.statusCode == 403 ||
headResponse.statusCode == 405 ||
headResponse.statusCode == 501)) {
final (getResponse, getError) = await get(
url: url,
timeout: effectiveTimeout,
clientType: clientType,
);
// Any response (even 404, 500) means the server is reachable
return getError == null || getResponse != null;
}
// If HEAD had a connection error, try GET as fallback
// Some servers don't handle HEAD properly
if (headError != null &&
(headError.type == ClientErrorType.unknown ||
headError.type == ClientErrorType.badResponse)) {
final (getResponse, getError) = await get(
url: url,
timeout: effectiveTimeout,
clientType: clientType,
);
// Any response means server is reachable
return getError == null || getResponse != null;
}
// Check if the error indicates a network/connection issue vs server response
if (headError != null) {
// These errors mean we couldn't connect at all
if (headError.type == ClientErrorType.connectionError ||
headError.type == ClientErrorType.connectionTimeout ||
headError.type == ClientErrorType.sendTimeout) {
return false;
}
// Other errors might mean the server responded but with an error
// If we have a response object, the server IS reachable
if (headResponse != null) {
return true;
}
}
return false;
}