Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for setting headers for all requests #1060

Merged
merged 11 commits into from
Dec 4, 2023
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
Loading