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
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// 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: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/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 {
|
abstract class AuthenticationClient extends BaseClient {
|
||||||
final BaseClient _inner;
|
final BaseClient _inner;
|
||||||
@ -24,6 +177,50 @@ abstract class AuthenticationClient extends BaseClient {
|
|||||||
|
|
||||||
AuthenticationClient(BaseClient? inner) : _inner = inner ?? RestClient();
|
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
|
@override
|
||||||
Future<StreamedResponse> send(BaseRequest request) {
|
Future<StreamedResponse> send(BaseRequest request) {
|
||||||
return _inner.send(request);
|
return _inner.send(request);
|
||||||
|
@ -31,6 +31,7 @@ abstract class HeaderAuthenticationClient extends AuthenticationClient {
|
|||||||
final newHeader = modifyHeader(Map.from(request.headers), request);
|
final newHeader = modifyHeader(Map.from(request.headers), request);
|
||||||
request.headers.clear();
|
request.headers.clear();
|
||||||
request.headers.addAll(newHeader);
|
request.headers.addAll(newHeader);
|
||||||
|
print(newHeader);
|
||||||
return super.send(request);
|
return super.send(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// 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';
|
import 'package:wyatt_http_client/src/authentication/interfaces/header_authentication_client.dart';
|
||||||
|
|
||||||
typedef TokenParser = String Function(Map<String, dynamic>);
|
typedef TokenParser = String Function(Map<String, dynamic>);
|
||||||
@ -21,14 +22,14 @@ typedef TokenParser = String Function(Map<String, dynamic>);
|
|||||||
abstract class Oauth2Client extends HeaderAuthenticationClient {
|
abstract class Oauth2Client extends HeaderAuthenticationClient {
|
||||||
Oauth2Client(super.inner);
|
Oauth2Client(super.inner);
|
||||||
|
|
||||||
Future<void> refresh() {
|
Future<Response?> refresh() {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> authorize(
|
Future<Response> authorize(
|
||||||
Map<String, dynamic> body, {
|
Map<String, dynamic> body, {
|
||||||
Map<String, String>? headers,
|
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/http_status.dart';
|
||||||
import 'package:wyatt_http_client/src/utils/utils.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 {
|
class RefreshTokenClient extends Oauth2Client {
|
||||||
final String authorizationEndpoint;
|
final String authorizationEndpoint;
|
||||||
final String tokenEndpoint;
|
final String tokenEndpoint;
|
||||||
@ -50,6 +122,8 @@ class RefreshTokenClient extends Oauth2Client {
|
|||||||
Map<String, String> header, [
|
Map<String, String> header, [
|
||||||
BaseRequest? request,
|
BaseRequest? request,
|
||||||
]) {
|
]) {
|
||||||
|
print('accessToken $accessToken');
|
||||||
|
print('request $request');
|
||||||
if (accessToken != null && request != null) {
|
if (accessToken != null && request != null) {
|
||||||
header[authenticationHeader] = '$authenticationMethod $accessToken';
|
header[authenticationHeader] = '$authenticationMethod $accessToken';
|
||||||
return header;
|
return header;
|
||||||
@ -58,13 +132,13 @@ class RefreshTokenClient extends Oauth2Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> authorize(
|
Future<Response> authorize(
|
||||||
Map<String, dynamic> body, {
|
Map<String, dynamic> body, {
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
}) async {
|
}) async {
|
||||||
final response = await inner.post(
|
final response = await inner.post(
|
||||||
Uri.parse(authorizationEndpoint),
|
Uri.parse(authorizationEndpoint),
|
||||||
body: jsonEncode(body),
|
body: body,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -80,10 +154,11 @@ class RefreshTokenClient extends Oauth2Client {
|
|||||||
this.refreshToken = refreshToken;
|
this.refreshToken = refreshToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> refresh() async {
|
Future<Response?> refresh() async {
|
||||||
if (refreshToken != null) {
|
if (refreshToken != null) {
|
||||||
final Map<String, String> header = {
|
final Map<String, String> header = {
|
||||||
authenticationHeader: '$authenticationHeader $refreshToken',
|
authenticationHeader: '$authenticationHeader $refreshToken',
|
||||||
@ -98,11 +173,16 @@ class RefreshTokenClient extends Oauth2Client {
|
|||||||
final body = json.decode(response.body) as Map<String, dynamic>;
|
final body = json.decode(response.body) as Map<String, dynamic>;
|
||||||
accessToken = accessTokenParser(body);
|
accessToken = accessTokenParser(body);
|
||||||
}
|
}
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<StreamedResponse> send(BaseRequest request) async {
|
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);
|
final response = await super.send(request);
|
||||||
|
|
||||||
if (response.statusCode == HttpStatus.unauthorized) {
|
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
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:http/http.dart';
|
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/protocols.dart';
|
||||||
import 'package:wyatt_http_client/src/utils/utils.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 Protocols protocol;
|
||||||
final String? authority;
|
final String? authority;
|
||||||
|
|
||||||
final Client _inner;
|
|
||||||
|
|
||||||
RestClient({
|
RestClient({
|
||||||
this.protocol = Protocols.https,
|
this.protocol = Protocols.https,
|
||||||
this.authority = '',
|
this.authority = '',
|
||||||
Client? inner,
|
super.inner,
|
||||||
}) : _inner = inner ?? Client();
|
});
|
||||||
|
|
||||||
@override
|
@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}');
|
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