diff --git a/.idea/runConfigurations/handle_error_dart.xml b/.idea/runConfigurations/handle_error_dart.xml new file mode 100644 index 00000000..5df40720 --- /dev/null +++ b/.idea/runConfigurations/handle_error_dart.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/view_dart.xml b/.idea/runConfigurations/view_dart.xml new file mode 100644 index 00000000..de62a90c --- /dev/null +++ b/.idea/runConfigurations/view_dart.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index d82f86ce..8b2f7e8b 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,8 +2,17 @@ + + + + - + + + + + + @@ -29,7 +38,7 @@ - + @@ -38,26 +47,17 @@ - - + + - - + + - - - - - - - - - - - + + @@ -65,14 +65,11 @@ - - + + - - - - - + + @@ -81,28 +78,7 @@ - - - - - - - - - - - - - - - - - - - - - - + @@ -110,20 +86,82 @@ - - + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -140,7 +178,6 @@ - getV zone zone.run aaa @@ -170,6 +207,7 @@ MID beforeIndex read( + new Trac modify @@ -199,9 +237,7 @@ var body = await getBody(rs); = - = { - C:\Users\thosa\Source\Angel\framework\lib @@ -224,9 +260,6 @@ @@ -288,8 +324,8 @@ - @@ -313,6 +349,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -371,7 +432,7 @@ - + @@ -641,14 +704,8 @@ - - - - 1506092186428 - 1506275793202 @@ -986,7 +1043,14 @@ - @@ -1022,7 +1086,7 @@ - @@ -1034,7 +1098,8 @@ - + + @@ -1056,24 +1121,24 @@ - + - - + - + + - + @@ -1084,7 +1149,6 @@ @@ -1117,30 +1182,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -1206,9 +1247,6 @@ - - - @@ -1216,9 +1254,6 @@ - - - @@ -1233,9 +1268,6 @@ - - - @@ -1246,13 +1278,6 @@ - - - - - - - @@ -1264,9 +1289,6 @@ - - - @@ -1274,9 +1296,6 @@ - - - @@ -1287,23 +1306,10 @@ - - - - - - - - - - - - - @@ -1311,9 +1317,6 @@ - - - @@ -1331,23 +1334,6 @@ - - - - - - - - - - - - - - - - - @@ -1355,16 +1341,6 @@ - - - - - - - - - - @@ -1389,16 +1365,6 @@ - - - - - - - - - - @@ -1410,9 +1376,6 @@ - - - @@ -1420,15 +1383,12 @@ - - - - + @@ -1438,25 +1398,11 @@ - + - - - - - - - - - - - - - - @@ -1464,10 +1410,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1476,39 +1599,8 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/CHANGELOG.md b/CHANGELOG.md index d0752ddd..f900158d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.1.4+2 +* Fix a bug that prevented proper rendering of views. +* Fixed a hidden bug that prevents error handling when a +stack trace is `null`. +* Fixed a bug that prevented proper handling of `content-encoding`. + # 1.1.4+1 * Ensure correct error handling when `useZone` is `false`. diff --git a/example/handle_error.dart b/example/handle_error.dart new file mode 100644 index 00000000..5b5b2d50 --- /dev/null +++ b/example/handle_error.dart @@ -0,0 +1,18 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:logging/logging.dart'; + +main() async { + var app = new Angel() + ..lazyParseBodies = true + ..logger = (new Logger('angel')..onRecord.listen(print)) + ..encoders.addAll({'gzip': gzip.encoder}); + + app.use(() => new Future.error('Throwing just because I feel like!')); + + var http = new AngelHttp(app); + var server = await http.startServer('127.0.0.1', 3000); + var url = 'http://${server.address.address}:${server.port}'; + print('Listening at $url'); +} diff --git a/example/view.dart b/example/view.dart new file mode 100644 index 00000000..72cd14f9 --- /dev/null +++ b/example/view.dart @@ -0,0 +1,16 @@ +import 'package:angel_framework/angel_framework.dart'; + +main() async { + var app = new Angel(); + + app.viewGenerator = (name, [data]) async => + 'View generator invoked with name $name and data: $data'; + + // Index route. Returns JSON. + app.get('/', (ResponseContext res) => res.render('index', {'foo': 'bar'})); + + var http = new AngelHttp(app); + var server = await http.startServer('127.0.0.1', 3000); + var url = 'http://${server.address.address}:${server.port}'; + print('Listening at $url'); +} diff --git a/lib/src/core/response_context.dart b/lib/src/core/response_context.dart index 4851c21b..1f3e8ab2 100644 --- a/lib/src/core/response_context.dart +++ b/lib/src/core/response_context.dart @@ -200,10 +200,11 @@ abstract class ResponseContext implements StreamSink>, StringSink { /// Renders a view to the response stream, and closes the response. Future render(String view, [Map data]) { if (!isOpen) throw closed(); - write(app.viewGenerator(view, data)); - headers['content-type'] = ContentType.HTML.toString(); - end(); - return new Future.value(); + return app.viewGenerator(view, data).then((content) { + write(content); + headers['content-type'] = ContentType.HTML.toString(); + end(); + }); } /// Redirects to user to the given URL. diff --git a/lib/src/http/angel_http.dart b/lib/src/http/angel_http.dart index 64e0e0f9..0f3a8945 100644 --- a/lib/src/http/angel_http.dart +++ b/lib/src/http/angel_http.dart @@ -179,7 +179,7 @@ class AngelHttp { parent.print(zone, line); }, handleUncaughtError: (self, parent, zone, error, stackTrace) { - var trace = new Trace.from(stackTrace).terse; + var trace = new Trace.from(stackTrace ?? StackTrace.current).terse; return new Future(() { AngelHttpException e; @@ -199,7 +199,7 @@ class AngelHttp { return handleAngelHttpException(e, trace, req, res, request); }).catchError((e, st) { - var trace = new Trace.from(st).terse; + var trace = new Trace.from(st ?? StackTrace.current).terse; request.response.close(); // Ideally, we won't be in a position where an absolutely fatal error occurs, // but if so, we'll need to log it. diff --git a/lib/src/http/http_response_context.dart b/lib/src/http/http_response_context.dart index 743fa4fd..56f3b324 100644 --- a/lib/src/http/http_response_context.dart +++ b/lib/src/http/http_response_context.dart @@ -67,32 +67,37 @@ class HttpResponseContextImpl extends ResponseContext { Stream> output = stream; if (encoders.isNotEmpty && correspondingRequest != null) { - var allowedEncodings = - (correspondingRequest.headers[HttpHeaders.ACCEPT_ENCODING] ?? []) - .map((str) { + var allowedEncodings = correspondingRequest.headers + .value(HttpHeaders.ACCEPT_ENCODING) + ?.split(',') + ?.map((s) => s.trim()) + ?.where((s) => s.isNotEmpty) + ?.map((str) { // Ignore quality specifications in accept-encoding // ex. gzip;q=0.8 if (!str.contains(';')) return str; return str.split(';')[0]; }); - for (var encodingName in allowedEncodings) { - Converter, List> encoder; - String key = encodingName; + if (allowedEncodings != null) { + for (var encodingName in allowedEncodings) { + Converter, List> encoder; + String key = encodingName; - if (encoders.containsKey(encodingName)) - encoder = encoders[encodingName]; - else if (encodingName == '*') { - encoder = encoders[key = encoders.keys.first]; - } - - if (encoder != null) { - if (firstStream) { - io.headers.set(HttpHeaders.CONTENT_ENCODING, key); + if (encoders.containsKey(encodingName)) + encoder = encoders[encodingName]; + else if (encodingName == '*') { + encoder = encoders[key = encoders.keys.first]; } - output = encoders[key].bind(output); - break; + if (encoder != null) { + if (firstStream) { + io.headers.set(HttpHeaders.CONTENT_ENCODING, key); + } + + output = encoders[key].bind(output); + break; + } } } } @@ -111,19 +116,19 @@ class HttpResponseContextImpl extends ResponseContext { } @override - Future close() { + Future close() { if (_useStream) { try { - io.close(); - } catch(_) { + io.close(); + } catch (_) { // This only seems to occur on `MockHttpRequest`, but // this try/catch prevents a crash. } } _isClosed = true; - super.close(); + super.close(); _useStream = false; return new Future.value(); } -} \ No newline at end of file +} diff --git a/performance/hello/main.dart b/performance/hello/main.dart index ea5eaaf1..6127e30c 100644 --- a/performance/hello/main.dart +++ b/performance/hello/main.dart @@ -25,15 +25,7 @@ void start(int id) { var app = new Angel()..lazyParseBodies = true; var http = new AngelHttp.custom(app, startShared, useZone: false); - app.get('/', (req, ResponseContext res) { - res.write('Hello, world!'); - //res.willCloseItself = true; - //res.io - // ..write('Hello, world!') - // ..close(); - return false; - }); - + app.get('/', (ResponseContext res) => res.write('Hello, world!')); var oldHandler = app.errorHandler; app.errorHandler = (e, req, res) { @@ -43,7 +35,7 @@ void start(int id) { }; http.startServer('127.0.0.1', 3000).then((server) { - print( - 'Instance #$id listening at http://${server.address.address}:${server.port}'); + print('Instance #$id listening at http://${server.address.address}:${server + .port}'); }); } diff --git a/pubspec.yaml b/pubspec.yaml index 52612af4..1bdec0f0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_framework -version: 1.1.4+1 +version: 1.1.4+2 description: A high-powered HTTP server with DI, routing and more. author: Tobe O homepage: https://github.com/angel-dart/angel_framework