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