From 27243b1f9ea260202e5119efcbac5d43d37c48b4 Mon Sep 17 00:00:00 2001 From: Ethan Lee <125412902+ethan-tbd@users.noreply.github.com> Date: Mon, 22 Apr 2024 18:41:15 -0700 Subject: [PATCH] fix: update with web5 changes (#17) --- lib/src/http_client/tbdex_http_client.dart | 58 ++++--- test/http_client/tbdex_http_client_test.dart | 169 +++++++++++-------- 2 files changed, 125 insertions(+), 102 deletions(-) diff --git a/lib/src/http_client/tbdex_http_client.dart b/lib/src/http_client/tbdex_http_client.dart index 67754bc..c1f97f0 100644 --- a/lib/src/http_client/tbdex_http_client.dart +++ b/lib/src/http_client/tbdex_http_client.dart @@ -1,6 +1,6 @@ import 'dart:convert'; +import 'dart:io'; -import 'package:http/http.dart' as http; import 'package:tbdex/src/http_client/models/create_exchange_request.dart'; import 'package:tbdex/src/http_client/models/exchange.dart'; import 'package:tbdex/src/http_client/models/get_offerings_filter.dart'; @@ -19,10 +19,10 @@ class TbdexHttpClient { static const _jsonHeader = 'application/json'; static const _expirationDuration = Duration(minutes: 5); - static http.Client _client = http.Client(); + static HttpClient _client = HttpClient(); // ignore: avoid_setters_without_getters - static set client(http.Client client) { + static set client(HttpClient client) { _client = client; } @@ -35,18 +35,17 @@ class TbdexHttpClient { final pfiServiceEndpoint = await _getPfiServiceEndpoint(pfiDid); final url = Uri.parse('$pfiServiceEndpoint/exchanges/$exchangeId'); - final response = await _client.get( - url, - headers: { - 'Authorization': 'Bearer $requestToken', - }, - ); + final request = await _client.getUrl(url); + request.headers.set('Authorization', 'Bearer $requestToken'); + final response = await request.close(); + + final body = await response.transform(utf8.decoder).join(); if (response.statusCode != 200) { - throw Exception('failed to fetch exchange: ${response.body}'); + throw Exception('failed to fetch exchange: $body'); } - return Parser.parseExchange(response.body); + return Parser.parseExchange(body); } static Future> getExchanges( @@ -57,18 +56,17 @@ class TbdexHttpClient { final pfiServiceEndpoint = await _getPfiServiceEndpoint(pfiDid); final url = Uri.parse('$pfiServiceEndpoint/exchanges/'); - final response = await _client.get( - url, - headers: { - 'Authorization': 'Bearer $requestToken', - }, - ); + final request = await _client.getUrl(url); + request.headers.set('Authorization', 'Bearer $requestToken'); + final response = await request.close(); + + final body = await response.transform(utf8.decoder).join(); if (response.statusCode != 200) { - throw Exception('failed to fetch exchanges: ${response.body}'); + throw Exception('failed to fetch exchanges: $body'); } - return Parser.parseExchanges(response.body); + return Parser.parseExchanges(body); } static Future> getOfferings( @@ -80,13 +78,16 @@ class TbdexHttpClient { queryParameters: filter?.toJson(), ); - final response = await _client.get(url); + final request = await _client.getUrl(url); + final response = await request.close(); + + final body = await response.transform(utf8.decoder).join(); if (response.statusCode != 200) { throw Exception(response); } - return Parser.parseOfferings(response.body); + return Parser.parseOfferings(body); } static Future createExchange( @@ -129,11 +130,9 @@ class TbdexHttpClient { final path = '/exchanges${exchangeId != null ? '/$exchangeId' : ''}'; final url = Uri.parse(pfiServiceEndpoint + path); - final response = await _client.post( - url, - headers: {'Content-Type': _jsonHeader}, - body: requestBody, - ); + final request = await _client.postUrl(url); + request.headers.set('Content-Type', _jsonHeader); + final response = await request.close(); if (response.statusCode != 201) { throw Exception(response); @@ -152,7 +151,12 @@ class TbdexHttpClient { orElse: () => throw Exception('did does not have service of type PFI'), ); - return service?.serviceEndpoint ?? ''; + final endpoint = service?.serviceEndpoint ?? []; + + if (endpoint.isEmpty) { + throw Exception('no service endpoints found'); + } + return 'http://${endpoint[0]}'; } static Future _generateRequestToken( diff --git a/test/http_client/tbdex_http_client_test.dart b/test/http_client/tbdex_http_client_test.dart index 5156b25..f1fc332 100644 --- a/test/http_client/tbdex_http_client_test.dart +++ b/test/http_client/tbdex_http_client_test.dart @@ -1,34 +1,52 @@ -import 'package:http/http.dart' as http; +import 'dart:convert'; +import 'dart:io'; + import 'package:mocktail/mocktail.dart'; import 'package:tbdex/src/http_client/tbdex_http_client.dart'; import 'package:test/test.dart'; import '../test_data.dart'; -class MockClient extends Mock implements http.Client {} +class MockClient extends Mock implements HttpClient {} + +class MockHttpHeaders extends Mock implements HttpHeaders {} + +class MockHttpRequest extends Mock implements HttpClientRequest {} + +class MockHttpResponse extends Mock implements HttpClientResponse {} void main() async { - const pfiDid = 'did:dht:74hg1efatndi8enx3e4z6c4u8ieh1xfkyay4ntg4dg1w6risu35y'; + const pfiDid = 'did:web:localhost%3A8892:ingress'; const pfiServiceEndpoint = 'http://localhost:8892/ingress/pfi'; - late MockClient mockHttpClient; + late MockClient client; + late MockHttpHeaders headers; + late MockHttpRequest request; + late MockHttpResponse response; await TestData.initializeDids(); group('TbdexHttpClient', () { setUp(() { - mockHttpClient = MockClient(); - TbdexHttpClient.client = mockHttpClient; + client = MockClient(); + headers = MockHttpHeaders(); + request = MockHttpRequest(); + response = MockHttpResponse(); + + TbdexHttpClient.client = client; }); test('can get exchange', () async { + when(() => request.headers).thenReturn(headers); + when(() => request.close()).thenAnswer((_) async => response); + + when(() => response.statusCode).thenReturn(200); + when(() => response.transform(utf8.decoder)) + .thenAnswer((_) => Stream.value(TestData.getExchangeResponse())); + when( - () => mockHttpClient.get( - Uri.parse('$pfiServiceEndpoint/exchanges/exchange_id'), - headers: any(named: 'headers'), - ), - ).thenAnswer( - (_) async => http.Response(TestData.getExchangeResponse(), 200), - ); + () => client + .getUrl(Uri.parse('$pfiServiceEndpoint/exchanges/exchange_id')), + ).thenAnswer((_) async => request); final exchange = await TbdexHttpClient.getExchange( TestData.aliceDid, @@ -39,22 +57,22 @@ void main() async { expect(exchange.length, 2); verify( - () => mockHttpClient.get( - Uri.parse('$pfiServiceEndpoint/exchanges/exchange_id'), - headers: any(named: 'headers'), - ), + () => client + .getUrl(Uri.parse('$pfiServiceEndpoint/exchanges/exchange_id')), ).called(1); }); test('can get exchanges', () async { + when(() => request.headers).thenReturn(headers); + when(() => request.close()).thenAnswer((_) async => response); + + when(() => response.statusCode).thenReturn(200); + when(() => response.transform(utf8.decoder)) + .thenAnswer((_) => Stream.value(TestData.getExchangesResponse())); + when( - () => mockHttpClient.get( - Uri.parse('$pfiServiceEndpoint/exchanges/'), - headers: any(named: 'headers'), - ), - ).thenAnswer( - (_) async => http.Response(TestData.getExchangesResponse(), 200), - ); + () => client.getUrl(Uri.parse('$pfiServiceEndpoint/exchanges/')), + ).thenAnswer((_) async => request); final exchanges = await TbdexHttpClient.getExchanges( TestData.aliceDid, @@ -64,58 +82,55 @@ void main() async { expect(exchanges.length, 1); verify( - () => mockHttpClient.get( - Uri.parse('$pfiServiceEndpoint/exchanges/'), - headers: any(named: 'headers'), - ), + () => client.getUrl(Uri.parse('$pfiServiceEndpoint/exchanges/')), ).called(1); }); test('can get offerings', () async { + when(() => request.close()).thenAnswer((_) async => response); + + when(() => response.statusCode).thenReturn(200); + when(() => response.transform(utf8.decoder)) + .thenAnswer((_) => Stream.value(TestData.getOfferingResponse())); + when( - () => mockHttpClient.get( - Uri.parse('$pfiServiceEndpoint/offerings/'), - headers: any(named: 'headers'), - ), - ).thenAnswer( - (_) async => http.Response(TestData.getOfferingResponse(), 200), - ); + () => client.getUrl(Uri.parse('$pfiServiceEndpoint/offerings/')), + ).thenAnswer((_) async => request); final offerings = await TbdexHttpClient.getOfferings(pfiDid); expect(offerings.length, 1); verify( - () => mockHttpClient.get( - Uri.parse('$pfiServiceEndpoint/offerings/'), - headers: any(named: 'headers'), - ), + () => client.getUrl(Uri.parse('$pfiServiceEndpoint/offerings/')), ).called(1); }); test('can create exchange', () async { final rfq = TestData.getRfq(to: pfiDid); await rfq.sign(TestData.aliceDid); - final request = - TestData.getCreateExchangeRequest(rfq, replyTo: 'reply_to'); + request + .write(TestData.getCreateExchangeRequest(rfq, replyTo: 'reply_to')); - when( - () => mockHttpClient.post( - Uri.parse('$pfiServiceEndpoint/exchanges'), - headers: any(named: 'headers'), - body: request, + when(() => request.headers).thenReturn(headers); + when(() => request.close()).thenAnswer((_) async => response); + + when(() => response.statusCode).thenReturn(201); + when(() => response.transform(utf8.decoder)).thenAnswer( + (_) => Stream.value( + '', ), - ).thenAnswer( - (_) async => http.Response('', 201), ); + when( + () => client.postUrl(Uri.parse('$pfiServiceEndpoint/exchanges')), + ).thenAnswer((_) async => request); + await TbdexHttpClient.createExchange(rfq, replyTo: 'reply_to'); verify( - () => mockHttpClient.post( + () => client.postUrl( Uri.parse('$pfiServiceEndpoint/exchanges'), - headers: any(named: 'headers'), - body: request, ), ).called(1); }); @@ -124,25 +139,27 @@ void main() async { final order = TestData.getOrder(to: pfiDid); final exchangeId = order.metadata.exchangeId; await order.sign(TestData.aliceDid); - final request = TestData.getSubmitOrderRequest(order); - when( - () => mockHttpClient.post( - Uri.parse('$pfiServiceEndpoint/exchanges/$exchangeId'), - headers: any(named: 'headers'), - body: request, - ), - ).thenAnswer( - (_) async => http.Response('', 201), + request.write(TestData.getSubmitOrderRequest(order)); + + when(() => request.headers).thenReturn(headers); + when(() => request.close()).thenAnswer((_) async => response); + + when(() => response.statusCode).thenReturn(201); + when(() => response.transform(utf8.decoder)).thenAnswer( + (_) => Stream.value(''), ); + when( + () => client + .postUrl(Uri.parse('$pfiServiceEndpoint/exchanges/$exchangeId')), + ).thenAnswer((_) async => request); + await TbdexHttpClient.submitOrder(order); verify( - () => mockHttpClient.post( + () => client.postUrl( Uri.parse('$pfiServiceEndpoint/exchanges/$exchangeId'), - headers: any(named: 'headers'), - body: request, ), ).called(1); }); @@ -151,25 +168,27 @@ void main() async { final close = TestData.getClose(to: pfiDid); final exchangeId = close.metadata.exchangeId; await close.sign(TestData.aliceDid); - final request = TestData.getSubmitCloseRequest(close); - when( - () => mockHttpClient.post( - Uri.parse('$pfiServiceEndpoint/exchanges/$exchangeId'), - headers: any(named: 'headers'), - body: request, - ), - ).thenAnswer( - (_) async => http.Response('', 201), + request.write(TestData.getSubmitCloseRequest(close)); + + when(() => request.headers).thenReturn(headers); + when(() => request.close()).thenAnswer((_) async => response); + + when(() => response.statusCode).thenReturn(201); + when(() => response.transform(utf8.decoder)).thenAnswer( + (_) => Stream.value(''), ); + when( + () => client + .postUrl(Uri.parse('$pfiServiceEndpoint/exchanges/$exchangeId')), + ).thenAnswer((_) async => request); + await TbdexHttpClient.submitClose(close); verify( - () => mockHttpClient.post( + () => client.postUrl( Uri.parse('$pfiServiceEndpoint/exchanges/$exchangeId'), - headers: any(named: 'headers'), - body: request, ), ).called(1); });