| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 import 'dart:isolate'; | 9 import 'dart:isolate'; |
| 10 import 'dart:uri'; | 10 import 'dart:uri'; |
| 11 import 'test_suite.dart'; // For TestUtils. | 11 import 'test_suite.dart'; // For TestUtils. |
| 12 // TODO(efortuna): Rewrite to not use the args library and simply take an | 12 // TODO(efortuna): Rewrite to not use the args library and simply take an |
| 13 // expected number of arguments, so test.dart doesn't rely on the args library? | 13 // expected number of arguments, so test.dart doesn't rely on the args library? |
| 14 // See discussion on https://codereview.chromium.org/11931025/. | 14 // See discussion on https://codereview.chromium.org/11931025/. |
| 15 import 'vendored_pkg/args/args.dart'; | 15 import 'vendored_pkg/args/args.dart'; |
| 16 import 'utils.dart'; | 16 import 'utils.dart'; |
| 17 | 17 |
| 18 | 18 |
| 19 /// Interface of the HTTP server: | 19 /// Interface of the HTTP server: |
| 20 /// | 20 /// |
| 21 /// /echo: This will stream the data received in the request stream back | 21 /// /echo: This will stream the data received in the request stream back |
| 22 /// to the client. | 22 /// to the client. |
| 23 /// /root_dart/X: This will serve the corresponding file from the dart | 23 /// /root_dart/X: This will serve the corresponding file from the dart |
| 24 /// directory (i.e. '$DartDirectory/X'). | 24 /// directory (i.e. '$DartDirectory/X'). |
| 25 /// /root_build/X: This will serve the corresponding file from the build | 25 /// /root_build/X: This will serve the corresponding file from the build |
| 26 /// directory (i.e. '$BuildDirectory/X'). | 26 /// directory (i.e. '$BuildDirectory/X'). |
| 27 /// /FOO/packages/BAR: This will serve the corresponding file from the packages | 27 /// /FOO/packages/BAR: This will serve the corresponding file from the packages |
| 28 /// directory (i.e. '$BuildDirectory/packages/BAR') | 28 /// directory (i.e. '$BuildDirectory/packages/BAR') |
| 29 /// /ws: This will upgrade the connection to a WebSocket connection and echo |
| 30 /// all data back to the client. |
| 29 /// | 31 /// |
| 30 /// In case a path does not refer to a file but rather to a directory, a | 32 /// In case a path does not refer to a file but rather to a directory, a |
| 31 /// directory listing will be displayed. | 33 /// directory listing will be displayed. |
| 32 | 34 |
| 33 const PREFIX_BUILDDIR = 'root_build'; | 35 const PREFIX_BUILDDIR = 'root_build'; |
| 34 const PREFIX_DARTDIR = 'root_dart'; | 36 const PREFIX_DARTDIR = 'root_dart'; |
| 35 | 37 |
| 36 // TODO(kustermann,ricow): We could change this to the following scheme: | 38 // TODO(kustermann,ricow): We could change this to the following scheme: |
| 37 // http://host:port/root_packages/X -> $BuildDir/packages/X | 39 // http://host:port/root_packages/X -> $BuildDir/packages/X |
| 38 // Issue: 8368 | 40 // Issue: 8368 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 for (var server in _serverList) { | 127 for (var server in _serverList) { |
| 126 server.close(); | 128 server.close(); |
| 127 } | 129 } |
| 128 } | 130 } |
| 129 | 131 |
| 130 Future _startHttpServer(String host, {int port: 0, int allowedPort: -1}) { | 132 Future _startHttpServer(String host, {int port: 0, int allowedPort: -1}) { |
| 131 return HttpServer.bind(host, port).then((HttpServer httpServer) { | 133 return HttpServer.bind(host, port).then((HttpServer httpServer) { |
| 132 httpServer.listen((HttpRequest request) { | 134 httpServer.listen((HttpRequest request) { |
| 133 if (request.uri.path == "/echo") { | 135 if (request.uri.path == "/echo") { |
| 134 _handleEchoRequest(request, request.response); | 136 _handleEchoRequest(request, request.response); |
| 137 } else if (request.uri.path == '/ws') { |
| 138 _handleWebSocketRequest(request); |
| 135 } else { | 139 } else { |
| 136 _handleFileOrDirectoryRequest( | 140 _handleFileOrDirectoryRequest( |
| 137 request, request.response, allowedPort); | 141 request, request.response, allowedPort); |
| 138 } | 142 } |
| 139 }, | 143 }, |
| 140 onError: (e) { | 144 onError: (e) { |
| 141 DebugLogger.error('HttpServer: an error occured: $e'); | 145 DebugLogger.error('HttpServer: an error occured: $e'); |
| 142 }); | 146 }); |
| 143 _serverList.add(httpServer); | 147 _serverList.add(httpServer); |
| 144 }); | 148 }); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 } | 183 } |
| 180 | 184 |
| 181 void _handleEchoRequest(HttpRequest request, HttpResponse response) { | 185 void _handleEchoRequest(HttpRequest request, HttpResponse response) { |
| 182 response.headers.set("Access-Control-Allow-Origin", "*"); | 186 response.headers.set("Access-Control-Allow-Origin", "*"); |
| 183 request.pipe(response).catchError((e) { | 187 request.pipe(response).catchError((e) { |
| 184 DebugLogger.warning( | 188 DebugLogger.warning( |
| 185 'HttpServer: error while closing the response stream: $e'); | 189 'HttpServer: error while closing the response stream: $e'); |
| 186 }); | 190 }); |
| 187 } | 191 } |
| 188 | 192 |
| 193 void _handleWebSocketRequest(HttpRequest request) { |
| 194 WebSocketTransformer.upgrade(request).then((websocket) { |
| 195 websocket.listen((data) { |
| 196 websocket.send(data); |
| 197 websocket.close(); |
| 198 }, onError: (e) { |
| 199 DebugLogger.warning( |
| 200 'HttpServer: error while echoing to WebSocket: $e'); |
| 201 }); |
| 202 }).catchError((e) { |
| 203 DebugLogger.warning( |
| 204 'HttpServer: error while transforming to WebSocket: $e'); |
| 205 }); |
| 206 } |
| 207 |
| 189 Path _getFilePathFromRequestPath(String urlRequestPath) { | 208 Path _getFilePathFromRequestPath(String urlRequestPath) { |
| 190 // Go to the top of the file to see an explanation of the URL path scheme. | 209 // Go to the top of the file to see an explanation of the URL path scheme. |
| 191 var requestPath = new Path(urlRequestPath.substring(1)).canonicalize(); | 210 var requestPath = new Path(urlRequestPath.substring(1)).canonicalize(); |
| 192 var pathSegments = requestPath.segments(); | 211 var pathSegments = requestPath.segments(); |
| 193 if (pathSegments.length > 0) { | 212 if (pathSegments.length > 0) { |
| 194 var basePath; | 213 var basePath; |
| 195 var relativePath; | 214 var relativePath; |
| 196 if (pathSegments[0] == PREFIX_BUILDDIR) { | 215 if (pathSegments[0] == PREFIX_BUILDDIR) { |
| 197 basePath = _buildDirectory; | 216 basePath = _buildDirectory; |
| 198 relativePath = new Path( | 217 relativePath = new Path( |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 class _Entry { | 361 class _Entry { |
| 343 final String name; | 362 final String name; |
| 344 final String displayName; | 363 final String displayName; |
| 345 | 364 |
| 346 _Entry(this.name, this.displayName); | 365 _Entry(this.name, this.displayName); |
| 347 | 366 |
| 348 int compareTo(_Entry other) { | 367 int compareTo(_Entry other) { |
| 349 return name.compareTo(other.name); | 368 return name.compareTo(other.name); |
| 350 } | 369 } |
| 351 } | 370 } |
| OLD | NEW |