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

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 TestingServerRunner._packageRootDir = new Path(args['package-root']); 46 TestingServerRunner._packageRootDir = new Path(args['package-root']);
44 TestingServerRunner.startHttpServer('127.0.0.1', 47 var network = args['network'];
48 TestingServerRunner.startHttpServer(network,
45 port: int.parse(args['port'])); 49 port: int.parse(args['port']));
46 print('Server listening on port ' 50 print('Server listening on port '
47 '${TestingServerRunner.serverList[0].port}.'); 51 '${TestingServerRunner.serverList[0].port}.');
48 TestingServerRunner.startHttpServer('127.0.0.1', 52 TestingServerRunner.startHttpServer(network,
49 allowedPort: TestingServerRunner.serverList[0].port, port: 53 allowedPort: TestingServerRunner.serverList[0].port, port:
50 int.parse(args['crossOriginPort'])); 54 int.parse(args['crossOriginPort']));
51 print( 55 print(
52 'Server listening on port ${TestingServerRunner.serverList[1].port}.'); 56 'Server listening on port ${TestingServerRunner.serverList[1].port}.');
53 } 57 }
54 } 58 }
55 /** 59 /**
56 * Runs a set of servers that are initialized specifically for the needs of our 60 * Runs a set of servers that are initialized specifically for the needs of our
57 * test framework, such as dealing with package-root. 61 * test framework, such as dealing with package-root.
58 */ 62 */
(...skipping 27 matching lines...) Expand all
86 // Essentially implement the packages path rewriting, so we don't have 90 // Essentially implement the packages path rewriting, so we don't have
87 // to pass environment variables to the browsers. 91 // to pass environment variables to the browsers.
88 var requestPathStr = requestPath.toNativePath().substring( 92 var requestPathStr = requestPath.toNativePath().substring(
89 requestPath.toNativePath().indexOf(packagesDirName)); 93 requestPath.toNativePath().indexOf(packagesDirName));
90 path = packageRootDir.append(requestPathStr); 94 path = packageRootDir.append(requestPathStr);
91 file = new File(path.toNativePath()); 95 file = new File(path.toNativePath());
92 } 96 }
93 file.exists().then((exists) { 97 file.exists().then((exists) {
94 if (exists) { 98 if (exists) {
95 if (allowedPort != -1) { 99 if (allowedPort != -1) {
96 // Allow loading from localhost:$allowedPort in browsers. 100 if (request.headers.value('Origin') != null) {
97 resp.headers.set("Access-Control-Allow-Origin", 101 var origin = new Uri(request.headers.value('Origin'));
98 "http://127.0.0.1:$allowedPort"); 102 // Allow loading from http://*:$allowedPort in browsers.
99 resp.headers.set('Access-Control-Allow-Credentials', 'true'); 103 var allowedOrigin =
104 '${origin.scheme}://${origin.domain}:${allowedPort}';
105 resp.headers.set("Access-Control-Allow-Origin", allowedOrigin);
106 resp.headers.set('Access-Control-Allow-Credentials', 'true');
107 }
100 } else { 108 } else {
101 // No allowedPort specified. Allow from anywhere (but cross-origin 109 // No allowedPort specified. Allow from anywhere (but cross-origin
102 // requests *with credentials* will fail because you can't use "*"). 110 // requests *with credentials* will fail because you can't use "*").
103 resp.headers.set("Access-Control-Allow-Origin", "*"); 111 resp.headers.set("Access-Control-Allow-Origin", "*");
104 } 112 }
105 if (path.toNativePath().endsWith('.html')) { 113 if (path.toNativePath().endsWith('.html')) {
106 resp.headers.set('Content-Type', 'text/html'); 114 resp.headers.set('Content-Type', 'text/html');
107 } else if (path.toNativePath().endsWith('.js')) { 115 } else if (path.toNativePath().endsWith('.js')) {
108 resp.headers.set('Content-Type', 'application/javascript'); 116 resp.headers.set('Content-Type', 'application/javascript');
109 } else if (path.toNativePath().endsWith('.dart')) { 117 } else if (path.toNativePath().endsWith('.dart')) {
110 resp.headers.set('Content-Type', 'application/dart'); 118 resp.headers.set('Content-Type', 'application/dart');
111 } 119 }
112 file.openInputStream().pipe(resp.outputStream); 120 file.openInputStream().pipe(resp.outputStream);
113 } else { 121 } else {
114 resp.statusCode = HttpStatus.NOT_FOUND; 122 var directory = new Directory.fromPath(path);
115 try { 123 directory.exists().then((exists) {
116 resp.outputStream.close(); 124 if (!exists) {
117 } catch (e) { 125 sendNotFound(resp);
118 if (e is StreamException) {
119 print('Test http_server error closing the response stream: $e');
120 } else { 126 } else {
121 throw e; 127 sendDirectoryListing(directory, request, resp);
122 } 128 }
123 } 129 });
124 } 130 }
125 }); 131 });
126 }; 132 };
127 133
128 // Echos back the contents of the request as the response data. 134 // Echos back the contents of the request as the response data.
129 httpServer.addRequestHandler((req) => req.path == "/echo", (request, resp) { 135 httpServer.addRequestHandler((req) => req.path == "/echo", (request, resp) {
130 resp.headers.set("Access-Control-Allow-Origin", "*"); 136 resp.headers.set("Access-Control-Allow-Origin", "*");
131 137
132 request.inputStream.pipe(resp.outputStream); 138 request.inputStream.pipe(resp.outputStream);
133 }); 139 });
134 140
135 httpServer.listen(host, port); 141 httpServer.listen(host, port);
136 serverList.add(httpServer); 142 serverList.add(httpServer);
137 } 143 }
138 144
145 static void sendNotFound(HttpResponse response) {
146 response.statusCode = HttpStatus.NOT_FOUND;
147 try {
148 response.outputStream.close();
149 } catch (e) {
150 if (e is StreamException) {
151 print('Test http_server error closing the response stream: $e');
152 } else {
153 throw e;
154 }
155 }
156 }
157
158 /**
159 * Sends a simple listing of all the files and sub-directories within
160 * directory.
161 *
162 * This is intended to make it easier to browse tests when manually running
163 * tests against this test server.
164 */
165 static void sendDirectoryListing(Directory directory, HttpRequest request,
166 HttpResponse response) {
167 response.headers.set('Content-Type', 'text/html');
168 var header = '''<!DOCTYPE html>
169 <html>
170 <head>
171 <title>${request.path}</title>
172 </head>
173 <body>
174 <code>
175 <div>${request.path}</div>
176 <hr/>
177 <ul>''';
178 var footer = '''
179 </ul>
180 </code>
181 </body>
182 </html>''';
183
184 var entries = [];
185
186 directory.list()
187 ..onFile = (filepath) {
188 var filename = new Path(filepath).filename;
189 entries.add(new _Entry(filename, filename));
190 }
191 ..onDir = (dirpath) {
192 var filename = new Path(dirpath).filename;
193 entries.add(new _Entry(filename, '$filename/'));
194 }
195 ..onDone = (_) {
196 var requestPath = new Path.raw(request.path);
197 entries.sort();
198
199 response.outputStream.writeString(header);
200 for (var entry in entries) {
201 response.outputStream.writeString(
202 '<li><a href="${requestPath.append(entry.name)}">'
203 '${entry.displayName}</a></li>');
204 }
205 response.outputStream.writeString(footer);
206 response.outputStream.close();
207 };
208 }
209
139 static terminateHttpServers() { 210 static terminateHttpServers() {
140 for (var server in serverList) server.close(); 211 for (var server in serverList) server.close();
141 } 212 }
142 } 213 }
214
215 // Helper class for displaying directory listings.
216 class _Entry {
217 final String name;
218 final String displayName;
219
220 _Entry(this.name, this.displayName);
221
222 int compareTo(_Entry other) {
223 return name.compareTo(other.name);
224 }
225 }
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