Skip to content

Commit

Permalink
Add responseHeaders extension on XMLHttpRequest (#298)
Browse files Browse the repository at this point in the history
* Add `responseHeaders` extension on `XMLHttpRequest`

Move this extension from `package:http` to here, it might also be used in `package:grpc`.

* Add test

* Reformat

* Add changelog

* Use LineSplitter

* Use `update`

* Use split instead of indexOf
  • Loading branch information
mosuem authored Sep 4, 2024
1 parent fcd8123 commit 6a8c3c5
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
1 change: 1 addition & 0 deletions web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
`getter`s and `setter`s, respectively.
- Exposed constants with primitive values as non-`external` so they can be
`switch`ed over.
- Add an extension `responseHeaders` to `XMLHttpRequest`.

## 1.0.0

Expand Down
31 changes: 31 additions & 0 deletions web/lib/src/helpers/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
/// * conversions: for example to wrap a `TouchList` as a `List<Touch>`
library;

import 'dart:convert';
import 'dart:js_interop';
import 'dart:math' show Point;

Expand Down Expand Up @@ -103,3 +104,33 @@ extension TouchListConvert on TouchList {
@Deprecated('Use JSImmutableListWrapper<TouchList, Touch> directly instead.')
List<Touch> toList() => JSImmutableListWrapper<TouchList, Touch>(this);
}

/// Returns all response headers as a key-value map.
///
/// Multiple values for the same header key can be combined into one,
/// separated by a comma and a space.
///
/// See: http://www.w3.org/TR/XMLHttpRequest/#the-getresponseheader()-method
extension XMLHttpRequestGlue on XMLHttpRequest {
Map<String, String> get responseHeaders {
// from Closure's goog.net.Xhrio.getResponseHeaders.
final headers = <String, String>{};
final headersString = getAllResponseHeaders();
final headersList =
LineSplitter.split(headersString).where((header) => header.isNotEmpty);
for (final header in headersList) {
final split = header.split(': ');
if (split.length <= 1) {
continue;
}
final key = split[0].toLowerCase();
final value = split.skip(1).join(': ');
headers.update(
key,
(oldValue) => '$oldValue, $value',
ifAbsent: () => value,
);
}
return headers;
}
}
19 changes: 19 additions & 0 deletions web/test/helpers_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,23 @@ void main() {
// Ensure accessing any arbitrary item in the list does not throw.
expect(() => dartList[0], returnsNormally);
});

test('responseHeaders transforms headers into a map', () async {
final request = XMLHttpRequest()
..open('GET', 'www.google.com')
..send();

await request.onLoad.first;

expect(
request.responseHeaders,
allOf(
containsPair('content-length', '10'),
containsPair('content-type', 'text/plain; charset=utf-8'),
containsPair('x-content-type-options', 'nosniff'),
containsPair('x-frame-options', 'SAMEORIGIN'),
containsPair('x-xss-protection', '1; mode=block'),
),
);
});
}

0 comments on commit 6a8c3c5

Please sign in to comment.