Skip to content

Commit 1f5caea

Browse files
authored
Added OnHttpCall hook to the Client (#62)
1 parent b6b0fbb commit 1f5caea

File tree

5 files changed

+91
-20
lines changed

5 files changed

+91
-20
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [2.1.0] - 2019-12-04
10+
### Added
11+
- `onHttpCall` hook to enable raw http request/response logging ([#60](https://github.com/f3ath/json-api-dart/issues/60)).
12+
913
## [2.0.3] - 2019-09-29
1014
### Fixed
1115
- Documentation links got broken due to pub.dev update.

lib/src/client/client.dart

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,20 @@ import 'package:json_api/src/document_builder.dart';
1717
/// JSON:API client
1818
class JsonApiClient {
1919
static const contentType = 'application/vnd.api+json';
20-
2120
final http.Client httpClient;
21+
final OnHttpCall _onHttpCall;
2222
final SimpleDocumentBuilder _build;
2323

24-
const JsonApiClient(this.httpClient, {SimpleDocumentBuilder builder})
25-
: _build = builder ?? const DocumentBuilder();
24+
/// Creates an instance of JSON:API client.
25+
/// You have to create and pass an instance of the [httpClient] yourself.
26+
/// Do not forget to call [httpClient.close()] when you're done using
27+
/// the JSON:API client.
28+
/// The [onHttpCall] hook, if passed, gets called when an http response is
29+
/// received from the HTTP Client.
30+
const JsonApiClient(this.httpClient,
31+
{SimpleDocumentBuilder builder, OnHttpCall onHttpCall})
32+
: _build = builder ?? const DocumentBuilder(),
33+
_onHttpCall = onHttpCall ?? _doNothing;
2634

2735
/// Fetches a resource collection by sending a GET query to the [uri].
2836
/// Use [headers] to pass extra HTTP headers.
@@ -161,7 +169,7 @@ class JsonApiClient {
161169
http.Request request, D decodePrimaryData(Object _)) async {
162170
final response =
163171
await http.Response.fromStream(await httpClient.send(request));
164-
172+
_onHttpCall(request, response);
165173
if (response.body.isEmpty) {
166174
return Response(response.statusCode, response.headers);
167175
}
@@ -177,3 +185,9 @@ class JsonApiClient {
177185
body == null ? null : Document.decodeJson(body, decodePrimaryData));
178186
}
179187
}
188+
189+
/// Defines the hook which gets called when the HTTP response is received from
190+
/// the HTTP Client.
191+
typedef void OnHttpCall(http.Request request, http.Response response);
192+
193+
_doNothing(http.Request request, http.Response response) {}

pubspec.yaml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
author: "Alexey Karapetov <karapetov@gmail.com>"
2-
description: "JSON:API Client for Flutter, Web and VM. Supports JSON:API v1.0 (http://jsonapi.org)"
3-
homepage: "https://github.com/f3ath/json-api-dart"
4-
name: "json_api"
5-
version: "2.0.3"
1+
name: json_api
2+
author: Alexey Karapetov <karapetov@gmail.com>
3+
version: 2.1.0
4+
homepage: https://github.com/f3ath/json-api-dart
5+
description: JSON:API Client for Flutter, Web and VM. Supports JSON:API v1.0 (http://jsonapi.org)
6+
environment:
7+
sdk: '>=2.3.0 <3.0.0'
68
dependencies:
7-
collection: "^1.14.11"
8-
http: "^0.12.0"
9+
http: ^0.12.0
10+
collection: ^1.14.11
911
dev_dependencies:
10-
json_matcher: "^0.2.3"
11-
stream_channel: "^1.6.8"
12-
test: "^1.6.1"
13-
uuid: "^2.0.1"
14-
environment:
15-
sdk: ">=2.3.0 <3.0.0"
12+
test: ^1.6.1
13+
json_matcher: ^0.2.3
14+
stream_channel: ^1.6.8
15+
uuid: ^2.0.1
Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
1-
import 'package:http/http.dart';
1+
import 'package:http/http.dart' as http;
22
import 'package:json_api/json_api.dart';
33
import 'package:test/test.dart';
44

55
void main() async {
6+
http.Request request;
7+
http.Response response;
8+
final httpClient = http.Client();
9+
final client = JsonApiClient(httpClient, onHttpCall: (req, resp) {
10+
request = req;
11+
response = resp;
12+
});
13+
614
test('can fetch collection', () async {
715
final channel = spawnHybridUri('test_server.dart');
8-
final httpClient = Client();
9-
final client = JsonApiClient(httpClient);
1016
final port = await channel.stream.first;
1117
final r = await client
1218
.fetchCollection(Uri.parse('http://localhost:$port/companies'));
19+
1320
httpClient.close();
1421
expect(r.status, 200);
1522
expect(r.isSuccessful, true);
1623
expect(r.data.unwrap().first.attributes['name'], 'Tesla');
24+
25+
expect(request, isNotNull);
26+
expect(response, isNotNull);
27+
expect(response.body, isNotEmpty);
1728
}, testOn: 'browser');
1829
}

test/functional/hooks_test.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import 'dart:io';
2+
3+
import 'package:http/http.dart' as http;
4+
import 'package:json_api/json_api.dart';
5+
import 'package:json_api/server.dart';
6+
import 'package:test/test.dart';
7+
8+
import '../../example/cars_server.dart';
9+
10+
void main() async {
11+
HttpServer server;
12+
http.Client httpClient;
13+
JsonApiClient client;
14+
http.Request request;
15+
http.Response response;
16+
final port = 8083;
17+
final urlDesign = PathBasedUrlDesign(Uri.parse('http://localhost:$port'));
18+
19+
setUp(() async {
20+
httpClient = http.Client();
21+
client = JsonApiClient(httpClient, onHttpCall: (req, resp) {
22+
request = req;
23+
response = resp;
24+
});
25+
server = await createServer(InternetAddress.loopbackIPv4, port);
26+
});
27+
28+
tearDown(() async {
29+
httpClient.close();
30+
await server.close();
31+
});
32+
33+
group('hooks', () {
34+
test('onHttpCall gets called', () async {
35+
await client.fetchCollection(urlDesign.collection('companies'));
36+
37+
expect(request, isNotNull);
38+
expect(response, isNotNull);
39+
expect(response.body, isNotEmpty);
40+
});
41+
}, testOn: 'vm');
42+
}

0 commit comments

Comments
 (0)