blob: 5137bcb527463fb2b4b1269b98cfa74726883371 [file] [log] [blame] [edit]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'client.dart';
import 'handler_client.dart';
import 'request.dart';
import 'response.dart';
/// A function which creates a new [Client] by wrapping a [Client].
///
/// You can extend the functions of a [Client] by wrapping it in [Middleware]
/// that can intercept and process a HTTP request before it it sent to a
/// client, a response after it is received by a client, or both.
///
/// Because [Middleware] consumes a [Client] and returns a new [Client],
/// multiple [Middleware] instances can be composed together to offer rich
/// functionality.
///
/// Common uses for middleware include caching, logging, and authentication.
///
/// A simple [Middleware] can be created using [createMiddleware].
typedef Client Middleware(Client inner);
/// Creates a [Middleware] using the provided functions.
///
/// If provided, [requestHandler] receives a [Request]. It replies to the
/// request by returning a [Future<Request>]. The modified [Request] is then
/// sent to the inner [Client].
///
/// If provided, [responseHandler] is called with the [Response] generated
/// by the inner [Client]. It replies to the response by returning a
/// [Future<Response]. The modified [Response] is then returned.
///
/// If provided, [onClose] will be invoked when the [Client.close] method is
/// called. Any cleanup of resources should happen at this point.
///
/// If provided, [errorHandler] receives errors thrown by the inner handler. It
/// does not receive errors thrown by [requestHandler] or [responseHandler].
/// It can either return a new response or throw an error.
Middleware createMiddleware(
{Future<Request> requestHandler(Request request),
Future<Response> responseHandler(Response response),
void onClose(),
void errorHandler(error, [StackTrace stackTrace])}) {
requestHandler ??= (request) async => request;
responseHandler ??= (response) async => response;
return (inner) {
return new HandlerClient(
(request) => requestHandler(request)
.then((req) => inner.send(req))
.then((res) => responseHandler(res), onError: errorHandler),
onClose == null
? inner.close
: () {
onClose();
inner.close();
});
};
}