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

Side by Side Diff: pkg/http_server/lib/src/virtual_host.dart

Issue 17581002: Add new VirtualHost class to http_server package, for handling multiple hosts on multiple sources (… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of http_server;
6
7
8 /**
9 * The [VirtualHost] class is a utility class for handling multiple hosts on
10 * multiple sources, by using name-based approach.
ricow1 2013/06/24 07:41:30 using name-based -> using a named-based
Anders Johnsen 2013/06/24 10:07:06 Done.
11 */
12 abstract class VirtualHost {
13 /**
14 * Get the [Stream] of [HttpRequest]s, not matching any hosts. If unused, the
15 * default implementation will result in a [HttpHeaders.FORBIDDEN] response.
16 */
17 Stream<HttpRequest> get unhandled;
18
19 /**
20 * Construct a new [VirtualHost].
21 *
22 * The optional [source] is a shortcut for calling [addSource].
23 *
24 * Example of usage:
25 *
26 * HttpServer.bind(..., 80).then((server) {
27 * var virtualHost = new VirtualHost(server);
28 * virtualServer.addHost('static.myserver.com')
29 * .listen(...);
30 * virtualServer.addHost('cache.myserver.com')
31 * .listen(...);
32 * })
33 */
34 factory VirtualHost([Stream<HttpRequest> source]) => new _VirtualHost(source);
35
36 /**
37 * Provide another source of [HttpRequest]s in the form of a [Stream].
38 */
39 void addSource(Stream<HttpRequest> source);
40
41
42 /**
43 * Add a host to the [VirtualHost] instance. The host can be either a specific
44 * domain (`my.domain.name`) or a wildcard-based domain name (`*.domain.name`) .
Søren Gjesse 2013/06/24 07:58:37 Long line.
Anders Johnsen 2013/06/24 10:07:06 Done.
45 * the former will only match the specific domain name while the latter will
46 * match any series of sub-domains.
47 *
48 * If both `my.domain.name` and `*.domain.name` is specified, the most qualifi ed
ricow1 2013/06/24 07:41:30 long line
Søren Gjesse 2013/06/24 07:58:37 Long line.
Anders Johnsen 2013/06/24 10:07:06 Done.
Anders Johnsen 2013/06/24 10:07:06 Done.
49 * will take precedence, `my.domain.name` in this case.
50 */
51 Stream<HttpRequest> addHost(String host);
52 }
53
54
55 class _VirtualHostDomain {
56 StreamController<HttpRequest> any;
57 StreamController<HttpRequest> exact;
58 Map<String, _VirtualHostDomain> subDomains = {};
59 }
60
61
62 class _VirtualHost {
63 final _VirtualHostDomain _topDomain = new _VirtualHostDomain();
64 StreamController<HttpRequest> _unhandledController;
65
66 Stream<HttpRequest> get unhandled {
67 if (_unhandledController == null) {
68 _unhandledController = new StreamController<HttpRequest>();
69 }
70 return _unhandledController.stream;
71 }
72
73 _VirtualHost([Stream<HttpRequest> source]) {
74 if (source != null) addSource(source);
75 }
76
77 void addSource(Stream<HttpRequest> source) {
78 source.listen((request) {
79 var host = request.headers.host;
80 if (host == null) {
81 _unhandled(request);
82 return;
83 }
84 var domains = host.split('.');
85 var current = _topDomain;
86 var any;
87 for (var i = domains.length - 1; i >= 0; i--) {
88 if (current.any != null) any = current.any;
89 if (i == 0) {
90 var last = current.subDomains[domains[i]];
91 if (last != null && last.exact != null) {
92 last.exact.add(request);
93 return;
94 }
95 } else {
96 if (!current.subDomains.containsKey(domains[i])) {
97 break;
98 }
99 current = current.subDomains[domains[i]];
100 }
101 }
102 if (any != null) {
103 any.add(request);
104 return;
105 }
106 _unhandled(request);
107 });
108 }
109
110 Stream<HttpRequest> addHost(String host) {
111 if (host.lastIndexOf('*') > 0) {
112 throw new ArgumentError('Invalid wildcard in host');
Søren Gjesse 2013/06/24 07:58:37 Possibly improve this message, as wildcards are ac
Anders Johnsen 2013/06/24 10:07:06 Done.
113 }
114 var controller = new StreamController<HttpRequest>();
115 var domains = host.split('.');
116 var current = _topDomain;
117 for (var i = domains.length - 1; i >= 0; i--) {
118 if (domains[i] == '*') {
119 if (current.any != null) {
120 throw new ArgumentError('Host is already provided');
121 }
122 current.any = controller;
123 } else {
124 if (!current.subDomains.containsKey(domains[i])) {
125 current.subDomains[domains[i]] = new _VirtualHostDomain();
126 }
127 if (i > 0) {
128 current = current.subDomains[domains[i]];
129 } else {
130 if (current.subDomains[domains[i]].exact != null) {
131 throw new ArgumentError('Host is already provided');
132 }
133 current.subDomains[domains[i]].exact = controller;
134 }
135 }
136 }
137 return controller.stream;
138 }
139
140 void _unhandled(HttpRequest request) {
141 if (_unhandledController != null) {
142 _unhandledController.add(request);
143 return;
144 }
145 request.response.statusCode = 403;
Søren Gjesse 2013/06/24 07:58:37 Use HttpStatus.XXX
Anders Johnsen 2013/06/24 10:07:06 Done.
146 request.response.close();
147 }
148 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698