blob: 51b958c7bb0afa191378081a1db3c0f5c8695367 [file] [log] [blame]
// Copyright (c) 2014, 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.
import 'dart:io';
import 'package:http_server/http_server.dart' as http_server;
import 'package:route/server.dart';
import 'package:path/path.dart';
import 'package:http_server/http_server.dart';
/*
* This program serves a visualization of a JavaScript source map file generated
* by dart2js or pub.
*
* Usage: dart source_map_viewer.dart <path to map file>.
*
* The default system browser is started and pointed to the viewer if
* available.
*/
Uri sourceMapFile;
void main(List<String> args) {
if (args.length != 1) {
print('One argument expected; the source map file.');
exit(-1);
return;
}
File mapFile = new File(args[0]);
if (!mapFile.existsSync()) {
print('Map file not found at ${args[0]}');
exit(-2);
return;
}
sourceMapFile = toUri(mapFile.path);
startServer();
}
// Sends the content of the file requested in the path parameter.
void handleFile(HttpRequest request) {
String path = request.uri.queryParameters["path"];
if (path == null) {
request.response.close();
return;
}
Uri uri = sourceMapFile.resolve(path);
new File.fromUri(uri)
.openRead()
.cast<List<int>>()
.pipe(request.response)
.catchError((e) {
print("Error: $e");
request.response.close();
});
}
// Sends back the name of the source map file.
void handleSourceMapFile(HttpRequest request) {
request.response.write(basename(sourceMapFile.path));
request.response.close();
}
// Starts an HttpServer rooted in [dir] with two special routes, /file and /map.
//
// /file takes a parameter [path] and serves the content of the specified file
// in path relative to [dir]
//
// /map serves the name of the map file such that its content can be requested
// with a /file request as above.
void startServer() {
String root = fromUri(Platform.script.resolve('../build/web/'));
Directory directory = new Directory(root);
if (!directory.existsSync()) {
print("Directory '$root' does not exist. "
"Run 'pub build' to generate the output.");
exit(-1);
}
// Use port 0 to get an ephemeral port.
int port = 0;
HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, port).then((server) {
port = server.port;
print("Source mapping server is running on "
"'http://${server.address.address}:$port/'");
Router router = new Router(server)
..serve('/file').listen(handleFile)
..serve('/map').listen(handleSourceMapFile);
// Set up default handler. This will serve files from our 'build'
// directory. Disable jail root, as packages are local symlinks.
VirtualDirectory virDir = new http_server.VirtualDirectory(root)
..jailRoot = false
..allowDirectoryListing = true;
virDir.directoryHandler = (dir, request) {
// Redirect directory requests to index.html files.
Uri indexUri = new Uri.file(dir.path).resolve('display.html');
virDir.serveFile(new File(indexUri.toFilePath()), request);
};
// Add an error page handler.
virDir.errorPageHandler = (HttpRequest request) {
print("Resource not found: ${request.uri.path}");
request.response.statusCode = HttpStatus.NOT_FOUND;
request.response.close();
};
// Serve everything not routed elsewhere through the virtual directory.
virDir.serve(router.defaultStream);
// Start the system' default browser
startBrowser('http://${server.address.address}:$port/');
});
}
startBrowser(String url) {
String command;
if (Platform.isWindows) {
command = 'cmd.exe /C start';
} else if (Platform.isMacOS) {
command = 'open';
} else {
String xdg = '/usr/bin/xdg-open';
if (new File(xdg).existsSync()) {
command = xdg;
} else {
command = '/usr/bin/google-chrome';
}
}
print('Starting browser: ${command} ${url}');
Process.run(command, ['$url']).then((ProcessResult result) {
if (result.exitCode != 0) {
print(result.stderr);
}
});
}