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

Side by Side Diff: tools/testing/dart/http_server.dart

Issue 12220068: Test server tweaks (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 10 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 | « no previous file | no next file » | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 library http_server; 5 library http_server;
6 6
7 import 'dart:io'; 7 import 'dart:io';
8 import 'dart:isolate'; 8 import 'dart:isolate';
9 import 'dart:uri';
9 import 'test_suite.dart'; // For TestUtils. 10 import 'test_suite.dart'; // For TestUtils.
10 // TODO(efortuna): Rewrite to not use the args library and simply take an 11 // TODO(efortuna): Rewrite to not use the args library and simply take an
11 // expected number of arguments, so test.dart doesn't rely on the args library? 12 // expected number of arguments, so test.dart doesn't rely on the args library?
12 // See discussion on https://codereview.chromium.org/11931025/. 13 // See discussion on https://codereview.chromium.org/11931025/.
13 import 'vendored_pkg/args/args.dart'; 14 import 'vendored_pkg/args/args.dart';
14 15
15 main() { 16 main() {
16 /** Convenience method for local testing. */ 17 /** Convenience method for local testing. */
17 var parser = new ArgParser(); 18 var parser = new ArgParser();
18 parser.addOption('port', abbr: 'p', 19 parser.addOption('port', abbr: 'p',
19 help: 'The main server port we wish to respond to requests.', 20 help: 'The main server port we wish to respond to requests.',
20 defaultsTo: '0'); 21 defaultsTo: '0');
21 parser.addOption('crossOriginPort', abbr: 'c', 22 parser.addOption('crossOriginPort', abbr: 'c',
22 help: 'A different port that accepts request from the main server port.', 23 help: 'A different port that accepts request from the main server port.',
23 defaultsTo: '0'); 24 defaultsTo: '0');
24 parser.addOption('mode', abbr: 'm', help: 'Testing mode.', 25 parser.addOption('mode', abbr: 'm', help: 'Testing mode.',
25 defaultsTo: 'release'); 26 defaultsTo: 'release');
26 parser.addOption('arch', abbr: 'a', help: 'Testing architecture.', 27 parser.addOption('arch', abbr: 'a', help: 'Testing architecture.',
27 defaultsTo: 'ia32'); 28 defaultsTo: 'ia32');
28 parser.addFlag('help', abbr: 'h', negatable: false, 29 parser.addFlag('help', abbr: 'h', negatable: false,
29 help: 'Print this usage information.'); 30 help: 'Print this usage information.');
30 parser.addOption('package-root', help: 'The package root to use.'); 31 parser.addOption('package-root', help: 'The package root to use.');
32 parser.addOption('network', help: 'The network interface to use.',
33 defaultsTo: '127.0.0.1');
31 var args = parser.parse(new Options().arguments); 34 var args = parser.parse(new Options().arguments);
32 if (args['help']) { 35 if (args['help']) {
33 print(parser.getUsage()); 36 print(parser.getUsage());
34 } else { 37 } else {
35 // Pretend we're running test.dart so that TestUtils doesn't get confused 38 // Pretend we're running test.dart so that TestUtils doesn't get confused
36 // about the "current directory." This is only used if we're trying to run 39 // about the "current directory." This is only used if we're trying to run
37 // this file independently for local testing. 40 // this file independently for local testing.
38 TestUtils.testScriptPath = new Path(new Options().script) 41 TestUtils.testScriptPath = new Path(new Options().script)
39 .directoryPath 42 .directoryPath
40 .join(new Path('../../test.dart')) 43 .join(new Path('../../test.dart'))
41 .canonicalize() 44 .canonicalize()
42 .toNativePath(); 45 .toNativePath();
43 // Note: args['package-root'] is always the build directory. We have the 46 // Note: args['package-root'] is always the build directory. We have the
44 // implicit assumption that it contains the 'packages' subdirectory. 47 // implicit assumption that it contains the 'packages' subdirectory.
45 // TODO: We should probably rename 'package-root' to 'build-directory'. 48 // TODO: We should probably rename 'package-root' to 'build-directory'.
46 TestingServerRunner._packageRootDir = new Path(args['package-root']); 49 TestingServerRunner._packageRootDir = new Path(args['package-root']);
47 TestingServerRunner._buildDirectory = new Path(args['package-root']); 50 TestingServerRunner._buildDirectory = new Path(args['package-root']);
48 TestingServerRunner.startHttpServer('127.0.0.1', 51 var network = args['network'];
52 TestingServerRunner.startHttpServer(network,
49 port: int.parse(args['port'])); 53 port: int.parse(args['port']));
50 print('Server listening on port ' 54 print('Server listening on port '
51 '${TestingServerRunner.serverList[0].port}.'); 55 '${TestingServerRunner.serverList[0].port}.');
52 TestingServerRunner.startHttpServer('127.0.0.1', 56 TestingServerRunner.startHttpServer(network,
53 allowedPort: TestingServerRunner.serverList[0].port, port: 57 allowedPort: TestingServerRunner.serverList[0].port, port:
54 int.parse(args['crossOriginPort'])); 58 int.parse(args['crossOriginPort']));
55 print( 59 print(
56 'Server listening on port ${TestingServerRunner.serverList[1].port}.'); 60 'Server listening on port ${TestingServerRunner.serverList[1].port}.');
57 } 61 }
58 } 62 }
59 /** 63 /**
60 * Runs a set of servers that are initialized specifically for the needs of our 64 * Runs a set of servers that are initialized specifically for the needs of our
61 * test framework, such as dealing with package-root. 65 * test framework, such as dealing with package-root.
62 */ 66 */
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 // Essentially implement the packages path rewriting, so we don't have 113 // Essentially implement the packages path rewriting, so we don't have
110 // to pass environment variables to the browsers. 114 // to pass environment variables to the browsers.
111 var requestPathStr = requestPath.toNativePath().substring( 115 var requestPathStr = requestPath.toNativePath().substring(
112 requestPath.toNativePath().indexOf(packagesDirName)); 116 requestPath.toNativePath().indexOf(packagesDirName));
113 path = packageRootDir.append(requestPathStr); 117 path = packageRootDir.append(requestPathStr);
114 file = new File(path.toNativePath()); 118 file = new File(path.toNativePath());
115 } 119 }
116 file.exists().then((exists) { 120 file.exists().then((exists) {
117 if (exists) { 121 if (exists) {
118 if (allowedPort != -1) { 122 if (allowedPort != -1) {
119 // Allow loading from localhost:$allowedPort in browsers. 123 var origin = new Uri(request.headers['Origin'][0]);
kustermann 2013/02/12 21:03:44 The 'Origin' header may not be present on HttpRequ
blois 2013/02/12 23:06:56 Updated. I wasn't aware that this server was inten
120 resp.headers.set("Access-Control-Allow-Origin", 124 // Allow loading from http://*:$allowedPort in browsers.
121 "http://127.0.0.1:$allowedPort"); 125 var allowedOrigin =
126 '${origin.scheme}://${origin.domain}:${allowedPort}';
127 resp.headers.set("Access-Control-Allow-Origin", allowedOrigin);
122 resp.headers.set('Access-Control-Allow-Credentials', 'true'); 128 resp.headers.set('Access-Control-Allow-Credentials', 'true');
123 } else { 129 } else {
124 // No allowedPort specified. Allow from anywhere (but cross-origin 130 // No allowedPort specified. Allow from anywhere (but cross-origin
125 // requests *with credentials* will fail because you can't use "*"). 131 // requests *with credentials* will fail because you can't use "*").
126 resp.headers.set("Access-Control-Allow-Origin", "*"); 132 resp.headers.set("Access-Control-Allow-Origin", "*");
127 } 133 }
128 if (path.toNativePath().endsWith('.html')) { 134 if (path.toNativePath().endsWith('.html')) {
129 resp.headers.set('Content-Type', 'text/html'); 135 resp.headers.set('Content-Type', 'text/html');
130 } else if (path.toNativePath().endsWith('.js')) { 136 } else if (path.toNativePath().endsWith('.js')) {
131 resp.headers.set('Content-Type', 'application/javascript'); 137 resp.headers.set('Content-Type', 'application/javascript');
132 } else if (path.toNativePath().endsWith('.dart')) { 138 } else if (path.toNativePath().endsWith('.dart')) {
133 resp.headers.set('Content-Type', 'application/dart'); 139 resp.headers.set('Content-Type', 'application/dart');
134 } 140 }
135 file.openInputStream().pipe(resp.outputStream); 141 file.openInputStream().pipe(resp.outputStream);
136 } else { 142 } else {
137 resp.statusCode = HttpStatus.NOT_FOUND; 143 var directory = new Directory.fromPath(path);
138 try { 144 directory.exists().then((exists) {
139 resp.outputStream.close(); 145 if (!exists) {
140 } catch (e) { 146 sendNotFound(resp);
141 if (e is StreamException) {
142 print('Test http_server error closing the response stream: $e');
143 } else { 147 } else {
144 throw e; 148 sendDirectoryListing(directory, request, resp);
145 } 149 }
146 } 150 });
147 } 151 }
148 }); 152 });
149 }; 153 };
150 154
151 // Echos back the contents of the request as the response data. 155 // Echos back the contents of the request as the response data.
152 httpServer.addRequestHandler((req) => req.path == "/echo", (request, resp) { 156 httpServer.addRequestHandler((req) => req.path == "/echo", (request, resp) {
153 resp.headers.set("Access-Control-Allow-Origin", "*"); 157 resp.headers.set("Access-Control-Allow-Origin", "*");
154 158
155 request.inputStream.pipe(resp.outputStream); 159 request.inputStream.pipe(resp.outputStream);
156 }); 160 });
157 161
158 httpServer.listen(host, port); 162 httpServer.listen(host, port);
159 serverList.add(httpServer); 163 serverList.add(httpServer);
160 } 164 }
161 165
166 static void sendNotFound(HttpResponse response) {
167 response.statusCode = HttpStatus.NOT_FOUND;
168 try {
169 response.outputStream.close();
170 } catch (e) {
171 if (e is StreamException) {
172 print('Test http_server error closing the response stream: $e');
173 } else {
174 throw e;
175 }
176 }
177 }
178
179 static void sendDirectoryListing(Directory directory, HttpRequest request,
Emily Fortuna 2013/02/12 22:21:24 can you add a little explanatory comment on this f
180 HttpResponse response) {
181 var os = response.outputStream;
kustermann 2013/02/12 21:03:44 You may want to set the content-type header to htm
Emily Fortuna 2013/02/12 22:21:24 +1 Chrome can handle it, but I've found DumpRender
blois 2013/02/12 23:06:56 Updated, though I've been using it OK on IE and iO
182 var header = '''<!DOCTYPE html>
183 <html>
184 <head>
185 <title>${request.path}</title>
186 </head>
187 <body>
188 <code>
189 <div>${request.path}</div>
190 <hr/>
191 <ul>''';
192 var footer = '''
193 </ul>
194 </code>
195 </body>
196 </html>''';
197
198 os.writeString(header);
199
200 var entries = [];
201
202 directory.list()
203 ..onFile = (filepath) {
204 var filename = new Path(filepath).filename;
205 entries.add(new _Entry(filename, filename));
206 }
207 ..onDir = (dirpath) {
208 var filename = new Path(dirpath).filename;
209 entries.add(new _Entry(filename, '$filename/'));
210 }
211 ..onDone = (_) {
212 var requestPath = new Path.raw(request.path);
213 entries.sort();
214 for (var entry in entries) {
215 os.writeString(
216 '<li><a href="${requestPath.append(entry.name)}">'
217 '${entry.displayName}</a></li>');
218 }
219 os.writeString(footer);
220 os.close();
221 };
222 }
223
162 static terminateHttpServers() { 224 static terminateHttpServers() {
163 for (var server in serverList) server.close(); 225 for (var server in serverList) server.close();
164 } 226 }
165 } 227 }
228
229 // Helper class for displaying directory listings.
230 class _Entry {
231 final String name;
232 final String displayName;
233
234 _Entry(this.name, this.displayName);
235
236 int compareTo(_Entry other) {
237 return name.compareTo(other.name);
238 }
239 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698