Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/src/_internal/web_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ extension type Headers._(JSObject _) implements web.Headers {
external ArrayIterator keys();
external ArrayIterator values();

factory Headers.fromHost(web.Headers host) => Headers._(host);

factory Headers.fromEntries(Iterable<MapEntry<String, String>> entries) {
final headers = Headers();
for (final MapEntry(key: name, :value) in entries) {
Expand Down
3 changes: 3 additions & 0 deletions lib/src/fetch/headers.js.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,6 @@ class Headers
}
}
}

Headers headersFromHost(dom.Headers host) =>
Headers._(web.Headers.fromHost(host));
186 changes: 89 additions & 97 deletions lib/src/fetch/response.io.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,42 @@ final class NativeResponseHost extends ResponseHost<native.Response> {
const NativeResponseHost(super.value);
}

final class _ResponseMetadata {
_ResponseMetadata({
required this.redirected,
required this.status,
required this.statusText,
required this.type,
required this.url,
});

factory _ResponseMetadata.from(
native.Response response, [
native.ResponseInit? init,
]) {
return _ResponseMetadata(
redirected: response.redirected,
status: init?.status ?? response.status,
statusText: init?.statusText ?? response.statusText,
type: response.type,
url: response.url,
);
}

final bool redirected;
final int status;
final String statusText;
final native.ResponseType type;
final String url;
}

class Response implements native.Response {
Response._(
this._host, {
_ResponseMetadata? metadata,
io_headers.Headers? headers,
bool? redirected,
int? status,
String? statusText,
native.ResponseType? type,
String? url,
}) : _headers = headers,
_redirected = redirected,
_status = status,
_statusText = statusText,
_type = type,
_url = url;
}) : _metadata = metadata,
_headers = headers;

factory Response([Object? body, native.ResponseInit? init]) {
return switch ((body, init)) {
Expand Down Expand Up @@ -70,13 +91,9 @@ class Response implements native.Response {
}

final ResponseHost _host;
final _ResponseMetadata? _metadata;
io_headers.Headers? _headers;
Body? _body;
final bool? _redirected;
final int? _status;
final String? _statusText;
final native.ResponseType? _type;
final String? _url;

@override
io_headers.Headers get headers {
Expand Down Expand Up @@ -107,8 +124,8 @@ class Response implements native.Response {

@override
bool get ok {
final status = _status;
if (status != null) return HttpStatus.isSuccess(status);
final metadata = _metadata;
if (metadata != null) return HttpStatus.isSuccess(metadata.status);

return switch (_host) {
final HttpClientResponseHost host => HttpStatus.isSuccess(
Expand All @@ -120,8 +137,8 @@ class Response implements native.Response {

@override
bool get redirected {
final redirected = _redirected;
if (redirected != null) return redirected;
final metadata = _metadata;
if (metadata != null) return metadata.redirected;

return switch (_host) {
final HttpClientResponseHost host => host.value.redirects.isNotEmpty,
Expand All @@ -131,8 +148,8 @@ class Response implements native.Response {

@override
int get status {
final status = _status;
if (status != null) return status;
final metadata = _metadata;
if (metadata != null) return metadata.status;

return switch (_host) {
final HttpClientResponseHost host => host.value.statusCode,
Expand All @@ -142,8 +159,8 @@ class Response implements native.Response {

@override
String get statusText {
final statusText = _statusText;
if (statusText != null) return statusText;
final metadata = _metadata;
if (metadata != null) return metadata.statusText;

return switch (_host) {
final HttpClientResponseHost host => host.value.reasonPhrase,
Expand All @@ -153,8 +170,8 @@ class Response implements native.Response {

@override
native.ResponseType get type {
final type = _type;
if (type != null) return type;
final metadata = _metadata;
if (metadata != null) return metadata.type;

return switch (_host) {
final HttpClientResponseHost _ => native.ResponseType.default_,
Expand All @@ -164,8 +181,8 @@ class Response implements native.Response {

@override
String get url {
final url = _url;
if (url != null) return url;
final metadata = _metadata;
if (metadata != null) return metadata.url;

return switch (_host) {
final HttpClientResponseHost _ => '',
Expand Down Expand Up @@ -232,15 +249,12 @@ class Response implements native.Response {

@override
Response clone() {
final metadata = _ResponseMetadata.from(this);
return switch (_host) {
final NativeResponseHost host => Response._(
NativeResponseHost(host.value.clone()),
metadata: metadata,
headers: io_headers.Headers(headers),
redirected: redirected,
status: status,
statusText: statusText,
type: type,
url: url,
),
final HttpClientResponseHost _ => Response._(
NativeResponseHost(
Expand All @@ -253,9 +267,7 @@ class Response implements native.Response {
),
),
),
redirected: redirected,
type: type,
url: url,
metadata: metadata,
),
};
}
Expand All @@ -272,93 +284,73 @@ class Response implements native.Response {
Response response,
native.ResponseInit? init,
) {
if (init?.status == null && response.status == 0) {
final clone = response.clone();
return Response._(
clone._host,
headers: io_headers.Headers(init?.headers ?? response.headers),
redirected: response.redirected,
status: response.status,
statusText: init?.statusText ?? response.statusText,
type: response.type,
url: response.url,
);
}

return Response._(
NativeResponseHost(_nativeResponseFromWrappedResponse(response, init)),
redirected: response.redirected,
type: response.type,
url: response.url,
return _responseFromNativeCopySource(
response,
init,
cloneHost: () => response.clone()._host,
body: response._bodyForNativeCopy,
);
}

static Response _responseFromNativeResponse(
native.Response response,
native.ResponseInit? init,
) {
if (init?.status == null && response.status == 0) {
return Response._(
NativeResponseHost(response.clone()),
headers: io_headers.Headers(init?.headers ?? response.headers),
redirected: response.redirected,
status: response.status,
statusText: init?.statusText ?? response.statusText,
type: response.type,
url: response.url,
);
}

return Response._(
NativeResponseHost(_nativeResponseFromNativeResponse(response, init)),
redirected: response.redirected,
type: response.type,
url: response.url,
return _responseFromNativeCopySource(
response,
init,
cloneHost: () => NativeResponseHost(response.clone()),
body: () => response.body,
);
}

static native.Response _nativeResponseFromWrappedResponse(
Response response,
native.ResponseInit? init,
) {
static Response _responseFromNativeCopySource(
native.Response response,
native.ResponseInit? init, {
required ResponseHost Function() cloneHost,
required Body? Function() body,
}) {
final metadata = _ResponseMetadata.from(response, init);
final sourceHeaders = io_headers.Headers(response.headers);
return _nativeResponseFromCopy(
response._bodyForNativeCopy(),
status: init?.status ?? response.status,
statusText: init?.statusText ?? response.statusText,
headers: init?.headers ?? sourceHeaders,
preserveMissingContentType:
init?.headers == null && !sourceHeaders.has('content-type'),
final effectiveHeaders = io_headers.Headers(init?.headers ?? sourceHeaders);
if (init?.status == null && metadata.status == 0) {
return Response._(
cloneHost(),
metadata: metadata,
headers: effectiveHeaders,
);
}

final nativeCopy = _nativeResponseFromCopy(
body(),
metadata: metadata,
headers: effectiveHeaders,
preserveMissingContentType: _shouldPreserveMissingContentType(
init,
sourceHeaders,
),
);
return Response._(NativeResponseHost(nativeCopy), metadata: metadata);
}

static native.Response _nativeResponseFromNativeResponse(
native.Response response,
static bool _shouldPreserveMissingContentType(
native.ResponseInit? init,
io_headers.Headers sourceHeaders,
) {
final sourceHeaders = io_headers.Headers(response.headers);
return _nativeResponseFromCopy(
response.body,
status: init?.status ?? response.status,
statusText: init?.statusText ?? response.statusText,
headers: init?.headers ?? sourceHeaders,
preserveMissingContentType:
init?.headers == null && !sourceHeaders.has('content-type'),
);
return init?.headers == null && !sourceHeaders.has('content-type');
}

static native.Response _nativeResponseFromCopy(
Body? body, {
required int status,
required String statusText,
required _ResponseMetadata metadata,
required Object? headers,
required bool preserveMissingContentType,
}) {
final response = native.Response(
body,
native.ResponseInit(
status: status,
statusText: statusText,
status: metadata.status,
statusText: metadata.statusText,
headers: headers,
),
);
Expand Down
Loading