| // 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(); |
| } |