Skip to content

Commit

Permalink
Add support for setting headers for all requests (#1060)
Browse files Browse the repository at this point in the history
  • Loading branch information
brianquinlan authored Dec 4, 2023
1 parent c90496e commit d8983fa
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 3 deletions.
5 changes: 4 additions & 1 deletion pkgs/cupertino_http/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
## 1.1.1-wip
## 1.2.0-wip

* Add support for setting additional http headers in
`URLSessionConfiguration`.

## 1.1.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,38 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:io';

import 'package:cupertino_http/cupertino_http.dart';
import 'package:integration_test/integration_test.dart';
import 'package:test/test.dart';

/// Make a HTTP request using the given configuration and return the headers
/// received by the server.
Future<Map<String, List<String>>> sentHeaders(
URLSessionConfiguration config) async {
final session = URLSession.sessionWithConfiguration(config);
final headers = <String, List<String>>{};
final server = (await HttpServer.bind('localhost', 0))
..listen((request) async {
request.headers.forEach((k, v) => headers[k] = v);
await request.drain<void>();
request.response.headers.set('Content-Type', 'text/plain');
request.response.write('Hello World');
await request.response.close();
});

final task = session.dataTaskWithRequest(URLRequest.fromUrl(
Uri(scheme: 'http', host: 'localhost', port: server.port)))
..resume();
while (task.state != URLSessionTaskState.urlSessionTaskStateCompleted) {
await pumpEventQueue();
}

await server.close();
return headers;
}

void testProperties(URLSessionConfiguration config) {
group('properties', () {
test('allowsCellularAccess', () {
Expand All @@ -32,6 +60,22 @@ void testProperties(URLSessionConfiguration config) {
config.discretionary = false;
expect(config.discretionary, false);
});
test('httpAdditionalHeaders', () async {
expect(config.httpAdditionalHeaders, isNull);

config.httpAdditionalHeaders = {
'User-Agent': 'My Client',
'MyHeader': 'myvalue'
};
expect(config.httpAdditionalHeaders,
{'User-Agent': 'My Client', 'MyHeader': 'myvalue'});
final headers = await sentHeaders(config);
expect(headers, containsPair('user-agent', ['My Client']));
expect(headers, containsPair('myheader', ['myvalue']));

config.httpAdditionalHeaders = null;
expect(config.httpAdditionalHeaders, isNull);
});
test('httpCookieAcceptPolicy', () {
config.httpCookieAcceptPolicy =
HTTPCookieAcceptPolicy.httpCookieAcceptPolicyAlways;
Expand Down
5 changes: 4 additions & 1 deletion pkgs/cupertino_http/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import 'book.dart';
void main() {
var clientFactory = Client.new; // The default Client.
if (Platform.isIOS || Platform.isMacOS) {
clientFactory = CupertinoClient.defaultSessionConfiguration.call;
final config = URLSessionConfiguration.ephemeralSessionConfiguration()
..cache = URLCache.withCapacity(memoryCapacity: 2 * 1024 * 1024)
..httpAdditionalHeaders = {'User-Agent': 'Book Agent'};
clientFactory = () => CupertinoClient.fromSessionConfiguration(config);
}
runWithClient(() => runApp(const BookSearchApp()), clientFactory);
}
Expand Down
27 changes: 27 additions & 0 deletions pkgs/cupertino_http/lib/src/cupertino_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,32 @@ class URLSessionConfiguration
bool get discretionary => _nsObject.discretionary;
set discretionary(bool value) => _nsObject.discretionary = value;

/// Additional headers to send with each request.
///
/// Note that the getter for this field returns a **copy** of the headers.
///
/// See [NSURLSessionConfiguration.HTTPAdditionalHeaders](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1411532-httpadditionalheaders)
Map<String, String>? get httpAdditionalHeaders {
if (_nsObject.HTTPAdditionalHeaders case var additionalHeaders?) {
final headers = ncb.NSDictionary.castFrom(additionalHeaders);
return stringDictToMap(headers);
}
return null;
}

set httpAdditionalHeaders(Map<String, String>? headers) {
if (headers == null) {
_nsObject.HTTPAdditionalHeaders = null;
return;
}
final d = ncb.NSMutableDictionary.alloc(linkedLibs).init();
headers.forEach((key, value) {
d.setObject_forKey_(
value.toNSString(linkedLibs), key.toNSString(linkedLibs));
});
_nsObject.HTTPAdditionalHeaders = d;
}

/// What policy to use when deciding whether to accept cookies.
///
/// See [NSURLSessionConfiguration.HTTPCookieAcceptPolicy](https://developer.apple.com/documentation/foundation/nsurlsessionconfiguration/1408933-httpcookieacceptpolicy).
Expand Down Expand Up @@ -441,6 +467,7 @@ class URLSessionConfiguration
'allowsConstrainedNetworkAccess=$allowsConstrainedNetworkAccess '
'allowsExpensiveNetworkAccess=$allowsExpensiveNetworkAccess '
'discretionary=$discretionary '
'httpAdditionalHeaders=$httpAdditionalHeaders '
'httpCookieAcceptPolicy=$httpCookieAcceptPolicy '
'httpShouldSetCookies=$httpShouldSetCookies '
'httpMaximumConnectionsPerHost=$httpMaximumConnectionsPerHost '
Expand Down
2 changes: 1 addition & 1 deletion pkgs/cupertino_http/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: cupertino_http
version: 1.1.1-wip
version: 1.2.0-wip
description: >-
A macOS/iOS Flutter plugin that provides access to the Foundation URL
Loading System.
Expand Down

0 comments on commit d8983fa

Please sign in to comment.