Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(808)

Side by Side Diff: lib/server.dart

Issue 14267030: Added support for http methods when mounting routes. (Closed) Base URL: git@github.com:dart-lang/route.git@master
Patch Set: responding to review comments Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/server_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * This library provides a simple API for routing HttpRequests based on thier 6 * This library provides a simple API for routing HttpRequests based on thier
7 * URL. 7 * URL.
8 */ 8 */
9 library route.server; 9 library route.server;
10 10
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 * var router = new Router(server); 44 * var router = new Router(server);
45 * router.filter(matchesAny(['/foo', '/bar']), authFilter); 45 * router.filter(matchesAny(['/foo', '/bar']), authFilter);
46 * router.serve('/foo').listen(fooHandler); 46 * router.serve('/foo').listen(fooHandler);
47 * router.serve('/bar').listen(barHandler); 47 * router.serve('/bar').listen(barHandler);
48 * router.defaultStream.listen(send404); 48 * router.defaultStream.listen(send404);
49 * }); 49 * });
50 */ 50 */
51 class Router { 51 class Router {
52 final Stream<HttpRequest> _incoming; 52 final Stream<HttpRequest> _incoming;
53 53
54 final Map<Pattern, StreamController> _controllers = 54 final List<_Route> _routes = <_Route>[];
55 new LinkedHashMap<Pattern, StreamController>(); 55
56
57 final Map<Pattern, Filter> _filters = new LinkedHashMap<Pattern, Filter>(); 56 final Map<Pattern, Filter> _filters = new LinkedHashMap<Pattern, Filter>();
58 57
59 final StreamController<HttpRequest> _defaultController = 58 final StreamController<HttpRequest> _defaultController =
60 new StreamController<HttpRequest>(); 59 new StreamController<HttpRequest>();
61 60
62 /** 61 /**
63 * Create a new Router that listens to the [incoming] stream, usually an 62 * Create a new Router that listens to the [incoming] stream, usually an
64 * instance of [HttpServer]. 63 * instance of [HttpServer].
65 */ 64 */
66 Router(Stream<HttpRequest> incoming) : _incoming = incoming { 65 Router(Stream<HttpRequest> incoming) : _incoming = incoming {
67 _incoming.listen(_handleRequest); 66 _incoming.listen(_handleRequest);
68 } 67 }
69 68
70 /** 69 /**
71 * Request whose URI matches [url] are sent to the stream created by this 70 * Request whose URI matches [url] and [method] (if provided) are sent to the
72 * method, and not sent to any other router streams. 71 * stream created by this method, and not sent to any other router streams.
73 */ 72 */
74 Stream<HttpRequest> serve(Pattern url) { 73 Stream<HttpRequest> serve(Pattern url, {String method}) {
75 var controller = new StreamController<HttpRequest>(); 74 var controller = new StreamController<HttpRequest>();
76 _controllers[url] = controller; 75 _routes.add(new _Route(controller, url, method:method));
77 return controller.stream; 76 return controller.stream;
78 } 77 }
79 78
80 /** 79 /**
81 * A [Filter] returns a [Future<bool>] that tells the router whether to apply 80 * A [Filter] returns a [Future<bool>] that tells the router whether to apply
82 * the remaining filters and send requests to the streams created by [serve]. 81 * the remaining filters and send requests to the streams created by [serve].
83 * 82 *
84 * If the filter returns true, the request is passed to the next filter, and 83 * If the filter returns true, the request is passed to the next filter, and
85 * then to the first matching server stream. If the filter returns false, it's 84 * then to the first matching server stream. If the filter returns false, it's
86 * assumed that the filter is handling the request and it's not forwarded. 85 * assumed that the filter is handling the request and it's not forwarded.
87 */ 86 */
88 void filter(Pattern url, Filter filter) { 87 void filter(Pattern url, Filter filter) {
89 _filters[url] = filter; 88 _filters[url] = filter;
90 } 89 }
91 90
92 Stream<HttpRequest> get defaultStream => _defaultController.stream; 91 Stream<HttpRequest> get defaultStream => _defaultController.stream;
93 92
94 void _handleRequest(HttpRequest req) { 93 void _handleRequest(HttpRequest req) {
95 bool cont = true; 94 bool cont = true;
96 doWhile(_filters.keys, (Pattern pattern) { 95 doWhile(_filters.keys, (Pattern pattern) {
97 if (matchesFull(pattern, req.uri.path)) { 96 if (matchesFull(pattern, req.uri.path)) {
98 return _filters[pattern](req).then((c) { 97 return _filters[pattern](req).then((c) {
99 cont = c; 98 cont = c;
100 return c; 99 return c;
101 }); 100 });
102 } 101 }
103 return new Future.value(true); 102 return new Future.value(true);
104 }).then((_) { 103 }).then((_) {
105 if (cont) { 104 if (cont) {
106 bool handled = false; 105 bool handled = false;
107 for (Pattern pattern in _controllers.keys) { 106 var matches = _routes.where((r) => r.matches(req));
108 if (matchesFull(pattern, req.uri.path)) { 107 if (!matches.isEmpty) {
109 _controllers[pattern].add(req); 108 matches.first.controller.add(req);
110 handled = true; 109 } else {
111 break;
112 }
113 }
114 if (!handled) {
115 if (_defaultController.hasListener) { 110 if (_defaultController.hasListener) {
116 _defaultController.add(req); 111 _defaultController.add(req);
117 } else { 112 } else {
118 send404(req); 113 send404(req);
119 } 114 }
120 } 115 }
121 } 116 }
122 }); 117 });
123 } 118 }
124 } 119 }
125 120
126 void send404(HttpRequest req) { 121 void send404(HttpRequest req) {
127 req.response.statusCode = HttpStatus.NOT_FOUND; 122 req.response.statusCode = HttpStatus.NOT_FOUND;
128 req.response.write("Not Found"); 123 req.response.write("Not Found");
129 req.response.close(); 124 req.response.close();
130 } 125 }
126
127 class _Route {
128 final Pattern url;
129 final String method;
130 final StreamController controller;
131 _Route(this.controller, this.url, {this.method});
132
133 bool matches(HttpRequest request) => matchesFull(url, request.uri.path) &&
134 (method == null || request.method.toUpperCase() == method);
135 }
OLDNEW
« no previous file with comments | « no previous file | test/server_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698