blob: b35250d6c6301f8f8f951eaa73f18abd67e7dcbb [file] [log] [blame]
// Copyright (c) 2016, 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:convert' show jsonDecode, utf8;
import 'dart:isolate' show RawReceivePort;
import 'dart:io';
import 'package:front_end/src/fasta/crash.dart' show defaultServerAddress;
badRequest(HttpRequest request, int status, String message) {
request.response.statusCode = status;
request.response.write('''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>$message</title>
</head>
<body>
<h1>$message</h1>
</body>
</html>
''');
request.response.close().catchError((e, s) {
print("Request error: $e.");
});
print("${request.uri}: $message");
}
collectLog(DateTime time, HttpRequest request) async {
String json = await request.cast<List<int>>().transform(utf8.decoder).join();
var data;
try {
data = jsonDecode(json);
} on FormatException catch (e) {
print(e);
return badRequest(
request, HttpStatus.badRequest, "Malformed JSON data: ${e.message}.");
}
if (data is! Map) {
return badRequest(
request, HttpStatus.badRequest, "Malformed JSON data: not a map.");
}
if (data["type"] != "crash") {
return badRequest(request, HttpStatus.badRequest,
"Malformed JSON data: type should be 'crash'.");
}
await request.response.close();
String year = "${time.year}".padLeft(4, "0");
String month = "${time.month}".padLeft(2, "0");
String day = "${time.day}".padLeft(2, "0");
String us = "${time.microsecondsSinceEpoch}".padLeft(19, '0');
Uri uri = Uri.base
.resolve("crash_logs/${data['client']}/$year-$month-$day/$us.log");
File file = new File.fromUri(uri);
await file.parent.create(recursive: true);
await file.writeAsString(json);
print("Wrote ${uri.toFilePath()}");
String type = data["type"];
String text = data["uri"];
uri = text == null ? null : Uri.parse(text);
int charOffset = data["offset"];
var error = data["error"];
text = data["trace"];
StackTrace trace = text == null ? null : new StackTrace.fromString(text);
String client = data["client"];
print("""
date: ${time}
type: $type
client: $client
uri: $uri
offset: $charOffset
error:
$error
trace:
$trace
""");
}
main(List<String> arguments) async {
RawReceivePort keepAlive = new RawReceivePort();
Uri uri;
if (arguments.length == 1) {
uri = Uri.base.resolve(arguments.single);
} else if (arguments.length == 0) {
uri = Uri.parse(defaultServerAddress);
} else {
throw "Unexpected arguments: ${arguments.join(' ')}.";
}
int port = uri.hasPort ? uri.port : 0;
var host = uri.host.isEmpty ? InternetAddress.loopbackIPv4 : uri.host;
HttpServer server = await HttpServer.bind(host, port);
print("Listening on http://${server.address.host}:${server.port}/");
await for (HttpRequest request in server) {
if (request.method != "POST") {
badRequest(request, HttpStatus.methodNotAllowed, "Not allowed.");
continue;
}
if (request.uri.path != "/") {
badRequest(request, HttpStatus.notFound, "Not found.");
continue;
}
collectLog(new DateTime.now(), request);
}
keepAlive.close();
}