// 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 . import 'package:wyatt_http_client/src/middleware.dart'; import 'package:wyatt_http_client/src/models/middleware_context.dart'; import 'package:wyatt_http_client/src/models/middleware_request.dart'; import 'package:wyatt_http_client/src/models/middleware_response.dart'; /// {@template pipeline} /// A [Pipeline] is a list of [Middleware]s that are executed in order. /// {@endtemplate} class Pipeline { /// {@macro pipeline} Pipeline() : _middlewares = []; /// {@macro pipeline} Pipeline.fromIterable(Iterable middlewares) : _middlewares = middlewares.toList(); final List _middlewares; /// The length of the [Pipeline]. /// /// This is the number of [Middleware]s in the [Pipeline]. int get length => _middlewares.length; /// Add a [Middleware] to this [Pipeline] void addMiddleware(Middleware middleware) { _middlewares.add(middleware); } /// Create new [Pipeline] from the start or end to a specified [Middleware]. Pipeline sub( Middleware middleware, { bool include = false, bool fromEnd = false, }) { final nodes = []; final list = fromEnd ? _middlewares.reversed : _middlewares; for (final m in list) { if (m != middleware) { nodes.add(m); } if (m == middleware) { if (include) { nodes.add(m); } break; } } return Pipeline.fromIterable(fromEnd ? nodes.reversed : nodes); } /// Call the [onRequest] method of all [OnRequestMiddleware]s in the /// [Pipeline]. /// /// The [MiddlewareRequest] returned by the last [OnRequestMiddleware] is /// returned. Future onRequest( MiddlewareContext context, MiddlewareRequest request, ) async { MiddlewareRequest req = request..apply(); MiddlewareContext ctx = context.copyWith(lastRequest: req); for (final middleware in _middlewares) { if (middleware is OnRequestMiddleware) { req = await (middleware as OnRequestMiddleware).onRequest(ctx, request); ctx = context.copyWith(lastRequest: req); } } return req; } /// Call the [onResponse] method of all [OnResponseMiddleware]s in the /// [Pipeline]. /// /// The [MiddlewareResponse] returned by the last [OnResponseMiddleware] is /// returned. Future onResponse( MiddlewareContext context, MiddlewareResponse response, ) async { MiddlewareResponse res = response; MiddlewareContext ctx = context.copyWith(lastResponse: res); for (final middleware in _middlewares.reversed) { if (middleware is OnResponseMiddleware) { res = await (middleware as OnResponseMiddleware) .onResponse(ctx, response); ctx = context.copyWith(lastResponse: res); } } return res; } @override String toString() { final req = []; final res = []; for (final middleware in _middlewares) { if (middleware is OnRequestMiddleware) { req.add(middleware.getName()); } if (middleware is OnResponseMiddleware) { res.insert(0, middleware.getName()); } } return '[Req] -> ${req.join(' -> ')}\n[Res] -> ${res.join(' -> ')}'; } }