send method
Sends to an absolute URL, as the declared host whose base URL it is under: that host's credential, timeout, retries, breaker and pool.
A URL no declared host covers is refused with DV-HTTP-001 and never
sent -- the same answer host gives a name nobody declared. Covered
means the same scheme, host and port, and a path at or below the base
URL's; where two declared hosts cover it, the longer base URL does.
allowUndeclaredHost is for a destination that is data rather than
configuration, such as a webhook subscriber's endpoint, which no pubspec
can list. It sends on the default policy -- a 30-second timeout,
idempotency-aware retries, no breaker, no pool -- and never as a declared
host, even one whose base URL covers it: a URL somebody else supplied
must not be able to borrow the application's credential for that host.
Whoever passes it owns checking where the URL leads.
Implementation
Future<Response> send(
String method,
Object url, {
Object? json,
Object? body,
Map<String, String> headers = const <String, String>{},
String? idempotencyKey,
int? attempts,
String? connectAddress,
bool allowUndeclaredHost = false,
}) {
final Uri uri = url is Uri ? url : Uri.parse('$url');
if (!uri.hasScheme || uri.host.isEmpty) {
throw ArgumentError('"$url" is not an absolute URL.');
}
String key;
DVHttpHostConfig config;
final (String, DVHttpHostConfig)? declared =
allowUndeclaredHost ? null : _covering(uri);
if (declared != null) {
(key, config) = declared;
} else if (allowUndeclaredHost) {
key = uri.authority;
config = DVHttpHostConfig(baseUrl: '${uri.scheme}://${uri.authority}');
} else {
DVObservability.log(
'Refused $method ${uri.scheme}://${uri.authority}${uri.path}: no '
'declared host covers it.',
level: DVLogLevel.error,
code: 'DV-HTTP-001',
context: <String, Object?>{'host': uri.authority},
);
return Future<Response>.error(
DVHttpUndeclaredHostException(uri.authority, url: uri));
}
return _execute(
key,
config,
method,
uri,
json: json,
body: body,
headers: headers,
idempotencyKey: idempotencyKey,
attempts: attempts,
connectAddress: connectAddress,
);
}