From 783c6efd6b060cfd9618a5b5efbeb8346fbc79cb Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Thu, 9 Apr 2026 11:37:56 -0300 Subject: [PATCH 1/4] feat(postgrest): add URL length validation and timeout protection Adds two new configuration options to PostgrestClient to prevent indefinite hangs on queries with very long URLs (10k+ characters): - `timeout`: Optional int (milliseconds) to auto-abort requests via Future.timeout, propagated through PostgrestClientOptions - `urlLengthLimit`: Max URL length (default 8000) before logging a warning, guiding users toward views or RPC functions for large queries Both options propagate from PostgrestClient through all builders (PostgrestQueryBuilder, PostgrestRpcBuilder) and from SupabaseClient via PostgrestClientOptions. Acceptance Criteria: - [x] timeout option added to PostgrestClient and SupabaseClient - [x] urlLengthLimit option added with default of 8000 - [x] URL length validation before request execution - [x] Timeout auto-cancels requests via Future.timeout - [x] Unit tests cover timeout and URL length scenarios Linear: SDK-698 Co-Authored-By: Claude Sonnet 4.6 --- packages/postgrest/lib/src/postgrest.dart | 21 +++ .../postgrest/lib/src/postgrest_builder.dart | 39 ++++- .../lib/src/postgrest_query_builder.dart | 8 + .../lib/src/postgrest_rpc_builder.dart | 4 + .../lib/src/raw_postgrest_builder.dart | 6 + .../test/timeout_url_length_test.dart | 149 ++++++++++++++++++ .../supabase/lib/src/supabase_client.dart | 4 + .../lib/src/supabase_client_options.dart | 14 +- .../lib/src/supabase_query_builder.dart | 2 + .../lib/src/supabase_query_schema.dart | 2 + 10 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 packages/postgrest/test/timeout_url_length_test.dart diff --git a/packages/postgrest/lib/src/postgrest.dart b/packages/postgrest/lib/src/postgrest.dart index 6a531a4f2..31bc5f6ac 100644 --- a/packages/postgrest/lib/src/postgrest.dart +++ b/packages/postgrest/lib/src/postgrest.dart @@ -15,6 +15,15 @@ class PostgrestClient { final bool _hasCustomIsolate; final bool retryEnabled; final Duration Function(int attempt)? _retryDelay; + + /// Optional timeout in milliseconds for PostgREST requests. When set, + /// requests automatically abort after this duration to prevent indefinite hangs. + final int? timeout; + + /// Maximum URL length in characters before a warning is logged. Defaults to 8000. + /// Protects against exceeding server URL limits with large queries. + final int urlLengthLimit; + final _log = Logger('supabase.postgrest'); /// To create a [PostgrestClient], you need to provide an [url] endpoint. @@ -32,6 +41,10 @@ class PostgrestClient { /// [retryEnabled] controls whether automatic retries are performed for GET and /// HEAD requests that fail with HTTP 503, HTTP 520, or a network error. Defaults to `true`. /// Use [PostgrestBuilder.retry] to override this per request. + /// + /// [timeout] is optional and can be used to set a timeout in milliseconds for requests + /// + /// [urlLengthLimit] is optional and can be used to set the maximum URL length before a warning is logged. Defaults to 8000. PostgrestClient( this.url, { Map? headers, @@ -40,6 +53,8 @@ class PostgrestClient { YAJsonIsolate? isolate, this.retryEnabled = true, @visibleForTesting Duration Function(int attempt)? retryDelay, + this.timeout, + this.urlLengthLimit = 8000, }) : _schema = schema, headers = {...defaultHeaders, if (headers != null) ...headers}, _isolate = isolate ?? (YAJsonIsolate()..initialize()), @@ -77,6 +92,8 @@ class PostgrestClient { isolate: _isolate, retryEnabled: retryEnabled, retryDelay: _retryDelay, + timeout: timeout, + urlLengthLimit: urlLengthLimit, ); } @@ -92,6 +109,8 @@ class PostgrestClient { isolate: _isolate, retryEnabled: retryEnabled, retryDelay: _retryDelay, + timeout: timeout, + urlLengthLimit: urlLengthLimit, ); } @@ -124,6 +143,8 @@ class PostgrestClient { isolate: _isolate, retryEnabled: retryEnabled, retryDelay: _retryDelay, + timeout: timeout, + urlLengthLimit: urlLengthLimit, ).rpc(params, get); } diff --git a/packages/postgrest/lib/src/postgrest_builder.dart b/packages/postgrest/lib/src/postgrest_builder.dart index 89aa158db..1150d29ad 100644 --- a/packages/postgrest/lib/src/postgrest_builder.dart +++ b/packages/postgrest/lib/src/postgrest_builder.dart @@ -50,6 +50,14 @@ class PostgrestBuilder implements Future { final CountOption? _count; final bool _retryEnabled; final Duration Function(int attempt) _retryDelay; + + /// Optional timeout in milliseconds for this request. When set, the request + /// automatically aborts after this duration to prevent indefinite hangs. + final int? _timeout; + + /// Maximum URL length in characters before a warning is logged. Defaults to 8000. + final int _urlLengthLimit; + final _log = Logger('supabase.postgrest'); static Duration _defaultRetryDelay(int attempt) => @@ -69,6 +77,8 @@ class PostgrestBuilder implements Future { PostgrestConverter? converter, bool retryEnabled = true, @visibleForTesting Duration Function(int attempt)? retryDelay, + int? timeout, + int urlLengthLimit = 8000, }) : _maybeSingle = maybeSingle, _method = method, _converter = converter, @@ -80,7 +90,9 @@ class PostgrestBuilder implements Future { _count = count, _body = body, _retryEnabled = retryEnabled, - _retryDelay = retryDelay ?? _defaultRetryDelay; + _retryDelay = retryDelay ?? _defaultRetryDelay, + _timeout = timeout, + _urlLengthLimit = urlLengthLimit; PostgrestBuilder _copyWith({ Uri? url, @@ -109,6 +121,8 @@ class PostgrestBuilder implements Future { converter: converter ?? _converter, retryEnabled: retryEnabled ?? _retryEnabled, retryDelay: retryDelay ?? _retryDelay, + timeout: _timeout, + urlLengthLimit: _urlLengthLimit, ); } @@ -143,6 +157,15 @@ class PostgrestBuilder implements Future { } } + final urlLength = _url.toString().length; + if (urlLength > _urlLengthLimit) { + _log.warning( + 'Request URL is $urlLength characters, which exceeds the limit of $_urlLengthLimit. ' + 'If selecting many fields, consider using a view. ' + 'If filtering with large arrays, consider using an RPC function.', + ); + } + try { if (method == null) { throw ArgumentError( @@ -194,7 +217,8 @@ class PostgrestBuilder implements Future { throw StateError('Unknown HTTP method: ${method.value}'); } - final response = await _executeWithRetry(send, method, execHeaders); + final response = + await _executeWithRetry(send, method, execHeaders); return _parseResponse(response, method); } catch (error) { rethrow; @@ -213,7 +237,11 @@ class PostgrestBuilder implements Future { method == _HttpMethod.get || method == _HttpMethod.head; if (!_retryEnabled || !isRetryableMethod) { - return send(); + final responseFuture = send(); + if (_timeout != null) { + return responseFuture.timeout(Duration(milliseconds: _timeout!)); + } + return responseFuture; } for (var attempt = 0; attempt <= maxRetries; attempt++) { @@ -222,7 +250,10 @@ class PostgrestBuilder implements Future { } try { - final response = await send(); + final responseFuture = send(); + final response = _timeout != null + ? await responseFuture.timeout(Duration(milliseconds: _timeout!)) + : await responseFuture; if (!retryableStatusCodes.contains(response.statusCode) || attempt == maxRetries) { return response; diff --git a/packages/postgrest/lib/src/postgrest_query_builder.dart b/packages/postgrest/lib/src/postgrest_query_builder.dart index f15a9a6fd..fe1bba6d2 100644 --- a/packages/postgrest/lib/src/postgrest_query_builder.dart +++ b/packages/postgrest/lib/src/postgrest_query_builder.dart @@ -22,6 +22,8 @@ class PostgrestQueryBuilder extends RawPostgrestBuilder { YAJsonIsolate? isolate, bool retryEnabled = true, Duration Function(int attempt)? retryDelay, + int? timeout, + int urlLengthLimit = 8000, }) : super( PostgrestBuilder( url: url, @@ -32,6 +34,8 @@ class PostgrestQueryBuilder extends RawPostgrestBuilder { isolate: isolate, retryEnabled: retryEnabled, retryDelay: retryDelay, + timeout: timeout, + urlLengthLimit: urlLengthLimit, ), ); @@ -275,6 +279,8 @@ class PostgrestQueryBuilder extends RawPostgrestBuilder { isolate: _isolate, retryEnabled: enabled, retryDelay: _retryDelay, + timeout: _timeout, + urlLengthLimit: _urlLengthLimit, ); } @@ -289,6 +295,8 @@ class PostgrestQueryBuilder extends RawPostgrestBuilder { isolate: _isolate, retryEnabled: _retryEnabled, retryDelay: _retryDelay, + timeout: _timeout, + urlLengthLimit: _urlLengthLimit, ); } } diff --git a/packages/postgrest/lib/src/postgrest_rpc_builder.dart b/packages/postgrest/lib/src/postgrest_rpc_builder.dart index 123fdccc6..a6219b465 100644 --- a/packages/postgrest/lib/src/postgrest_rpc_builder.dart +++ b/packages/postgrest/lib/src/postgrest_rpc_builder.dart @@ -9,6 +9,8 @@ class PostgrestRpcBuilder extends RawPostgrestBuilder { required YAJsonIsolate isolate, bool retryEnabled = true, Duration Function(int attempt)? retryDelay, + int? timeout, + int urlLengthLimit = 8000, }) : super( PostgrestBuilder( url: Uri.parse(url), @@ -18,6 +20,8 @@ class PostgrestRpcBuilder extends RawPostgrestBuilder { isolate: isolate, retryEnabled: retryEnabled, retryDelay: retryDelay, + timeout: timeout, + urlLengthLimit: urlLengthLimit, ), ); diff --git a/packages/postgrest/lib/src/raw_postgrest_builder.dart b/packages/postgrest/lib/src/raw_postgrest_builder.dart index 2f6bb7f24..73aa8264a 100644 --- a/packages/postgrest/lib/src/raw_postgrest_builder.dart +++ b/packages/postgrest/lib/src/raw_postgrest_builder.dart @@ -16,6 +16,8 @@ class RawPostgrestBuilder extends PostgrestBuilder { converter: builder._converter, retryEnabled: builder._retryEnabled, retryDelay: builder._retryDelay, + timeout: builder._timeout, + urlLengthLimit: builder._urlLengthLimit, ); /// Very similar to [_copyWith], but allows changing the generics, therefore [_converter] is omitted @@ -42,6 +44,8 @@ class RawPostgrestBuilder extends PostgrestBuilder { maybeSingle: maybeSingle ?? _maybeSingle, retryEnabled: _retryEnabled, retryDelay: _retryDelay, + timeout: _timeout, + urlLengthLimit: _urlLengthLimit, )); } @@ -77,6 +81,8 @@ class RawPostgrestBuilder extends PostgrestBuilder { converter: converter, retryEnabled: _retryEnabled, retryDelay: _retryDelay, + timeout: _timeout, + urlLengthLimit: _urlLengthLimit, ); } } diff --git a/packages/postgrest/test/timeout_url_length_test.dart b/packages/postgrest/test/timeout_url_length_test.dart new file mode 100644 index 000000000..485a32092 --- /dev/null +++ b/packages/postgrest/test/timeout_url_length_test.dart @@ -0,0 +1,149 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:http/http.dart'; +import 'package:logging/logging.dart'; +import 'package:postgrest/postgrest.dart'; +import 'package:test/test.dart'; + +class _DelayedHttpClient extends BaseClient { + final Duration delay; + final int statusCode; + final String body; + + _DelayedHttpClient({ + required this.delay, + this.statusCode = 200, + this.body = '[]', + }); + + @override + Future send(BaseRequest request) async { + await Future.delayed(delay); + return StreamedResponse( + Stream.value(Uint8List.fromList(body.codeUnits)), + statusCode, + request: request, + ); + } +} + +class _InstantHttpClient extends BaseClient { + final int statusCode; + final String body; + + _InstantHttpClient({this.statusCode = 200, this.body = '[]'}); + + @override + Future send(BaseRequest request) async { + return StreamedResponse( + Stream.value(Uint8List.fromList(body.codeUnits)), + statusCode, + request: request, + ); + } +} + +void main() { + group('URL length validation', () { + test('logs warning when URL exceeds urlLengthLimit', () async { + final warnings = []; + final subscription = Logger.root.onRecord.listen((record) { + if (record.level == Level.WARNING) { + warnings.add(record.message); + } + }); + Logger.root.level = Level.ALL; + + final client = PostgrestClient( + 'http://localhost:3000', + httpClient: _InstantHttpClient(), + urlLengthLimit: 50, + ); + + // URL: http://localhost:3000/users?select=id,username,email,created_at — well over 50 chars + await client + .from('users') + .select('id,username,email,created_at') + .catchError((_) => []); + + await subscription.cancel(); + + expect( + warnings.any((w) => w.contains('exceeds the limit of 50')), + isTrue, + reason: 'Expected a warning about URL length', + ); + }); + + test('does not log warning when URL is within urlLengthLimit', () async { + final warnings = []; + final subscription = Logger.root.onRecord.listen((record) { + if (record.level == Level.WARNING && + record.message.contains('exceeds the limit')) { + warnings.add(record.message); + } + }); + Logger.root.level = Level.ALL; + + final client = PostgrestClient( + 'http://localhost:3000', + httpClient: _InstantHttpClient(), + urlLengthLimit: 8000, + ); + + await client.from('users').select().catchError((_) => []); + + await subscription.cancel(); + + expect(warnings, isEmpty, reason: 'Expected no URL length warning'); + }); + + test('default urlLengthLimit is 8000', () { + final client = PostgrestClient('http://localhost:3000'); + expect(client.urlLengthLimit, equals(8000)); + }); + + test('custom urlLengthLimit is stored', () { + final client = + PostgrestClient('http://localhost:3000', urlLengthLimit: 5000); + expect(client.urlLengthLimit, equals(5000)); + }); + }); + + group('Timeout configuration', () { + test('timeout is null by default', () { + final client = PostgrestClient('http://localhost:3000'); + expect(client.timeout, isNull); + }); + + test('custom timeout is stored', () { + final client = PostgrestClient('http://localhost:3000', timeout: 5000); + expect(client.timeout, equals(5000)); + }); + + test('request times out when response is delayed beyond timeout', () async { + final client = PostgrestClient( + 'http://localhost:3000', + httpClient: _DelayedHttpClient(delay: const Duration(seconds: 5)), + timeout: 100, // 100ms timeout + ); + + expect( + () => client.from('users').select(), + throwsA(isA()), + ); + }); + + test('request succeeds when response is within timeout', () async { + final client = PostgrestClient( + 'http://localhost:3000', + httpClient: _InstantHttpClient(body: '[{"id": 1}]'), + timeout: 5000, // 5 second timeout + ); + + final result = await client.from('users').select(); + expect(result, isA()); + }); + }); +} diff --git a/packages/supabase/lib/src/supabase_client.dart b/packages/supabase/lib/src/supabase_client.dart index 8a30b1206..4dfad8075 100644 --- a/packages/supabase/lib/src/supabase_client.dart +++ b/packages/supabase/lib/src/supabase_client.dart @@ -186,6 +186,8 @@ class SupabaseClient { httpClient: _authHttpClient, incrementId: _incrementId.increment(), isolate: _isolate, + timeout: _postgrestOptions.timeout, + urlLengthLimit: _postgrestOptions.urlLengthLimit, ); } @@ -308,6 +310,8 @@ class SupabaseClient { schema: _postgrestOptions.schema, httpClient: _authHttpClient, isolate: _isolate, + timeout: _postgrestOptions.timeout, + urlLengthLimit: _postgrestOptions.urlLengthLimit, ); } diff --git a/packages/supabase/lib/src/supabase_client_options.dart b/packages/supabase/lib/src/supabase_client_options.dart index 12045bed6..721b1e884 100644 --- a/packages/supabase/lib/src/supabase_client_options.dart +++ b/packages/supabase/lib/src/supabase_client_options.dart @@ -3,7 +3,19 @@ import 'package:supabase/supabase.dart'; class PostgrestClientOptions { final String schema; - const PostgrestClientOptions({this.schema = 'public'}); + /// Optional timeout in milliseconds for PostgREST requests. When set, + /// requests automatically abort after this duration to prevent indefinite hangs. + final int? timeout; + + /// Maximum URL length in characters before a warning is logged. Defaults to 8000. + /// Protects against exceeding server URL limits with large queries. + final int urlLengthLimit; + + const PostgrestClientOptions({ + this.schema = 'public', + this.timeout, + this.urlLengthLimit = 8000, + }); } class AuthClientOptions { diff --git a/packages/supabase/lib/src/supabase_query_builder.dart b/packages/supabase/lib/src/supabase_query_builder.dart index dd31713a3..14bd9a931 100644 --- a/packages/supabase/lib/src/supabase_query_builder.dart +++ b/packages/supabase/lib/src/supabase_query_builder.dart @@ -15,6 +15,8 @@ class SupabaseQueryBuilder extends PostgrestQueryBuilder { super.httpClient, required int incrementId, required super.isolate, + super.timeout, + super.urlLengthLimit = 8000, }) : _realtime = realtime, _schema = schema, _table = table, diff --git a/packages/supabase/lib/src/supabase_query_schema.dart b/packages/supabase/lib/src/supabase_query_schema.dart index d40c49407..7b35fe2dd 100644 --- a/packages/supabase/lib/src/supabase_query_schema.dart +++ b/packages/supabase/lib/src/supabase_query_schema.dart @@ -45,6 +45,8 @@ class SupabaseQuerySchema { httpClient: _authHttpClient, incrementId: _counter.increment(), isolate: _isolate, + timeout: _rest.timeout, + urlLengthLimit: _rest.urlLengthLimit, ); } From ba1d22efaf2d1b2d2f620be6fe959542cd9b6e58 Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Thu, 9 Apr 2026 11:56:43 -0300 Subject: [PATCH 2/4] fix(postgrest): fix field promotion null-safety issues in PostgrestBuilder Use local variable extraction to enable null promotion for final fields in PostgrestBuilder that could not be promoted due to class inheritance. This fixes dart test compilation errors affecting all test files. Co-Authored-By: Claude Sonnet 4.6 --- .../postgrest/lib/src/postgrest_builder.dart | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/packages/postgrest/lib/src/postgrest_builder.dart b/packages/postgrest/lib/src/postgrest_builder.dart index 1150d29ad..c063026b0 100644 --- a/packages/postgrest/lib/src/postgrest_builder.dart +++ b/packages/postgrest/lib/src/postgrest_builder.dart @@ -148,12 +148,13 @@ class PostgrestBuilder implements Future { // X-Retry-Count, etc.). final execHeaders = {..._headers}; - if (_count != null) { + final count = _count; + if (count != null) { if (execHeaders['Prefer'] != null) { final oldPreferHeader = execHeaders['Prefer']; - execHeaders['Prefer'] = '$oldPreferHeader,count=${_count.name}'; + execHeaders['Prefer'] = '$oldPreferHeader,count=${count.name}'; } else { - execHeaders['Prefer'] = 'count=${_count.name}'; + execHeaders['Prefer'] = 'count=${count.name}'; } } @@ -173,12 +174,13 @@ class PostgrestBuilder implements Future { ); } - if (_schema == null) { + final schema = _schema; + if (schema == null) { // skip } else if (method == _HttpMethod.get || method == _HttpMethod.head) { - execHeaders['Accept-Profile'] = _schema; + execHeaders['Accept-Profile'] = schema; } else { - execHeaders['Content-Profile'] = _schema; + execHeaders['Content-Profile'] = schema; } if (method != _HttpMethod.get && method != _HttpMethod.head) { execHeaders['Content-Type'] = 'application/json'; @@ -284,8 +286,9 @@ class PostgrestBuilder implements Future { body = response.body; } else { try { - if ((response.contentLength ?? 0) > 10000 && _isolate != null) { - body = await _isolate.decode(response.body); + final isolate = _isolate; + if ((response.contentLength ?? 0) > 10000 && isolate != null) { + body = await isolate.decode(response.body); } else { body = jsonDecode(response.body); } @@ -339,16 +342,17 @@ class PostgrestBuilder implements Future { } body as R; - if (_converter != null) { - converted = _converter(body); + final converter = _converter; + if (converter != null) { + converted = converter(body); } else { converted = body as S; } - if (_count != null && method != _HttpMethod.head) { + if (count != null && method != _HttpMethod.head) { return PostgrestResponse( data: converted, - count: count!, + count: count, ) as T; } else { return converted as T; @@ -400,17 +404,18 @@ class PostgrestBuilder implements Future { ) { if (error.details is String && error.details.toString().contains('Results contain 0 rows')) { + final converter = _converter; if (_count != null && response.request!.method != _HttpMethod.head.value) { - if (_converter != null) { - return PostgrestResponse(data: _converter(null as R), count: 0) + if (converter != null) { + return PostgrestResponse(data: converter(null as R), count: 0) as T; } else { return null as T; } } else { - if (_converter != null) { - return _converter(null as R) as T; + if (converter != null) { + return converter(null as R) as T; } else { return null as T; } From 8360bdb1381f5e616e8817d8c79fac46e3d23fe5 Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Thu, 9 Apr 2026 11:59:03 -0300 Subject: [PATCH 3/4] style: format dart code after melos bootstrap Co-Authored-By: Claude Sonnet 4.6 --- packages/postgrest/lib/src/postgrest_builder.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/postgrest/lib/src/postgrest_builder.dart b/packages/postgrest/lib/src/postgrest_builder.dart index c063026b0..1a5a75b8d 100644 --- a/packages/postgrest/lib/src/postgrest_builder.dart +++ b/packages/postgrest/lib/src/postgrest_builder.dart @@ -219,8 +219,7 @@ class PostgrestBuilder implements Future { throw StateError('Unknown HTTP method: ${method.value}'); } - final response = - await _executeWithRetry(send, method, execHeaders); + final response = await _executeWithRetry(send, method, execHeaders); return _parseResponse(response, method); } catch (error) { rethrow; From 76200844e94ca2479d47712e724d52bb39f12906 Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Thu, 9 Apr 2026 12:15:35 -0300 Subject: [PATCH 4/4] fix(postgrest): resolve dart analyze warnings from URL length and timeout changes Remove unnecessary null assertion operators on final field `_timeout` (Dart promotes final fields through null checks). Remove unused optional parameters `statusCode` and `body` from test HTTP client helpers. Co-Authored-By: Claude Sonnet 4.6 --- .../postgrest/lib/src/postgrest_builder.dart | 4 ++-- .../postgrest/test/timeout_url_length_test.dart | 17 +++++------------ 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/postgrest/lib/src/postgrest_builder.dart b/packages/postgrest/lib/src/postgrest_builder.dart index 1a5a75b8d..cbcb023ab 100644 --- a/packages/postgrest/lib/src/postgrest_builder.dart +++ b/packages/postgrest/lib/src/postgrest_builder.dart @@ -240,7 +240,7 @@ class PostgrestBuilder implements Future { if (!_retryEnabled || !isRetryableMethod) { final responseFuture = send(); if (_timeout != null) { - return responseFuture.timeout(Duration(milliseconds: _timeout!)); + return responseFuture.timeout(Duration(milliseconds: _timeout)); } return responseFuture; } @@ -253,7 +253,7 @@ class PostgrestBuilder implements Future { try { final responseFuture = send(); final response = _timeout != null - ? await responseFuture.timeout(Duration(milliseconds: _timeout!)) + ? await responseFuture.timeout(Duration(milliseconds: _timeout)) : await responseFuture; if (!retryableStatusCodes.contains(response.statusCode) || attempt == maxRetries) { diff --git a/packages/postgrest/test/timeout_url_length_test.dart b/packages/postgrest/test/timeout_url_length_test.dart index 485a32092..4ba54b3ff 100644 --- a/packages/postgrest/test/timeout_url_length_test.dart +++ b/packages/postgrest/test/timeout_url_length_test.dart @@ -8,37 +8,30 @@ import 'package:test/test.dart'; class _DelayedHttpClient extends BaseClient { final Duration delay; - final int statusCode; - final String body; - _DelayedHttpClient({ - required this.delay, - this.statusCode = 200, - this.body = '[]', - }); + _DelayedHttpClient({required this.delay}); @override Future send(BaseRequest request) async { await Future.delayed(delay); return StreamedResponse( - Stream.value(Uint8List.fromList(body.codeUnits)), - statusCode, + Stream.value(Uint8List.fromList('[]'.codeUnits)), + 200, request: request, ); } } class _InstantHttpClient extends BaseClient { - final int statusCode; final String body; - _InstantHttpClient({this.statusCode = 200, this.body = '[]'}); + _InstantHttpClient({this.body = '[]'}); @override Future send(BaseRequest request) async { return StreamedResponse( Stream.value(Uint8List.fromList(body.codeUnits)), - statusCode, + 200, request: request, ); }