import 'dart:async'; import 'dart:collection'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; class FakeHttpHeaders implements HttpHeaders { final Map> _headers = HashMap>(); @override List? operator [](key) => _headers[key]; @override int get contentLength => int.parse(_headers[HttpHeaders.contentLengthHeader]![0]); @override DateTime? get ifModifiedSince { var values = _headers[HttpHeaders.ifModifiedSinceHeader]; if (values != null) { try { return HttpDate.parse(values[0]); } on Exception { return null; } } return null; } @override set ifModifiedSince(DateTime? ifModifiedSince) { ArgumentError.checkNotNull(ifModifiedSince); // Format "ifModifiedSince" header with date in Greenwich Mean Time (GMT). var formatted = HttpDate.format(ifModifiedSince!.toUtc()); _set(HttpHeaders.ifModifiedSinceHeader, formatted); } @override ContentType? contentType; @override void set(String name, Object value, {bool preserveHeaderCase = false}) { if (preserveHeaderCase) { throw ArgumentError('preserveHeaderCase not supported'); } name = name.toLowerCase(); _headers.remove(name); _addAll(name, value); } @override String? value(String name) { name = name.toLowerCase(); var values = _headers[name]; if (values == null) return null; if (values.length > 1) { throw HttpException('More than one value for header $name'); } return values[0]; } @override String toString() => '$runtimeType : $_headers'; // [name] must be a lower-case version of the name. void _add(String name, Object value) { if (name == HttpHeaders.ifModifiedSinceHeader) { if (value is DateTime) { ifModifiedSince = value; } else if (value is String) { _set(HttpHeaders.ifModifiedSinceHeader, value); } else { throw HttpException('Unexpected type for header named $name'); } } else { _addValue(name, value); } } void _addAll(String name, Object value) { if (value is List) { for (var i = 0; i < value.length; i++) { _add(name, value[i] as Object); } } else { _add(name, value); } } void _addValue(String name, Object value) { var values = _headers[name]; if (values == null) { values = []; _headers[name] = values; } if (value is DateTime) { values.add(HttpDate.format(value)); } else { values.add(value.toString()); } } void _set(String name, String value) { assert(name == name.toLowerCase()); var values = []; _headers[name] = values; values.add(value); } /* * Implemented to remove editor warnings */ @override dynamic noSuchMethod(Invocation invocation) { print([ invocation.memberName, invocation.isGetter, invocation.isSetter, invocation.isMethod, invocation.isAccessor ]); return super.noSuchMethod(invocation); } } class FakeHttpRequest extends StreamView implements HttpRequest { @override final Uri uri; @override final FakeHttpResponse response = FakeHttpResponse(); @override final HttpHeaders headers = FakeHttpHeaders(); @override final String method = 'GET'; final bool followRedirects; FakeHttpRequest(this.uri, {this.followRedirects = true, DateTime? ifModifiedSince, required Stream data}) : super(data) { if (ifModifiedSince != null) { headers.ifModifiedSince = ifModifiedSince; } } /* * Implemented to remove editor warnings */ @override dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); } class FakeHttpResponse implements HttpResponse { @override final HttpHeaders headers = FakeHttpHeaders(); final Completer _completer = Completer(); final List _buffer = []; String? _reasonPhrase; late final Future _doneFuture; FakeHttpResponse() { _doneFuture = _completer.future.whenComplete(() { assert(!_isDone); _isDone = true; }); } bool _isDone = false; @override int statusCode = HttpStatus.ok; @override String get reasonPhrase => _findReasonPhrase(statusCode)!; @override set reasonPhrase(String value) { _reasonPhrase = value; } @override Future get done => _doneFuture; @override Future close() { _completer.complete(); return _doneFuture; } @override void add(List data) { _buffer.addAll(data); } @override void addError(error, [StackTrace? stackTrace]) { // doesn't seem to be hit...hmm... } @override Future redirect(Uri location, {int status = HttpStatus.movedTemporarily}) { statusCode = status; headers.set(HttpHeaders.locationHeader, location.toString()); return close(); } @override void write(Object? obj) { var str = obj.toString(); add(utf8.encode(str)); } /* * Implemented to remove editor warnings */ @override dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); String get fakeContent => utf8.decode(_buffer); List get fakeContentBinary => _buffer; bool get fakeDone => _isDone; // Copied from SDK http_impl.dart @ 845 on 2014-01-05 // TODO: file an SDK bug to expose this on HttpStatus in some way String? _findReasonPhrase(int statusCode) { if (_reasonPhrase != null) { return _reasonPhrase; } switch (statusCode) { case HttpStatus.notFound: return 'Not Found'; default: return 'Status $statusCode'; } } }