import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:charcode/ascii.dart'; import 'connection_info.dart'; import 'lockable_headers.dart'; import 'response.dart'; import 'session.dart'; class MockHttpRequest implements HttpRequest, StreamSink>, StringSink { int _contentLength = 0; late BytesBuilder _buf; final Completer _done = Completer(); final LockableMockHttpHeaders _headers = LockableMockHttpHeaders(); Uri? _requestedUri; late MockHttpSession _session; final StreamController _stream = StreamController(); @override final List cookies = []; @override HttpConnectionInfo connectionInfo = MockHttpConnectionInfo(remoteAddress: InternetAddress.loopbackIPv4); @override MockHttpResponse response = MockHttpResponse( contentLength: 0, encoding: utf8, persistentConnection: false, reasonPhrase: '', statusCode: 200); @override HttpSession get session => _session; @override final String method; @override final Uri uri; @override bool persistentConnection = true; /// [copyBuffer] corresponds to `copy` on the [BytesBuilder] constructor. MockHttpRequest(this.method, this.uri, {bool copyBuffer = true, String? protocolVersion, String? sessionId, this.certificate, this.persistentConnection = true}) { _buf = BytesBuilder(copy: copyBuffer != false); _session = MockHttpSession(id: sessionId ?? 'mock-http-session'); this.protocolVersion = protocolVersion ?? '1.1'; } @override int get contentLength => _contentLength; @override HttpHeaders get headers => _headers; @override Uri get requestedUri { if (_requestedUri != null) { return _requestedUri!; } else { return _requestedUri = Uri( scheme: 'http', host: 'example.com', path: uri.path, query: uri.query, ); } } set requestedUri(Uri value) { _requestedUri = value; } @override late String protocolVersion; @override X509Certificate? certificate; @override void add(List data) { if (_done.isCompleted) { throw StateError('Cannot add to closed MockHttpRequest.'); } else { _headers.lock(); _contentLength += data.length; _buf.add(data); } } @override void addError(error, [StackTrace? stackTrace]) { if (_done.isCompleted) { throw StateError('Cannot add to closed MockHttpRequest.'); } else { _stream.addError(error, stackTrace); } } @override Future addStream(Stream> stream) { var c = Completer(); stream.listen(add, onError: addError, onDone: c.complete); return c.future; } @override Future close() async { await flush(); _headers.lock(); scheduleMicrotask(_stream.close); _done.complete(); return await _done.future; } @override Future get done => _done.future; // @override Future flush() async { _contentLength += _buf.length; _stream.add(_buf.takeBytes()); } @override void write(Object? obj) { obj?.toString().codeUnits.forEach(writeCharCode); } @override void writeAll(Iterable objects, [String separator = '']) { write(objects.join(separator)); } @override void writeCharCode(int charCode) { add([charCode]); } @override void writeln([Object? obj = '']) { write(obj ?? ''); add([$cr, $lf]); } @override Future any(bool Function(Uint8List element) test) { return _stream.stream.any((List e) { return test(Uint8List.fromList(e)); }); } @override Stream asBroadcastStream({ void Function(StreamSubscription subscription)? onListen, void Function(StreamSubscription subscription)? onCancel, }) { return _stream.stream .asBroadcastStream(onListen: onListen, onCancel: onCancel); } @override Stream asyncExpand(Stream? Function(Uint8List event) convert) => _stream.stream.asyncExpand(convert); @override Stream asyncMap(FutureOr Function(Uint8List event) convert) => _stream.stream.asyncMap(convert); @override Future contains(Object? needle) => _stream.stream.contains(needle); @override Stream distinct( [bool Function(Uint8List previous, Uint8List next)? equals]) => _stream.stream.distinct(equals); @override Future drain([E? futureValue]) => _stream.stream.drain(futureValue); @override Future elementAt(int index) => _stream.stream.elementAt(index); @override Future every(bool Function(Uint8List element) test) => _stream.stream.every(test); @override Stream expand(Iterable Function(Uint8List value) convert) => _stream.stream.expand(convert); @override Future get first => _stream.stream.first; @override Future firstWhere(bool Function(Uint8List element) test, {List Function()? orElse}) => _stream.stream .firstWhere(test, orElse: () => Uint8List.fromList(orElse!())); @override Future fold( S initialValue, S Function(S previous, Uint8List element) combine) => _stream.stream.fold(initialValue, combine); @override Future forEach(void Function(Uint8List element) action) => _stream.stream.forEach(action); @override Stream handleError(Function onError, {bool Function(Object?)? test}) => _stream.stream.handleError(onError, test: test); @override bool get isBroadcast => _stream.stream.isBroadcast; @override Future get isEmpty => _stream.stream.isEmpty; @override Future join([String separator = '']) => _stream.stream.join(separator); @override Future get last => _stream.stream.last; @override Future lastWhere(bool Function(Uint8List element) test, {List Function()? orElse}) => _stream.stream .lastWhere(test, orElse: () => Uint8List.fromList(orElse!())); @override Future get length => _stream.stream.length; @override StreamSubscription listen( void Function(Uint8List event)? onData, { Function? onError, void Function()? onDone, bool? cancelOnError, }) { return _stream.stream.listen( onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError == true, ); } @override Stream map(S Function(Uint8List event) convert) => _stream.stream.map(convert); @override Future pipe(StreamConsumer> streamConsumer) => _stream.stream.cast>().pipe(streamConsumer); @override Future reduce( List Function(Uint8List previous, Uint8List element) combine) { return _stream.stream.reduce((Uint8List previous, Uint8List element) { return Uint8List.fromList(combine(previous, element)); }); } @override Future get single => _stream.stream.single; @override Future singleWhere(bool Function(Uint8List element) test, {List Function()? orElse}) => _stream.stream .singleWhere(test, orElse: () => Uint8List.fromList(orElse!())); @override Stream skip(int count) => _stream.stream.skip(count); @override Stream skipWhile(bool Function(Uint8List element) test) => _stream.stream.skipWhile(test); @override Stream take(int count) => _stream.stream.take(count); @override Stream takeWhile(bool Function(Uint8List element) test) => _stream.stream.takeWhile(test); @override Stream timeout(Duration timeLimit, {void Function(EventSink sink)? onTimeout}) => _stream.stream.timeout(timeLimit, onTimeout: onTimeout); @override Future> toList() => _stream.stream.toList(); @override Future> toSet() => _stream.stream.toSet(); @override Stream transform(StreamTransformer, S> streamTransformer) => _stream.stream.cast>().transform(streamTransformer); @override Stream where(bool Function(Uint8List event) test) => _stream.stream.where(test); @override Stream cast() => Stream.castFrom, R>(this); }