send method
Implementation
@override
Future<HttpResponse> send(
HttpRequest request, CancellationToken cancellationToken) async {
var current = request;
for (var redirect = 0;; redirect++) {
final response = await _sendOnce(current, cancellationToken);
if (!_options.followRedirects ||
!{301, 302, 303, 307, 308}.contains(response.statusCode)) {
return response;
}
final locations = response.headers['location'];
if (locations.isEmpty) return response;
if (redirect >= _options.maxRedirects) {
await response.dispose();
throw StateError('Maximum redirects exceeded.');
}
final toGet =
response.statusCode == 303 && current.method != HttpMethod.head;
if (!toGet && current.body?.isReplayable == false) return response;
if ({301, 302}.contains(response.statusCode) &&
!{HttpMethod.get, HttpMethod.head}.contains(current.method)) {
return response;
}
Uri target;
try {
target = current.uri.resolve(locations.first);
} catch (_) {
await response.dispose();
rethrow;
}
if (!{'http', 'https'}.contains(target.scheme) ||
target.host.isEmpty ||
target.userInfo.isNotEmpty ||
(current.uri.scheme == 'https' && target.scheme == 'http')) {
await response.dispose();
throw StateError('Unsafe redirect destination.');
}
var headers = current.headers;
if (target.origin != current.uri.origin) {
headers =
headers.without(['authorization', 'proxy-authorization', 'cookie']);
}
if (toGet) {
headers = headers
.without(['content-type', 'content-length', 'transfer-encoding']);
}
current = current.copyWith(
uri: target,
headers: headers,
method: toGet ? HttpMethod.get : current.method,
removeBody: toGet);
await response.dispose();
}
}