183 lines
5.2 KiB
Markdown

<!--
* 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/>.
-->
# HTTP Client
<p align="left">
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis"><img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" /></a>
<img src="https://img.shields.io/badge/SDK-Dart%20%7C%20Flutter-blue?style=flat-square" alt="SDK: Dart & Flutter" />
</p>
HTTP Client for Dart with Middlewares !
## Getting started
Simply add wyatt_http_client in pubspec.yaml, then
```dart
import 'package:wyatt_http_client/wyatt_http_client.dart';
```
## Usage
Firstly you have to understand **Middleware** and **Pipeline** concepts.
In `wyatt_http_client` a middleware is an object where requests and responses
pass through. And a pipeline is basicaly a list of middlewares.
In a pipeline with middlewares A and B, if request pass through A, then B,
the response will pass through B then A.
> You can `print(pipeline)` to get full process order of a pipeline.
For example, if you want to log every request, and simplify an url you can use provided `SimpleLogger` and `UriPrefix` .
```dart
// Create the Pipeline
final Pipeline pipeline = Pipeline()
..addMiddleware(
const UriPrefixMiddleware(
protocol: Protocols.http,
authority: 'localhost:80',
),
)
..addMiddleware(const SimpleLoggerMiddleware());
```
Then if you print the pipeline,
```
[Req] -> UriPrefix -> SimpleLogger
[Res] -> SimpleLogger
```
> The `response` doesn't pass through `UriPrefix` because it's an `OnRequestMiddleware` only.
And you can create a client.
```dart
final client = MiddlewareClient(pipeline: pipeline);
```
At this point you can use `client` like every Client from `package:http/http.dart` .
## Recipes
### Rest API with URL Authentication
Let's build a client for a REST API where the (bad) authentication is through the URL.
We need some middlewares:
* SimpleLogger, to log every request and response (useful for debug).
* BodyToJson, to automaticaly transform Map object to JSON.
* UriPrefix, to simplify the build of an API Object (save protocol and API prefix).
* UnsafeAuth, to use url based authentication.
Let's start by creating the Pipeline:
```dart
final Pipeline pipeline = Pipeline()
..addMiddleware(
const UriPrefixMiddleware(
protocol: Protocols.http,
authority: 'localhost:80',
),
)
..addMiddleware(const BodyToJsonMiddleware())
..addMiddleware(
const UnsafeAuthMiddleware(
username: 'wyatt',
password: 'motdepasse',
),
)
..addMiddleware(SimpleLoggerMiddleware());
```
Then simply create a client and make a call.
```dart
final client = MiddlewareClient(pipeline: pipeline);
await client.get(Uri.parse('/protected'));
```
> Here it make a `GET` call on `http://localhost:80/protected?username=wyatt&password=motdepasse`
And voilà.
### Rest API with Oauth2
So now we want a real authentication.
```dart
final Pipeline pipeline = Pipeline()
..addMiddleware(
const UriPrefixMiddleware(
protocol: Protocols.http,
authority: 'localhost:80',
),
)
..addMiddleware(const BodyToJsonMiddleware())
..addMiddleware(
RefreshTokenAuthMiddleware(
authorizationEndpoint: '/auth/sign-in',
tokenEndpoint: '/auth/refresh',
accessTokenParser: (body) => body['access_token']! as String,
refreshTokenParser: (body) => body['refresh_token']! as String,
unauthorized: HttpStatus.forbidden,
),
)
..addMiddleware(const SimpleLoggerMiddleware());
```
> Here we just change `UnsafeAuthMiddleware` by `RefreshTokenAuthMiddleware` and the whole app while adapt to a new authentication system.
### Create a new Middleware
You can create your own middleware by implementing `Middleware` class, and use mixins to add `OnRequest` and/or `OnResponse` methods.
```dart
class SimpleLoggerMiddleware
with OnRequestMiddleware, OnResponseMiddleware
implements Middleware {
const SimpleLoggerMiddleware();
@override
String getName() => 'SimpleLogger';
@override
Future<MiddlewareRequest> onRequest(
MiddlewareContext context,
MiddlewareRequest request,
) async {
print('${getName()}::OnRequest');
return request;
}
@override
Future<MiddlewareResponse> onResponse(
MiddlewareContext context,
MiddlewareResponse response,
) async {
print('${getName()}::OnResponse');
return response;
}
}
```