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

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 if (request.headers.value('Origin') != null) {
120 resp.headers.set("Access-Control-Allow-Origin", 124 var origin = new Uri(request.headers.value('Origin'));
121 "http://127.0.0.1:$allowedPort"); 125 // Allow loading from http://*:$allowedPort in browsers.
122 resp.headers.set('Access-Control-Allow-Credentials', 'true'); 126 var allowedOrigin =
127 '${origin.scheme}://${origin.domain}:${allowedPort}';
128 resp.headers.set("Access-Control-Allow-Origin", allowedOrigin);
129 resp.headers.set('Access-Control-Allow-Credentials', 'true');
130 }
123 } else { 131 } else {
124 // No allowedPort specified. Allow from anywhere (but cross-origin 132 // No allowedPort specified. Allow from anywhere (but cross-origin
125 // requests *with credentials* will fail because you can't use "*"). 133 // requests *with credentials* will fail because you can't use "*").
126 resp.headers.set("Access-Control-Allow-Origin", "*"); 134 resp.headers.set("Access-Control-Allow-Origin", "*");
127 } 135 }
128 if (path.toNativePath().endsWith('.html')) { 136 if (path.toNativePath().endsWith('.html')) {
129 resp.headers.set('Content-Type', 'text/html'); 137 resp.headers.set('Content-Type', 'text/html');
130 } else if (path.toNativePath().endsWith('.js')) { 138 } else if (path.toNativePath().endsWith('.js')) {
131 resp.headers.set('Content-Type', 'application/javascript'); 139 resp.headers.set('Content-Type', 'application/javascript');
132 } else if (path.toNativePath().endsWith('.dart')) { 140 } else if (path.toNativePath().endsWith('.dart')) {
133 resp.headers.set('Content-Type', 'application/dart'); 141 resp.headers.set('Content-Type', 'application/dart');
134 } 142 }
135 file.openInputStream().pipe(resp.outputStream); 143 file.openInputStream().pipe(resp.outputStream);
136 } else { 144 } else {
137 resp.statusCode = HttpStatus.NOT_FOUND; 145 var directory = new Directory.fromPath(path);
138 try { 146 directory.exists().then((exists) {
139 resp.outputStream.close(); 147 if (!exists) {
140 } catch (e) { 148 sendNotFound(resp);
141 if (e is StreamException) {
142 print('Test http_server error closing the response stream: $e');
143 } else { 149 } else {
144 throw e; 150 sendDirectoryListing(directory, request, resp);
145 } 151 }
146 } 152 });
147 } 153 }
148 }); 154 });
149 }; 155 };
150 156
151 // Echos back the contents of the request as the response data. 157 // Echos back the contents of the request as the response data.
152 httpServer.addRequestHandler((req) => req.path == "/echo", (request, resp) { 158 httpServer.addRequestHandler((req) => req.path == "/echo", (request, resp) {
153 resp.headers.set("Access-Control-Allow-Origin", "*"); 159 resp.headers.set("Access-Control-Allow-Origin", "*");
154 160
155 request.inputStream.pipe(resp.outputStream); 161 request.inputStream.pipe(resp.outputStream);
156 }); 162 });
157 163
158 httpServer.listen(host, port); 164 httpServer.listen(host, port);
159 serverList.add(httpServer); 165 serverList.add(httpServer);
160 } 166 }
161 167
168 static void sendNotFound(HttpResponse response) {
169 response.statusCode = HttpStatus.NOT_FOUND;
170 try {
171 response.outputStream.close();
172 } catch (e) {
173 if (e is StreamException) {
174 print('Test http_server error closing the response stream: $e');
175 } else {
176 throw e;
177 }
178 }
179 }
180
181 /**
182 * Sends a simple listing of all the files and sub-directories within
183 * directory.
184 *
185 * This is intended to make it easier to browse tests when manually running
186 * tests against this test server.
187 */
188 static void sendDirectoryListing(Directory directory, HttpRequest request,
189 HttpResponse response) {
190 response.headers.set('Content-Type', 'text/html');
191 var os = response.outputStream;
ricow1 2013/02/13 13:31:20 could we have a more describing variable name here
blois 2013/02/13 22:27:02 Removed it completely, it's old habit of mine to u
192 var header = '''<!DOCTYPE html>
193 <html>
194 <head>
195 <title>${request.path}</title>
196 </head>
197 <body>
198 <code>
199 <div>${request.path}</div>
200 <hr/>
201 <ul>''';
202 var footer = '''
203 </ul>
204 </code>
205 </body>
206 </html>''';
207
208 os.writeString(header);
ricow1 2013/02/13 13:31:20 move this down in the onDone, then we have all the
blois 2013/02/13 22:27:02 Done. I had been hoping that I could write them ou
ricow1 2013/02/14 07:15:57 Yeah, I already had a big comment asking why the b
209
210 var entries = [];
211
212 directory.list()
213 ..onFile = (filepath) {
214 var filename = new Path(filepath).filename;
215 entries.add(new _Entry(filename, filename));
216 }
217 ..onDir = (dirpath) {
218 var filename = new Path(dirpath).filename;
219 entries.add(new _Entry(filename, '$filename/'));
220 }
221 ..onDone = (_) {
222 var requestPath = new Path.raw(request.path);
223 entries.sort();
224 for (var entry in entries) {
225 os.writeString(
226 '<li><a href="${requestPath.append(entry.name)}">'
227 '${entry.displayName}</a></li>');
228 }
229 os.writeString(footer);
230 os.close();
231 };
232 }
233
162 static terminateHttpServers() { 234 static terminateHttpServers() {
163 for (var server in serverList) server.close(); 235 for (var server in serverList) server.close();
164 } 236 }
165 } 237 }
238
239 // Helper class for displaying directory listings.
240 class _Entry {
241 final String name;
242 final String displayName;
243
244 _Entry(this.name, this.displayName);
245
246 int compareTo(_Entry other) {
247 return name.compareTo(other.name);
248 }
249 }
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