| Index: mojo/public/dart/third_party/shelf/lib/src/cascade.dart
|
| diff --git a/mojo/public/dart/third_party/shelf/lib/src/cascade.dart b/mojo/public/dart/third_party/shelf/lib/src/cascade.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cf57478312444f70059501a6e050e505edeb3e6a
|
| --- /dev/null
|
| +++ b/mojo/public/dart/third_party/shelf/lib/src/cascade.dart
|
| @@ -0,0 +1,91 @@
|
| +// Copyright (c) 2014, 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.
|
| +
|
| +library shelf.cascade;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'handler.dart';
|
| +import 'response.dart';
|
| +
|
| +/// A typedef for [Cascade._shouldCascade].
|
| +typedef bool _ShouldCascade(Response response);
|
| +
|
| +/// A helper that calls several handlers in sequence and returns the first
|
| +/// acceptable response.
|
| +///
|
| +/// By default, a response is considered acceptable if it has a status other
|
| +/// than 404 or 405; other statuses indicate that the handler understood the
|
| +/// request.
|
| +///
|
| +/// If all handlers return unacceptable responses, the final response will be
|
| +/// returned.
|
| +///
|
| +/// var handler = new Cascade()
|
| +/// .add(webSocketHandler)
|
| +/// .add(staticFileHandler)
|
| +/// .add(application)
|
| +/// .handler;
|
| +class Cascade {
|
| + /// The function used to determine whether the cascade should continue on to
|
| + /// the next handler.
|
| + final _ShouldCascade _shouldCascade;
|
| +
|
| + final Cascade _parent;
|
| + final Handler _handler;
|
| +
|
| + /// Creates a new, empty cascade.
|
| + ///
|
| + /// If [statusCodes] is passed, responses with those status codes are
|
| + /// considered unacceptable. If [shouldCascade] is passed, responses for which
|
| + /// it returns `true` are considered unacceptable. [statusCode] and
|
| + /// [shouldCascade] may not both be passed.
|
| + Cascade({Iterable<int> statusCodes, bool shouldCascade(Response response)})
|
| + : _shouldCascade = _computeShouldCascade(statusCodes, shouldCascade),
|
| + _parent = null,
|
| + _handler = null {
|
| + if (statusCodes != null && shouldCascade != null) {
|
| + throw new ArgumentError("statusCodes and shouldCascade may not both be "
|
| + "passed.");
|
| + }
|
| + }
|
| +
|
| + Cascade._(this._parent, this._handler, this._shouldCascade);
|
| +
|
| + /// Returns a new cascade with [handler] added to the end.
|
| + ///
|
| + /// [handler] will only be called if all previous handlers in the cascade
|
| + /// return unacceptable responses.
|
| + Cascade add(Handler handler) => new Cascade._(this, handler, _shouldCascade);
|
| +
|
| + /// Exposes this cascade as a single handler.
|
| + ///
|
| + /// This handler will call each inner handler in the cascade until one returns
|
| + /// an acceptable response, and return that. If no inner handlers return an
|
| + /// acceptable response, this will return the final response.
|
| + Handler get handler {
|
| + if (_handler == null) {
|
| + throw new StateError("Can't get a handler for a cascade with no inner "
|
| + "handlers.");
|
| + }
|
| +
|
| + return (request) {
|
| + if (_parent._handler == null) return _handler(request);
|
| + return new Future.sync(() => _parent.handler(request)).then((response) {
|
| + if (_shouldCascade(response)) return _handler(request);
|
| + return response;
|
| + });
|
| + };
|
| + }
|
| +}
|
| +
|
| +/// Computes the [Cascade._shouldCascade] function based on the user's
|
| +/// parameters.
|
| +Function _computeShouldCascade(
|
| + Iterable<int> statusCodes, Function shouldCascade) {
|
| + if (shouldCascade != null) return shouldCascade;
|
| + if (statusCodes == null) statusCodes = [404, 405];
|
| + statusCodes = statusCodes.toSet();
|
| + return (response) => statusCodes.contains(response.statusCode);
|
| +}
|
|
|