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

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: Add cert and factor out getStatusCode and getHeaders to utils.dart. 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
« no previous file with comments | « pkg/http_server/lib/http_server.dart ('k') | pkg/http_server/test/pkcert/README » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 a named-based approach.
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
45 * (`*.domain.name`). The former will only match the specific domain name
46 * while the latter will match any series of sub-domains.
47 *
48 * If both `my.domain.name` and `*.domain.name` is specified, the most
49 * qualified 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 implements 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(
113 'Wildcards are only allowed in the beginning of a host');
114 }
115 var controller = new StreamController<HttpRequest>();
116 var domains = host.split('.');
117 var current = _topDomain;
118 for (var i = domains.length - 1; i >= 0; i--) {
119 if (domains[i] == '*') {
120 if (current.any != null) {
121 throw new ArgumentError('Host is already provided');
122 }
123 current.any = controller;
124 } else {
125 if (!current.subDomains.containsKey(domains[i])) {
126 current.subDomains[domains[i]] = new _VirtualHostDomain();
127 }
128 if (i > 0) {
129 current = current.subDomains[domains[i]];
130 } else {
131 if (current.subDomains[domains[i]].exact != null) {
132 throw new ArgumentError('Host is already provided');
133 }
134 current.subDomains[domains[i]].exact = controller;
135 }
136 }
137 }
138 return controller.stream;
139 }
140
141 void _unhandled(HttpRequest request) {
142 if (_unhandledController != null) {
143 _unhandledController.add(request);
144 return;
145 }
146 request.response.statusCode = HttpStatus.FORBIDDEN;
147 request.response.close();
148 }
149 }
OLDNEW
« no previous file with comments | « pkg/http_server/lib/http_server.dart ('k') | pkg/http_server/test/pkcert/README » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698