Index: pkg/dart2js_incremental/lib/server.dart |
diff --git a/pkg/dart2js_incremental/lib/server.dart b/pkg/dart2js_incremental/lib/server.dart |
deleted file mode 100644 |
index d2dc9a2235657671e643385bd5cf9a66c58c09f9..0000000000000000000000000000000000000000 |
--- a/pkg/dart2js_incremental/lib/server.dart |
+++ /dev/null |
@@ -1,301 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library dart2js_incremental.server; |
- |
-import 'dart:io'; |
- |
-import 'dart:async' show |
- Completer, |
- Future, |
- Stream, |
- StreamController, |
- StreamSubscription; |
- |
-import 'dart:convert' show |
- HtmlEscape, |
- JSON, |
- UTF8; |
- |
-import 'src/options.dart'; |
- |
-import 'compiler.dart' show |
- CompilerEvent, |
- IncrementalKind, |
- compile; |
- |
-class Conversation { |
- HttpRequest request; |
- HttpResponse response; |
- |
- static const String PACKAGES_PATH = '/packages'; |
- |
- static const String CONTENT_TYPE = HttpHeaders.CONTENT_TYPE; |
- |
- static Uri documentRoot = Uri.base; |
- |
- static Uri packageRoot = Uri.base.resolve('packages/'); |
- |
- static Map<Uri, Future<String>> generatedFiles = |
- new Map<Uri, Future<String>>(); |
- |
- static Map<Uri, StreamController<String>> updateControllers = |
- new Map<Uri, StreamController<String>>(); |
- |
- Conversation(this.request, this.response); |
- |
- onClosed(_) { |
- if (response.statusCode == HttpStatus.OK) return; |
- print('Request for ${request.uri} ${response.statusCode}'); |
- } |
- |
- Future notFound(Uri uri) { |
- response |
- ..headers.set(CONTENT_TYPE, 'text/html') |
- ..statusCode = HttpStatus.NOT_FOUND |
- ..write(htmlInfo("Not Found", "The file '$uri' could not be found.")); |
- return response.close(); |
- } |
- |
- Future badRequest(String problem) { |
- response |
- ..headers.set(CONTENT_TYPE, 'text/html') |
- ..statusCode = HttpStatus.BAD_REQUEST |
- ..write( |
- htmlInfo("Bad request", "Bad request '${request.uri}': $problem")); |
- return response.close(); |
- } |
- |
- Future handleSocket() async { |
- StreamController<String> controller = updateControllers[request.uri]; |
- if (controller != null) { |
- WebSocket socket = await WebSocketTransformer.upgrade(request); |
- print( |
- "Patches to ${request.uri} will be pushed to " |
- "${request.connectionInfo.remoteAddress.host}:" |
- "${request.connectionInfo.remotePort}."); |
- controller.stream.pipe(socket); |
- } else { |
- response.done |
- .then(onClosed) |
- .catchError(onError); |
- return await notFound(request.uri); |
- } |
- } |
- |
- Future handle() { |
- response.done |
- .then(onClosed) |
- .catchError(onError); |
- |
- Uri uri = request.uri; |
- if (uri.path.endsWith('/')) { |
- uri = uri.resolve('index.html'); |
- } |
- if (uri.path.contains('..') || uri.path.contains('%')) { |
- return notFound(uri); |
- } |
- String path = uri.path; |
- Uri root = documentRoot; |
- if (path.startsWith('${PACKAGES_PATH}/')) { |
- root = packageRoot; |
- path = path.substring(PACKAGES_PATH.length); |
- } |
- |
- Uri resolvedRequest = root.resolve('.$path'); |
- switch (request.method) { |
- case 'GET': |
- return handleGet(resolvedRequest); |
- default: |
- String method = const HtmlEscape().convert(request.method); |
- return badRequest("Unsupported method: '$method'"); |
- } |
- } |
- |
- Future handleGet(Uri uri) async { |
- String path = uri.path; |
- var f = new File.fromUri(uri); |
- if (!await f.exists()) { |
- return await handleNonExistingFile(uri); |
- } else { |
- setContentType(path); |
- } |
- return await f.openRead().pipe(response); |
- } |
- |
- void setContentType(String path) { |
- if (path.endsWith('.html')) { |
- response.headers.set(CONTENT_TYPE, 'text/html'); |
- } else if (path.endsWith('.dart')) { |
- response.headers.set(CONTENT_TYPE, 'application/dart'); |
- } else if (path.endsWith('.js')) { |
- response.headers.set(CONTENT_TYPE, 'application/javascript'); |
- } else if (path.endsWith('.ico')) { |
- response.headers.set(CONTENT_TYPE, 'image/x-icon'); |
- } else if (path.endsWith('.appcache')) { |
- response.headers.set(CONTENT_TYPE, 'text/cache-manifest'); |
- } else if (path.endsWith('.css')) { |
- response.headers.set(CONTENT_TYPE, 'text/css'); |
- } else if (path.endsWith('.png')) { |
- response.headers.set(CONTENT_TYPE, 'image/png'); |
- } |
- } |
- |
- Future handleNonExistingFile(Uri uri) async { |
- String path = uri.path; |
- String generated = await generatedFiles[request.uri]; |
- if (generated != null) { |
- print("Serving ${request.uri} from memory."); |
- setContentType(path); |
- response.write(generated); |
- return await response.close(); |
- } |
- if (path.endsWith('.dart.js')) { |
- Uri dartScript = uri.resolve(path.substring(0, path.length - 3)); |
- if (await new File.fromUri(dartScript).exists()) { |
- return await compileToJavaScript(dartScript); |
- } |
- } |
- return await notFound(request.uri); |
- } |
- |
- compileToJavaScript(Uri dartScript) { |
- Uri outputUri = request.uri; |
- Completer<String> completer = new Completer<String>(); |
- generatedFiles[outputUri] = completer.future; |
- StreamController controller = updateControllers[outputUri]; |
- if (controller != null) { |
- controller.close(); |
- } |
- updateControllers[outputUri] = new StreamController<String>.broadcast(); |
- print("Compiling $dartScript to $outputUri."); |
- StreamSubscription<CompilerEvent> subscription; |
- subscription = compile(dartScript).listen((CompilerEvent event) { |
- subscription.onData( |
- (CompilerEvent event) => onCompilerEvent(completer, event)); |
- if (event.kind != IncrementalKind.FULL) { |
- notFound(request.uri); |
- // TODO(ahe): Do something about this situation. |
- } else { |
- print("Done compiling $dartScript to $outputUri."); |
- completer.complete(event['.js']); |
- setContentType(outputUri.path); |
- response.write(event['.js']); |
- response.close(); |
- } |
- }); |
- } |
- |
- onCompilerEvent(Completer completer, CompilerEvent event) { |
- Uri outputUri = request.uri; |
- print("Got ${event.kind} for $outputUri"); |
- |
- switch (event.kind) { |
- case IncrementalKind.FULL: |
- generatedFiles[outputUri] = new Future.value(event['.js']); |
- break; |
- |
- case IncrementalKind.INCREMENTAL: |
- generatedFiles[outputUri] = completer.future.then( |
- (String full) => '$full\n\n${event.compiler.allUpdates()}'); |
- pushUpdates(event.updates); |
- break; |
- |
- case IncrementalKind.ERROR: |
- generatedFiles.removeKey(outputUri); |
- break; |
- } |
- } |
- |
- void pushUpdates(String updates) { |
- if (updates == null) return; |
- StreamController<String> controller = updateControllers[request.uri]; |
- if (controller == null) return; |
- print("Adding updates to controller"); |
- controller.add(updates); |
- } |
- |
- Future dispatch() async { |
- try { |
- return await WebSocketTransformer.isUpgradeRequest(request) |
- ? handleSocket() |
- : handle(); |
- } catch (e, s) { |
- onError(e, s); |
- } |
- } |
- |
- static Future onRequest(HttpRequest request) async { |
- HttpResponse response = request.response; |
- try { |
- return await new Conversation(request, response).dispatch(); |
- } catch (e, s) { |
- try { |
- onStaticError(e, s); |
- return await response.close(); |
- } catch (e, s) { |
- onStaticError(e, s); |
- } |
- } |
- } |
- |
- Future onError(error, [stack]) async { |
- try { |
- onStaticError(error, stack); |
- return await response.close(); |
- } catch (e, s) { |
- onStaticError(e, s); |
- } |
- } |
- |
- static void onStaticError(error, [stack]) { |
- if (error is HttpException) { |
- print('Error: ${error.message}'); |
- } else { |
- print('Error: ${error}'); |
- } |
- if (stack != null) { |
- print(stack); |
- } |
- } |
- |
- String htmlInfo(String title, String text) { |
- // No script injection, please. |
- title = const HtmlEscape().convert(title); |
- text = const HtmlEscape().convert(text); |
- return """ |
-<!DOCTYPE html> |
-<html lang='en'> |
-<head> |
-<title>$title</title> |
-</head> |
-<body> |
-<h1>$title</h1> |
-<p style='white-space:pre'>$text</p> |
-</body> |
-</html> |
-"""; |
- } |
-} |
- |
-main(List<String> arguments) async { |
- Options options = Options.parse(arguments); |
- if (options == null) { |
- exit(1); |
- } |
- if (!options.arguments.isEmpty) { |
- Conversation.documentRoot = Uri.base.resolve(options.arguments.single); |
- } |
- Conversation.packageRoot = options.packageRoot; |
- String host = options.host; |
- int port = options.port; |
- try { |
- HttpServer server = await HttpServer.bind(host, port); |
- print('HTTP server started on http://$host:${server.port}/'); |
- server.listen(Conversation.onRequest, onError: Conversation.onStaticError); |
- } catch (e) { |
- print("HttpServer.bind error: $e"); |
- exit(1); |
- }; |
-} |