Feature/middlewares #9
| @ -0,0 +1,386 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| // ignore_for_file: public_member_api_docs, sort_constructors_first | ||||
| import 'dart:convert'; | ||||
| 
 | ||||
| import 'package:wyatt_http_client/src/authentication/refresh_token_client.dart'; | ||||
| import 'package:wyatt_http_client/src/rest_client.dart'; | ||||
| import 'package:wyatt_http_client/src/utils/protocols.dart'; | ||||
| 
 | ||||
| enum EmailVerificationAction { | ||||
|   signUp, | ||||
|   resetPassword, | ||||
|   changeEmail; | ||||
| 
 | ||||
|   String toSnakeCase() { | ||||
|     return name.splitMapJoin( | ||||
|       RegExp('[A-Z]'), | ||||
|       onMatch: (m) => '_${m[0]?.toLowerCase()}', | ||||
|       onNonMatch: (n) => n, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   factory EmailVerificationAction.fromString(String str) { | ||||
|     return EmailVerificationAction.values.firstWhere( | ||||
|       (EmailVerificationAction element) => element.toSnakeCase() == str, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class VerifyCode { | ||||
|   final String email; | ||||
|   final String verificationCode; | ||||
|   final EmailVerificationAction action; | ||||
|   VerifyCode({ | ||||
|     required this.email, | ||||
|     required this.verificationCode, | ||||
|     required this.action, | ||||
|   }); | ||||
| 
 | ||||
|   VerifyCode copyWith({ | ||||
|     String? email, | ||||
|     String? verificationCode, | ||||
|     EmailVerificationAction? action, | ||||
|   }) { | ||||
|     return VerifyCode( | ||||
|       email: email ?? this.email, | ||||
|       verificationCode: verificationCode ?? this.verificationCode, | ||||
|       action: action ?? this.action, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toMap() { | ||||
|     return <String, dynamic>{ | ||||
|       'email': email, | ||||
|       'verification_code': verificationCode, | ||||
|       'action': action.toSnakeCase(), | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   factory VerifyCode.fromMap(Map<String, dynamic> map) { | ||||
|     return VerifyCode( | ||||
|       email: map['email'] as String, | ||||
|       verificationCode: map['verification_code'] as String, | ||||
|       action: EmailVerificationAction.fromString(map['action'] as String), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   String toJson() => json.encode(toMap()); | ||||
| 
 | ||||
|   factory VerifyCode.fromJson(String source) => | ||||
|       VerifyCode.fromMap(json.decode(source) as Map<String, dynamic>); | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => | ||||
|       'VerifyCode(email: $email, verificationCode: $verificationCode, action: $action)'; | ||||
| } | ||||
| 
 | ||||
| class Account { | ||||
|   final String email; | ||||
|   final String? sessionId; | ||||
|   Account({ | ||||
|     required this.email, | ||||
|     this.sessionId, | ||||
|   }); | ||||
| 
 | ||||
|   Account copyWith({ | ||||
|     String? email, | ||||
|     String? sessionId, | ||||
|   }) { | ||||
|     return Account( | ||||
|       email: email ?? this.email, | ||||
|       sessionId: sessionId ?? this.sessionId, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toMap() { | ||||
|     return <String, dynamic>{ | ||||
|       'email': email, | ||||
|       'session_id': sessionId, | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   factory Account.fromMap(Map<String, dynamic> map) { | ||||
|     return Account( | ||||
|       email: map['email'] as String, | ||||
|       sessionId: map['session_id'] != null ? map['session_id'] as String : null, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   String toJson() => json.encode(toMap()); | ||||
| 
 | ||||
|   factory Account.fromJson(String source) => | ||||
|       Account.fromMap(json.decode(source) as Map<String, dynamic>); | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => 'Account(email: $email, sessionId: $sessionId)'; | ||||
| } | ||||
| 
 | ||||
| class SignUp { | ||||
|   final String sessionId; | ||||
|   final String password; | ||||
|   SignUp({ | ||||
|     required this.sessionId, | ||||
|     required this.password, | ||||
|   }); | ||||
| 
 | ||||
|   SignUp copyWith({ | ||||
|     String? sessionId, | ||||
|     String? password, | ||||
|   }) { | ||||
|     return SignUp( | ||||
|       sessionId: sessionId ?? this.sessionId, | ||||
|       password: password ?? this.password, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toMap() { | ||||
|     return <String, dynamic>{ | ||||
|       'session_id': sessionId, | ||||
|       'password': password, | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   factory SignUp.fromMap(Map<String, dynamic> map) { | ||||
|     return SignUp( | ||||
|       sessionId: map['session_id'] as String, | ||||
|       password: map['password'] as String, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   String toJson() => json.encode(toMap()); | ||||
| 
 | ||||
|   factory SignUp.fromJson(String source) => | ||||
|       SignUp.fromMap(json.decode(source) as Map<String, dynamic>); | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => 'SignUp(sessionId: $sessionId, password: $password)'; | ||||
| } | ||||
| 
 | ||||
| class TokenSuccess { | ||||
|   final String accessToken; | ||||
|   final String refreshToken; | ||||
|   final Account account; | ||||
|   TokenSuccess({ | ||||
|     required this.accessToken, | ||||
|     required this.refreshToken, | ||||
|     required this.account, | ||||
|   }); | ||||
| 
 | ||||
|   TokenSuccess copyWith({ | ||||
|     String? accessToken, | ||||
|     String? refreshToken, | ||||
|     Account? account, | ||||
|   }) { | ||||
|     return TokenSuccess( | ||||
|       accessToken: accessToken ?? this.accessToken, | ||||
|       refreshToken: refreshToken ?? this.refreshToken, | ||||
|       account: account ?? this.account, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toMap() { | ||||
|     return <String, dynamic>{ | ||||
|       'access_token': accessToken, | ||||
|       'refresh_token': refreshToken, | ||||
|       'account': account.toMap(), | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   factory TokenSuccess.fromMap(Map<String, dynamic> map) { | ||||
|     return TokenSuccess( | ||||
|       accessToken: map['access_token'] as String, | ||||
|       refreshToken: map['refresh_token'] as String, | ||||
|       account: Account.fromMap(map['account'] as Map<String, dynamic>), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   String toJson() => json.encode(toMap()); | ||||
| 
 | ||||
|   factory TokenSuccess.fromJson(String source) => | ||||
|       TokenSuccess.fromMap(json.decode(source) as Map<String, dynamic>); | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => | ||||
|       'TokenSuccess(accessToken: $accessToken, refreshToken: $refreshToken, account: $account)'; | ||||
| } | ||||
| 
 | ||||
| class Login { | ||||
|   final String email; | ||||
|   final String password; | ||||
|   Login({ | ||||
|     required this.email, | ||||
|     required this.password, | ||||
|   }); | ||||
| 
 | ||||
|   Login copyWith({ | ||||
|     String? email, | ||||
|     String? password, | ||||
|   }) { | ||||
|     return Login( | ||||
|       email: email ?? this.email, | ||||
|       password: password ?? this.password, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   Map<String, dynamic> toMap() { | ||||
|     return <String, dynamic>{ | ||||
|       'email': email, | ||||
|       'password': password, | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   factory Login.fromMap(Map<String, dynamic> map) { | ||||
|     return Login( | ||||
|       email: map['email'] as String, | ||||
|       password: map['password'] as String, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   String toJson() => json.encode(toMap()); | ||||
| 
 | ||||
|   factory Login.fromJson(String source) => | ||||
|       Login.fromMap(json.decode(source) as Map<String, dynamic>); | ||||
| 
 | ||||
|   @override | ||||
|   String toString() => 'Login(email: $email, password: $password)'; | ||||
| } | ||||
| 
 | ||||
| class FastAPI { | ||||
|   final String baseUrl; | ||||
|   final RefreshTokenClient client; | ||||
|   final int apiVersion; | ||||
| 
 | ||||
|   FastAPI({ | ||||
|     this.baseUrl = 'localhost:80', | ||||
|     RefreshTokenClient? client, | ||||
|     this.apiVersion = 1, | ||||
|   }) : client = client ?? | ||||
|             RefreshTokenClient( | ||||
|               authorizationEndpoint: '', | ||||
|               tokenEndpoint: '', | ||||
|               accessTokenParser: (body) => body['access_token']! as String, | ||||
|               refreshTokenParser: (body) => body['refresh_token']! as String, | ||||
|               inner: RestClient( | ||||
|                 protocol: Protocols.http, | ||||
|                 authority: baseUrl, | ||||
|               ), | ||||
|             ); | ||||
| 
 | ||||
|   String get apiPath => '/api/v$apiVersion'; | ||||
| 
 | ||||
|   Future<void> sendSignUpCode(String email) async { | ||||
|     final r = await client.post( | ||||
|       Uri.parse('$apiPath/auth/send-sign-up-code'), | ||||
|       body: <String, String>{ | ||||
|         'email': email, | ||||
|       }, | ||||
|     ); | ||||
|     if (r.statusCode != 201) { | ||||
|       throw Exception('Invalid reponse: ${r.statusCode}'); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   Future<Account> verifyCode(VerifyCode verifyCode) async { | ||||
|     final r = await client.post( | ||||
|       Uri.parse('$apiPath/auth/verify-code'), | ||||
|       body: verifyCode.toMap(), | ||||
|     ); | ||||
|     if (r.statusCode != 202) { | ||||
|       throw Exception('Invalid reponse: ${r.statusCode}'); | ||||
|     } else { | ||||
|       return Account.fromMap( | ||||
|         (jsonDecode(r.body) as Map<String, dynamic>)['account'] | ||||
|             as Map<String, dynamic>, | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   Future<Account> signUp(SignUp signUp) async { | ||||
|     final r = await client.post( | ||||
|       Uri.parse('$apiPath/auth/sign-up'), | ||||
|       body: signUp.toMap(), | ||||
|     ); | ||||
|     if (r.statusCode != 201) { | ||||
|       throw Exception('Invalid reponse: ${r.statusCode}'); | ||||
|     } else { | ||||
|       return Account.fromJson(r.body); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   Future<TokenSuccess> signInWithPassword(Login login) async { | ||||
|     final r = await client.authorize(login.toMap()); | ||||
|     return TokenSuccess.fromJson(r.body); | ||||
|   } | ||||
| 
 | ||||
|   Future<TokenSuccess> refresh() async { | ||||
|     final r = await client.refresh(); | ||||
|     return TokenSuccess.fromJson(r?.body ?? ''); | ||||
|   } | ||||
| 
 | ||||
|   Future<List<Account>> getAccountList() async { | ||||
|     final r = await client.get( | ||||
|       Uri.parse('$apiPath/account'), | ||||
|     ); | ||||
|     if (r.statusCode != 200) { | ||||
|       throw Exception('Invalid reponse: ${r.statusCode}'); | ||||
|     } else { | ||||
|       final list = (jsonDecode(r.body) as Map<String, dynamic>)['founds'] | ||||
|           as List<Map<String, dynamic>>; | ||||
|       final result = <Account>[]; | ||||
|       for (final element in list) { | ||||
|         result.add(Account.fromMap(element)); | ||||
|       } | ||||
|       return result; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void main(List<String> args) async { | ||||
|   final api = FastAPI( | ||||
|     client: RefreshTokenClient( | ||||
|       authorizationEndpoint: '/api/v1/auth/sign-in-with-password', | ||||
|       tokenEndpoint: '/api/v1/auth/refresh', | ||||
|       accessTokenParser: (body) => body['access_token']! as String, | ||||
|       refreshTokenParser: (body) => body['refresh_token']! as String, | ||||
|       inner: RestClient( | ||||
|         protocol: Protocols.http, | ||||
|         authority: 'localhost:80', | ||||
|       ), | ||||
|     ), | ||||
|   ); | ||||
| 
 | ||||
|   // await api.sendSignUpCode('git@pcl.ovh'); | ||||
|   // final verifiedAccount = await api.verifyCode( | ||||
|   //   VerifyCode( | ||||
|   //     email: 'git@pcl.ovh', | ||||
|   //     verificationCode: '000000000', | ||||
|   //     action: EmailVerificationAction.signUp, | ||||
|   //   ), | ||||
|   // ); | ||||
|   // print(verifiedAccount); | ||||
|   // final registeredAccount = await api.signUp( | ||||
|   //   SignUp(sessionId: verifiedAccount.sessionId ?? '', password: 'password'), | ||||
|   // ); | ||||
|   // print(registeredAccount); | ||||
|   final signedInAccount = await api.signInWithPassword( | ||||
|     Login(email: 'git@pcl.ovh', password: 'password'), | ||||
|   ); | ||||
|   // print(signedInAccount); | ||||
|   final accountList = await api.getAccountList(); | ||||
|   print(accountList); | ||||
| } | ||||
							
								
								
									
										41
									
								
								packages/wyatt_http_client/example/http_client_test.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								packages/wyatt_http_client/example/http_client_test.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| 
 | ||||
| Future<void> main(List<String> args) async { | ||||
|   // final client = Oauth2Client( | ||||
|   //   accessToken: 'test-token', | ||||
|   //   inner: RestClient(protocol: Protocols.http, authority: 'localhost:80'), | ||||
|   // ); | ||||
|   // final client = RestClient( | ||||
|   //   protocol: Protocols.http, | ||||
|   //   authority: 'localhost:80', | ||||
|   //   inner: Oauth2Client( | ||||
|   //     authorizationEndpoint: '/api/v1/account/test', | ||||
|   //     tokenEndpoint: '/api/v1/account/test', | ||||
|   //     accessToken: 'test-token', | ||||
|   //     refreshToken: 'refresh-token', | ||||
|   //   ), | ||||
|   // ); | ||||
|   // final client = RestClient(protocol: Protocols.http, authority: 'localhost:80'); | ||||
|   // final client =AwesomeRestClient(protocol: Protocols.http, authority: 'localhost:80'); | ||||
|   // var r = await client.post( | ||||
|   //   Uri.parse('/api/v1/account/test'), | ||||
|   //   body: <String, String>{ | ||||
|   //     'email': 'test@test.fr', | ||||
|   //   }, | ||||
|   // ); | ||||
| } | ||||
| @ -0,0 +1,87 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'dart:convert'; | ||||
| import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| import 'package:wyatt_http_client/src/implemented_base_client.dart'; | ||||
| 
 | ||||
| abstract class AuthenticatedClient implements ImplementedBaseClient { | ||||
|   final Client _inner; | ||||
| 
 | ||||
|   AuthenticatedClient({ | ||||
|     Client? inner, | ||||
|   }) : _inner = inner ?? Client(); | ||||
| 
 | ||||
|   @override | ||||
|   void close() => _inner.close(); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> head(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.head(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> get(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.get(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> post( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.post(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> put( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.put(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> patch( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.patch(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> delete( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.delete(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<String> read(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.read(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Uint8List> readBytes(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.readBytes(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) => _inner.send(request); | ||||
| } | ||||
| @ -14,8 +14,161 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'dart:convert'; | ||||
| import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| import 'package:wyatt_http_client/src/mixins/body_transformer.dart'; | ||||
| import 'package:wyatt_http_client/src/mixins/headers_transformer.dart'; | ||||
| import 'package:wyatt_http_client/src/rest_client.dart'; | ||||
| import 'package:wyatt_http_client/src/utils/protocols.dart'; | ||||
| import 'package:wyatt_http_client/src/utils/utils.dart'; | ||||
| 
 | ||||
| class AwesomeClient extends BaseClient { | ||||
|   final Client _inner; | ||||
| 
 | ||||
|   AwesomeClient({ | ||||
|     Client? inner, | ||||
|   }) : _inner = inner ?? Client(); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) { | ||||
|     return _inner.send(request); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class AwesomeRestClient extends AwesomeClient | ||||
|     with HeadersTransformer, BodyTransformer { | ||||
|   final Protocols protocol; | ||||
|   final String? authority; | ||||
| 
 | ||||
|   AwesomeRestClient({ | ||||
|     this.protocol = Protocols.https, | ||||
|     this.authority = '', | ||||
|     super.inner, | ||||
|   }); | ||||
| 
 | ||||
|   @override | ||||
|   Object? bodyMutator(Object? body) { | ||||
|     print('bodyMutator: Json encoding'); | ||||
|     return jsonEncode(body); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Map<String, String>? headersMutator( | ||||
|     Object? body, | ||||
|     Map<String, String>? headers, | ||||
|   ) { | ||||
|     print('headerMutator: Json encoding'); | ||||
|     final mutation = { | ||||
|       'content-type': 'application/json; charset=utf-8', | ||||
|     }; | ||||
|     if (headers != null) { | ||||
|       headers.addAll(mutation); | ||||
|       return headers; | ||||
|     } else { | ||||
|       return mutation; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   BaseRequest requestMutator(BaseRequest request) { | ||||
|     print('requestMutator: scheme + authority'); | ||||
|     final Uri uri = Uri.parse('${protocol.scheme}$authority${request.url}'); | ||||
|     return Utils.copyRequestWith(request, url: uri); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class AwesomeUrlClient extends AuthenticatedClient { | ||||
|   AwesomeUrlClient(super.inner); | ||||
| } | ||||
| 
 | ||||
| class AwesomeOauth2Client extends AuthenticatedClient with HeadersTransformer { | ||||
|   AwesomeOauth2Client(super.inner); | ||||
| 
 | ||||
|   @override | ||||
|   Map<String, String>? headersMutator( | ||||
|     Object? body, | ||||
|     Map<String, String>? headers, | ||||
|   ) { | ||||
|     print('headersMutator: Token manager'); | ||||
|     final mutation = { | ||||
|       'authorization': 'Bearer TOKEN', | ||||
|     }; | ||||
|     if (headers != null) { | ||||
|       headers.addAll(mutation); | ||||
|       return headers; | ||||
|     } else { | ||||
|       return mutation; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| abstract class AuthenticatedClient implements Client { | ||||
|   final Client _inner; | ||||
| 
 | ||||
|   Client get inner => _inner; | ||||
| 
 | ||||
|   AuthenticatedClient(BaseClient? inner) : _inner = inner ?? RestClient(); | ||||
| 
 | ||||
|   @override | ||||
|   void close() => _inner.close(); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> head(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.head(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> get(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.get(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> post( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.post(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> put( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.put(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> patch( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.patch(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> delete( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.delete(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<String> read(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.read(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Uint8List> readBytes(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.readBytes(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) => _inner.send(request); | ||||
| } | ||||
| 
 | ||||
| abstract class AuthenticationClient extends BaseClient { | ||||
|   final BaseClient _inner; | ||||
| @ -24,6 +177,50 @@ abstract class AuthenticationClient extends BaseClient { | ||||
| 
 | ||||
|   AuthenticationClient(BaseClient? inner) : _inner = inner ?? RestClient(); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> head(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.head(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> get(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.get(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> post( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.post(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> put( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.put(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> patch( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.patch(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> delete( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.delete(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) { | ||||
|     return _inner.send(request); | ||||
|  | ||||
| @ -31,6 +31,7 @@ abstract class HeaderAuthenticationClient extends AuthenticationClient { | ||||
|     final newHeader = modifyHeader(Map.from(request.headers), request); | ||||
|     request.headers.clear(); | ||||
|     request.headers.addAll(newHeader); | ||||
|     print(newHeader); | ||||
|     return super.send(request); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -14,6 +14,7 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| import 'package:wyatt_http_client/src/authentication/interfaces/header_authentication_client.dart'; | ||||
| 
 | ||||
| typedef TokenParser = String Function(Map<String, dynamic>); | ||||
| @ -21,14 +22,14 @@ typedef TokenParser = String Function(Map<String, dynamic>); | ||||
| abstract class Oauth2Client extends HeaderAuthenticationClient { | ||||
|   Oauth2Client(super.inner); | ||||
| 
 | ||||
|   Future<void> refresh() { | ||||
|   Future<Response?> refresh() { | ||||
|     return Future.value(); | ||||
|   } | ||||
| 
 | ||||
|   Future<void> authorize( | ||||
|   Future<Response> authorize( | ||||
|     Map<String, dynamic> body, { | ||||
|     Map<String, String>? headers, | ||||
|   }) { | ||||
|     return Future.value(); | ||||
|     return Future<Response>.value(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -23,6 +23,78 @@ import 'package:wyatt_http_client/src/utils/header_keys.dart'; | ||||
| import 'package:wyatt_http_client/src/utils/http_status.dart'; | ||||
| import 'package:wyatt_http_client/src/utils/utils.dart'; | ||||
| 
 | ||||
| // class Oauth2Client extends ImplementedBaseClient with RequestTransformer { | ||||
| //   final String authorizationEndpoint; | ||||
| //   final String tokenEndpoint; | ||||
| //   String? accessToken; | ||||
| //   String? refreshToken; | ||||
| //   String? tokenToUse; | ||||
| 
 | ||||
| //   Oauth2Client({ | ||||
| //     required this.authorizationEndpoint, | ||||
| //     required this.tokenEndpoint, | ||||
| //     this.accessToken, | ||||
| //     this.refreshToken, | ||||
| //     super.inner, | ||||
| //   }) : tokenToUse = accessToken; | ||||
| 
 | ||||
| //   @override | ||||
| //   BaseRequest requestMutator(BaseRequest request) { | ||||
| //     print('Oauth2Client::requestMutator -> add authorization: $accessToken'); | ||||
| //     final headers = request.headers; | ||||
| //     final mutation = { | ||||
| //       'Authorization': 'Bearer $tokenToUse', | ||||
| //     }; | ||||
| //     if (tokenToUse?.isNotEmpty ?? false) { | ||||
| //       headers.addAll(mutation); | ||||
| //       return Utils.copyRequestWith(request, headers: headers); | ||||
| //     } | ||||
| //     return request; | ||||
| //   } | ||||
| 
 | ||||
| //   Future<Response?> refresh() async { | ||||
| //     if (refreshToken?.isNotEmpty ?? false) { | ||||
| //       tokenToUse = refreshToken; | ||||
| 
 | ||||
| //       final response = await get( | ||||
| //         Uri.parse(tokenEndpoint), | ||||
| //       ); | ||||
| 
 | ||||
| //       if (response.statusCode == HttpStatus.ok) { | ||||
| //         // final body = json.decode(response.body) as Map<String, dynamic>; | ||||
| //         // accessToken = accessTokenParser(body); | ||||
| //         print('Oauth2Client::refresh -> ok'); | ||||
| //       } | ||||
| //       return response; | ||||
| //     } | ||||
| //     return null; | ||||
| //   } | ||||
| 
 | ||||
| // @override | ||||
| // Map<String, String>? headersMutator( | ||||
| //   Object? body, | ||||
| //   Map<String, String>? headers, | ||||
| // ) { | ||||
| //   print( | ||||
| //     'Oauth2Client::headersMutator -> add authorization: $accessToken', | ||||
| //   ); | ||||
| //   final mutation = { | ||||
| //     'Authorization': 'Bearer $accessToken', | ||||
| //   }; | ||||
| //   if (accessToken.isNotEmpty) { | ||||
| //     if (headers != null) { | ||||
| //       headers.addAll(mutation); | ||||
| //       return headers; | ||||
| //     } else { | ||||
| //       return mutation; | ||||
| //     } | ||||
| //   } else { | ||||
| //     return headers; | ||||
| //   } | ||||
| // } | ||||
| 
 | ||||
| // } | ||||
| 
 | ||||
| class RefreshTokenClient extends Oauth2Client { | ||||
|   final String authorizationEndpoint; | ||||
|   final String tokenEndpoint; | ||||
| @ -50,6 +122,8 @@ class RefreshTokenClient extends Oauth2Client { | ||||
|     Map<String, String> header, [ | ||||
|     BaseRequest? request, | ||||
|   ]) { | ||||
|     print('accessToken $accessToken'); | ||||
|     print('request $request'); | ||||
|     if (accessToken != null && request != null) { | ||||
|       header[authenticationHeader] = '$authenticationMethod $accessToken'; | ||||
|       return header; | ||||
| @ -58,13 +132,13 @@ class RefreshTokenClient extends Oauth2Client { | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> authorize( | ||||
|   Future<Response> authorize( | ||||
|     Map<String, dynamic> body, { | ||||
|     Map<String, String>? headers, | ||||
|   }) async { | ||||
|     final response = await inner.post( | ||||
|       Uri.parse(authorizationEndpoint), | ||||
|       body: jsonEncode(body), | ||||
|       body: body, | ||||
|       headers: headers, | ||||
|     ); | ||||
| 
 | ||||
| @ -80,10 +154,11 @@ class RefreshTokenClient extends Oauth2Client { | ||||
|         this.refreshToken = refreshToken; | ||||
|       } | ||||
|     } | ||||
|     return response; | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<void> refresh() async { | ||||
|   Future<Response?> refresh() async { | ||||
|     if (refreshToken != null) { | ||||
|       final Map<String, String> header = { | ||||
|         authenticationHeader: '$authenticationHeader $refreshToken', | ||||
| @ -98,11 +173,16 @@ class RefreshTokenClient extends Oauth2Client { | ||||
|         final body = json.decode(response.body) as Map<String, dynamic>; | ||||
|         accessToken = accessTokenParser(body); | ||||
|       } | ||||
|       return response; | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) async { | ||||
|     final newHeader = modifyHeader(Map.from(request.headers), request); | ||||
|     request.headers.clear(); | ||||
|     request.headers.addAll(newHeader); | ||||
|     final response = await super.send(request); | ||||
| 
 | ||||
|     if (response.statusCode == HttpStatus.unauthorized) { | ||||
|  | ||||
| @ -0,0 +1,31 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| 
 | ||||
| class ImplementedBaseClient extends BaseClient { | ||||
|   final Client inner; | ||||
| 
 | ||||
|   ImplementedBaseClient({ | ||||
|     Client? inner, | ||||
|   }) : inner = inner ?? Client(); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) { | ||||
|     return inner.send(request); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										86
									
								
								packages/wyatt_http_client/lib/src/implemented_client.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								packages/wyatt_http_client/lib/src/implemented_client.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,86 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'dart:convert'; | ||||
| import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| 
 | ||||
| abstract class ImplementedClient extends BaseClient { | ||||
|   final Client _inner; | ||||
| 
 | ||||
|   ImplementedClient({ | ||||
|     Client? inner, | ||||
|   }) : _inner = inner ?? Client(); | ||||
| 
 | ||||
|   @override | ||||
|   void close() => _inner.close(); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> head(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.head(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> get(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.get(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> post( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.post(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> put( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.put(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> patch( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.patch(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> delete( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) => | ||||
|       _inner.delete(url, headers: headers, body: body, encoding: encoding); | ||||
| 
 | ||||
|   @override | ||||
|   Future<String> read(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.read(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Uint8List> readBytes(Uri url, {Map<String, String>? headers}) => | ||||
|       _inner.readBytes(url, headers: headers); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) => _inner.send(request); | ||||
| } | ||||
| @ -0,0 +1,83 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'dart:convert'; | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| 
 | ||||
| mixin BodyTransformer on Client { | ||||
|   Object? bodyMutator(Object? body); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> post( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) { | ||||
|     return super.post( | ||||
|       url, | ||||
|       headers: headers, | ||||
|       body: bodyMutator(body), | ||||
|       encoding: encoding, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> put( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) { | ||||
|     return super.put( | ||||
|       url, | ||||
|       headers: headers, | ||||
|       body: bodyMutator(body), | ||||
|       encoding: encoding, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> patch( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) { | ||||
|     return super.patch( | ||||
|       url, | ||||
|       headers: headers, | ||||
|       body: bodyMutator(body), | ||||
|       encoding: encoding, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> delete( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) { | ||||
|     return super.delete( | ||||
|       url, | ||||
|       headers: headers, | ||||
|       body: bodyMutator(body), | ||||
|       encoding: encoding, | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,131 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'dart:convert'; | ||||
| import 'dart:typed_data'; | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| 
 | ||||
| mixin HeadersTransformer on Client { | ||||
|   Map<String, String>? headersMutator( | ||||
|     Object? body, | ||||
|     Map<String, String>? headers, | ||||
|   ); | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> head( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|   }) { | ||||
|     return super.head( | ||||
|       url, | ||||
|       headers: headersMutator(null, headers), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> get( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|   }) { | ||||
|     return super.get( | ||||
|       url, | ||||
|       headers: headersMutator(null, headers), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> post( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) { | ||||
|     return super.post( | ||||
|       url, | ||||
|       headers: headersMutator(body, headers), | ||||
|       body: body, | ||||
|       encoding: encoding, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> put( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) { | ||||
|     return super.put( | ||||
|       url, | ||||
|       headers: headersMutator(body, headers), | ||||
|       body: body, | ||||
|       encoding: encoding, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> patch( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) { | ||||
|     return super.patch( | ||||
|       url, | ||||
|       headers: headersMutator(body, headers), | ||||
|       body: body, | ||||
|       encoding: encoding, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Response> delete( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|     Object? body, | ||||
|     Encoding? encoding, | ||||
|   }) { | ||||
|     return super.delete( | ||||
|       url, | ||||
|       headers: headersMutator(body, headers), | ||||
|       body: body, | ||||
|       encoding: encoding, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<String> read( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|   }) { | ||||
|     return super.read( | ||||
|       url, | ||||
|       headers: headersMutator(null, headers), | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Future<Uint8List> readBytes( | ||||
|     Uri url, { | ||||
|     Map<String, String>? headers, | ||||
|   }) { | ||||
|     return super.readBytes( | ||||
|       url, | ||||
|       headers: headersMutator(null, headers), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,33 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| //  | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| //  | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| //  | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| import 'package:wyatt_http_client/src/implemented_base_client.dart'; | ||||
| 
 | ||||
| mixin Oauth2Transformer on ImplementedBaseClient { | ||||
|   late final String authorizationEndpoint; | ||||
|   late final String tokenEndpoint; | ||||
|   String? accessToken; | ||||
|   String? refreshToken; | ||||
| 
 | ||||
|   BaseRequest requestAuthenticator(BaseRequest request); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) { | ||||
|     final req = requestAuthenticator(request); | ||||
|     return super.send(req); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| // Copyright (C) 2022 WYATT GROUP | ||||
| // Please see the AUTHORS file for details. | ||||
| // | ||||
| // This program is free software: you can redistribute it and/or modify | ||||
| // it under the terms of the GNU General Public License as published by | ||||
| // the Free Software Foundation, either version 3 of the License, or | ||||
| // any later version. | ||||
| // | ||||
| // This program is distributed in the hope that it will be useful, | ||||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| // GNU General Public License for more details. | ||||
| // | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| import 'package:wyatt_http_client/src/implemented_base_client.dart'; | ||||
| 
 | ||||
| mixin RequestTransformer on ImplementedBaseClient { | ||||
|   BaseRequest requestMutator(BaseRequest request); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) { | ||||
|     return super.send(requestMutator(request)); | ||||
|   } | ||||
| } | ||||
| @ -14,25 +14,177 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| import 'dart:convert'; | ||||
| 
 | ||||
| import 'package:http/http.dart'; | ||||
| import 'package:wyatt_http_client/src/implemented_base_client.dart'; | ||||
| import 'package:wyatt_http_client/src/mixins/body_transformer.dart'; | ||||
| import 'package:wyatt_http_client/src/mixins/headers_transformer.dart'; | ||||
| import 'package:wyatt_http_client/src/mixins/request_transformer.dart'; | ||||
| import 'package:wyatt_http_client/src/utils/protocols.dart'; | ||||
| import 'package:wyatt_http_client/src/utils/utils.dart'; | ||||
| 
 | ||||
| class RestClient extends BaseClient { | ||||
| class RestClient extends ImplementedBaseClient | ||||
|     with BodyTransformer, HeadersTransformer, RequestTransformer { | ||||
|   final Protocols protocol; | ||||
|   final String? authority; | ||||
| 
 | ||||
|   final Client _inner; | ||||
| 
 | ||||
|   RestClient({ | ||||
|     this.protocol = Protocols.https, | ||||
|     this.authority = '', | ||||
|     Client? inner, | ||||
|   }) : _inner = inner ?? Client(); | ||||
|     super.inner, | ||||
|   }); | ||||
| 
 | ||||
|   @override | ||||
|   Future<StreamedResponse> send(BaseRequest request) { | ||||
|   Object? bodyMutator(Object? body) { | ||||
|     print( | ||||
|       'RestClient::bodyMutator -> encode in json if body is Map: ${body is Map}', | ||||
|     ); | ||||
|     if (body is Map) { | ||||
|       return jsonEncode(body); | ||||
|     } | ||||
|     return body; | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   Map<String, String>? headersMutator( | ||||
|     Object? body, | ||||
|     Map<String, String>? headers, | ||||
|   ) { | ||||
|     print( | ||||
|       'RestClient::headersMutator -> add json content-type if body is Map: ${body is Map}', | ||||
|     ); | ||||
|     final mutation = { | ||||
|       'content-type': 'application/json; charset=utf-8', | ||||
|     }; | ||||
|     if (body is Map) { | ||||
|       if (headers != null) { | ||||
|         headers.addAll(mutation); | ||||
|         return headers; | ||||
|       } else { | ||||
|         return mutation; | ||||
|       } | ||||
|     } | ||||
|     return headers; | ||||
|   } | ||||
| 
 | ||||
|   @override | ||||
|   BaseRequest requestMutator(BaseRequest request) { | ||||
|     print( | ||||
|       'RestClient::requestMutator -> add prefix path: ${protocol.scheme}$authority', | ||||
|     ); | ||||
|     final Uri uri = Uri.parse('${protocol.scheme}$authority${request.url}'); | ||||
|     return _inner.send(Utils.copyRequestWith(request, url: uri)); | ||||
|     return Utils.copyRequestWith(request, url: uri); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // class RestClient extends BaseClient { | ||||
| //   final Protocols protocol; | ||||
| //   final String? authority; | ||||
| 
 | ||||
| //   final Client _inner; | ||||
| 
 | ||||
| //   RestClient({ | ||||
| //     this.protocol = Protocols.https, | ||||
| //     this.authority = '', | ||||
| //     Client? inner, | ||||
| //   }) : _inner = inner ?? Client(); | ||||
| 
 | ||||
| //   String? forceJson(Object? body) { | ||||
| //     String? b; | ||||
| //     if (body != null && body is Map) { | ||||
| //       b = jsonEncode(body); | ||||
| //     } | ||||
| //     return b; | ||||
| //   } | ||||
| 
 | ||||
| //   Map<String, String>? forceJsonHeader( | ||||
| //       Object? body, Map<String, String>? headers,) { | ||||
| //     final Map<String, String> h = headers ?? {}; | ||||
| //     if (body != null && body is Map) { | ||||
| //       h['Content-Type'] = 'application/json'; | ||||
| //     } | ||||
| //     return h; | ||||
| //   } | ||||
| 
 | ||||
| //   // @override | ||||
| //   // Future<Response> post( | ||||
| //   //   Uri url, { | ||||
| //   //   Map<String, String>? headers, | ||||
| //   //   Object? body, | ||||
| //   //   Encoding? encoding, | ||||
| //   // }) { | ||||
| //   //   final b = forceJson(body) ?? body; | ||||
| //   //   final h = forceJsonHeader(body, headers) ?? headers; | ||||
| //   //   print(b); | ||||
| //   //   print(h); | ||||
| //   //   return super.post( | ||||
| //   //     url, | ||||
| //   //     headers: h, | ||||
| //   //     body: b, | ||||
| //   //     encoding: encoding, | ||||
| //   //   ); | ||||
| //   // } | ||||
| 
 | ||||
| //   @override | ||||
| //   Future<Response> put( | ||||
| //     Uri url, { | ||||
| //     Map<String, String>? headers, | ||||
| //     Object? body, | ||||
| //     Encoding? encoding, | ||||
| //   }) { | ||||
| //     final b = forceJson(body) ?? body; | ||||
| //     final h = forceJsonHeader(body, headers) ?? headers; | ||||
| //     return super.put( | ||||
| //       url, | ||||
| //       headers: h, | ||||
| //       body: b, | ||||
| //       encoding: encoding, | ||||
| //     ); | ||||
| //   } | ||||
| 
 | ||||
| //   @override | ||||
| //   Future<Response> patch( | ||||
| //     Uri url, { | ||||
| //     Map<String, String>? headers, | ||||
| //     Object? body, | ||||
| //     Encoding? encoding, | ||||
| //   }) { | ||||
| //     final b = forceJson(body) ?? body; | ||||
| //     final h = forceJsonHeader(body, headers) ?? headers; | ||||
| //     return super.patch( | ||||
| //       url, | ||||
| //       headers: h, | ||||
| //       body: b, | ||||
| //       encoding: encoding, | ||||
| //     ); | ||||
| //   } | ||||
| 
 | ||||
| //   @override | ||||
| //   Future<Response> delete( | ||||
| //     Uri url, { | ||||
| //     Map<String, String>? headers, | ||||
| //     Object? body, | ||||
| //     Encoding? encoding, | ||||
| //   }) { | ||||
| //     final b = forceJson(body) ?? body; | ||||
| //     final h = forceJsonHeader(body, headers) ?? headers; | ||||
| //     return super.delete( | ||||
| //       url, | ||||
| //       headers: h, | ||||
| //       body: b, | ||||
| //       encoding: encoding, | ||||
| //     ); | ||||
| //   } | ||||
| 
 | ||||
| //   @override | ||||
| //   Future<StreamedResponse> send(BaseRequest request) { | ||||
| //     final Uri uri = Uri.parse('${protocol.scheme}$authority${request.url}'); | ||||
| //     return _inner.send( | ||||
| //       Utils.copyRequestWith( | ||||
| //         request, | ||||
| //         url: uri, | ||||
| //       ), | ||||
| //     ); | ||||
| //   } | ||||
| // } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user