Skip to content

Commit 40c2ee9

Browse files
committed
Add Response.url
Closes #321, closes #623, closes #692 Fixes #293 Add a Uri field to BaseResponse with the final, potentially redirected, url for the content. The field is nullable for backwards compatibility - TODO: consider if this should be non-nullable from the start, or if it can be published nullable first and become non-nullable (and the constructor arg required) in the next breaking release. This may break tests which use bocks but do not mock the field used to read the URL.
1 parent 74a4371 commit 40c2ee9

9 files changed

+24
-0
lines changed

lib/src/base_request.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ abstract class BaseRequest {
137137
request: response.request,
138138
headers: response.headers,
139139
isRedirect: response.isRedirect,
140+
url: response.url,
140141
persistentConnection: response.persistentConnection,
141142
reasonPhrase: response.reasonPhrase);
142143
} catch (_) {

lib/src/base_response.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ abstract class BaseResponse {
3131

3232
final bool isRedirect;
3333

34+
final Uri? url;
35+
3436
/// Whether the server requested that a persistent connection be maintained.
3537
final bool persistentConnection;
3638

@@ -39,6 +41,7 @@ abstract class BaseResponse {
3941
this.request,
4042
this.headers = const {},
4143
this.isRedirect = false,
44+
this.url,
4245
this.persistentConnection = true,
4346
this.reasonPhrase}) {
4447
if (statusCode < 100) {

lib/src/browser_client.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,15 @@ class BrowserClient extends BaseClient {
5353

5454
unawaited(xhr.onLoad.first.then((_) {
5555
var body = (xhr.response as ByteBuffer).asUint8List();
56+
var responseUrl = xhr.responseUrl;
57+
var url = (responseUrl != null && responseUrl.isNotEmpty)
58+
? Uri.parse(responseUrl)
59+
: null;
5660
completer.complete(StreamedResponse(
5761
ByteStream.fromBytes(body), xhr.status!,
5862
contentLength: body.length,
5963
request: request,
64+
url: url,
6065
headers: xhr.responseHeaders,
6166
reasonPhrase: xhr.statusText));
6267
}));

lib/src/io_client.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ class IOClient extends BaseClient {
5959
request: request,
6060
headers: headers,
6161
isRedirect: response.isRedirect,
62+
url: response.redirects.isNotEmpty
63+
? response.redirects.last.location
64+
: request.url,
6265
persistentConnection: response.persistentConnection,
6366
reasonPhrase: response.reasonPhrase,
6467
inner: response);

lib/src/io_streamed_response.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class IOStreamedResponse extends StreamedResponse {
2222
BaseRequest? request,
2323
Map<String, String> headers = const {},
2424
bool isRedirect = false,
25+
Uri? url,
2526
bool persistentConnection = true,
2627
String? reasonPhrase,
2728
HttpClientResponse? inner})
@@ -31,6 +32,7 @@ class IOStreamedResponse extends StreamedResponse {
3132
request: request,
3233
headers: headers,
3334
isRedirect: isRedirect,
35+
url: url,
3436
persistentConnection: persistentConnection,
3537
reasonPhrase: reasonPhrase);
3638

lib/src/mock_client.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class MockClient extends BaseClient {
4646
request: response.request,
4747
headers: response.headers,
4848
isRedirect: response.isRedirect,
49+
url: response.url,
4950
persistentConnection: response.persistentConnection,
5051
reasonPhrase: response.reasonPhrase);
5152
});
@@ -60,6 +61,7 @@ class MockClient extends BaseClient {
6061
request: response.request,
6162
headers: response.headers,
6263
isRedirect: response.isRedirect,
64+
url: response.url,
6365
persistentConnection: response.persistentConnection,
6466
reasonPhrase: response.reasonPhrase);
6567
});

lib/src/response.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@ class Response extends BaseResponse {
3232
{BaseRequest? request,
3333
Map<String, String> headers = const {},
3434
bool isRedirect = false,
35+
Uri? url,
3536
bool persistentConnection = true,
3637
String? reasonPhrase})
3738
: this.bytes(_encodingForHeaders(headers).encode(body), statusCode,
3839
request: request,
3940
headers: headers,
4041
isRedirect: isRedirect,
42+
url: url,
4143
persistentConnection: persistentConnection,
4244
reasonPhrase: reasonPhrase);
4345

@@ -46,6 +48,7 @@ class Response extends BaseResponse {
4648
{BaseRequest? request,
4749
Map<String, String> headers = const {},
4850
bool isRedirect = false,
51+
Uri? url,
4952
bool persistentConnection = true,
5053
String? reasonPhrase})
5154
: bodyBytes = toUint8List(bodyBytes),
@@ -54,6 +57,7 @@ class Response extends BaseResponse {
5457
request: request,
5558
headers: headers,
5659
isRedirect: isRedirect,
60+
url: url,
5761
persistentConnection: persistentConnection,
5862
reasonPhrase: reasonPhrase);
5963

lib/src/streamed_response.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class StreamedResponse extends BaseResponse {
2323
BaseRequest? request,
2424
Map<String, String> headers = const {},
2525
bool isRedirect = false,
26+
Uri? url,
2627
bool persistentConnection = true,
2728
String? reasonPhrase})
2829
: stream = toByteStream(stream),
@@ -31,6 +32,7 @@ class StreamedResponse extends BaseResponse {
3132
request: request,
3233
headers: headers,
3334
isRedirect: isRedirect,
35+
url: url,
3436
persistentConnection: persistentConnection,
3537
reasonPhrase: reasonPhrase);
3638
}

test/io/request_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ void main() {
4444
final response = await request.send();
4545

4646
expect(response.statusCode, equals(302));
47+
expect(response.url, serverUrl.resolve('/redirect'));
4748
});
4849

4950
test('with redirects', () async {
@@ -53,6 +54,7 @@ void main() {
5354
expect(response.statusCode, equals(200));
5455
final bytesString = await response.stream.bytesToString();
5556
expect(bytesString, parse(containsPair('path', '/')));
57+
expect(response.url, serverUrl.resolve('/'));
5658
});
5759

5860
test('exceeding max redirects', () async {

0 commit comments

Comments
 (0)