Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library shelf.cascade; | |
| 6 | |
| 7 import 'handler.dart'; | |
| 8 import 'response.dart'; | |
| 9 import 'util.dart'; | |
| 10 | |
| 11 /// A typedef for [Cascade._shouldCascade]. | |
| 12 typedef bool _ShouldCascade(Response response); | |
| 13 | |
| 14 /// A helper that calls several handlers in sequence and returns the first | |
| 15 /// acceptable response. | |
| 16 /// | |
| 17 /// By default, a response is considered acceptable if it has a status other | |
| 18 /// than 404 or 405; other statuses indicate that the handler understood the | |
| 19 /// request. | |
| 20 /// | |
| 21 /// If all handlers return unacceptable responses, the final response will be | |
| 22 /// returned. | |
| 23 /// | |
| 24 /// var handler = new Cascade() | |
| 25 /// .add(webSocketHandler) | |
| 26 /// .add(staticFileHandler) | |
| 27 /// .add(application) | |
| 28 /// .handler; | |
| 29 class Cascade { | |
| 30 /// The function used to determine whether the cascade should continue on to | |
| 31 /// the next handler. | |
| 32 final _ShouldCascade _shouldCascade; | |
| 33 | |
| 34 final Cascade _parent; | |
| 35 final Handler _handler; | |
| 36 | |
| 37 /// Creates a new, empty cascade. | |
| 38 /// | |
| 39 /// If [statusCodes] is passed, responses with those status codes are | |
| 40 /// considered unacceptable. If [shouldCascade] is passed, responses for which | |
| 41 /// it returns `true` are considered unacceptale. [statusCode] and | |
| 42 /// [shouldCascade] may not both be passed. | |
| 43 Cascade({Iterable<int> statusCodes, bool shouldCascade(Response response)}) | |
| 44 : _shouldCascade = _computeShouldCascade(statusCodes, shouldCascade), | |
| 45 _parent = null, | |
| 46 _handler = null { | |
| 47 if (statusCodes != null && shouldCascade != null) { | |
| 48 throw new ArgumentError("statusCodes and shouldCascade may not both be " | |
| 49 "passed."); | |
| 50 } | |
| 51 } | |
| 52 | |
| 53 Cascade._(this._parent, this._handler, this._shouldCascade); | |
| 54 | |
| 55 /// Returns a new cascade with [handler] added to the end. | |
| 56 /// | |
| 57 /// [handler] will only be called if all previous handlers in the cascade | |
| 58 /// return unacceptable responses. | |
| 59 Cascade add(Handler handler) => new Cascade._(this, handler, _shouldCascade); | |
| 60 | |
| 61 /// Exposes this cascade as a single handler. | |
| 62 /// | |
| 63 /// This handler will call each inner handler in the cascade until one returns | |
| 64 /// an acceptable response, and return that. If no inner handlers return an | |
| 65 /// acceptable response, this will return the final response. | |
| 66 Handler get handler { | |
| 67 if (_handler == null) { | |
| 68 throw new StateError("Can't get a handler for a cascade with no inner " | |
| 69 "handlers."); | |
| 70 } | |
| 71 | |
| 72 return (request) { | |
| 73 if (_parent._handler == null) return _handler(request); | |
| 74 return syncFuture(() => _parent.handler(request)).then((response) { | |
| 75 if (_shouldCascade(response)) return _handler(request); | |
| 76 return response; | |
| 77 }); | |
| 78 }; | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 /// Computes the [Cascade._shouldCascade] function based on the user's | |
| 83 /// parameters. | |
| 84 Function _computeShouldCascade(Iterable<int> statusCodes, | |
|
kevmoo
2014/04/25 21:55:11
Woulda coulda used typedef here, too :-)
| |
| 85 Function shouldCascade) { | |
| 86 if (shouldCascade != null) return shouldCascade; | |
| 87 if (statusCodes == null) statusCodes = [404, 405]; | |
| 88 statusCodes = statusCodes.toSet(); | |
| 89 return (response) => statusCodes.contains(response.statusCode); | |
| 90 } | |
| OLD | NEW |