Call RequestContext.close in Driver.sendResponse.

This commit is contained in:
Tobe O 2019-05-02 18:46:07 -04:00
parent 28b6f84051
commit 1ed6736257
5 changed files with 28 additions and 10 deletions

View file

@ -1,6 +1,10 @@
# 2.0.1
* Tracked down a bug in `Driver.runPipeline` that allowed fallback
handlers to run, even after the response was closed.
* Add `RequestContext.shutdownHooks`.
* Call `RequestContext.close` in `Driver.sendResponse`.
* AngelConfigurer is now `FutureOr<void>`, instead of just `FutureOr`.
* Use a `Container.has<Stopwatch>` check in `Driver.sendResponse`.
# 2.0.0
* Angel 2! :angel: :rocket:

View file

@ -280,12 +280,15 @@ abstract class Driver<
Future sendResponse(Request request, Response response, RequestContext req,
ResponseContext res,
{bool ignoreFinalizers = false}) {
void _cleanup(_) {
if (!app.environment.isProduction && app.logger != null) {
Future<void> _cleanup(_) {
if (!app.environment.isProduction &&
app.logger != null &&
req.container.has<Stopwatch>()) {
var sw = req.container.make<Stopwatch>();
app.logger.info(
"${res.statusCode} ${req.method} ${req.uri} (${sw?.elapsedMilliseconds ?? 'unknown'} ms)");
}
return req.close();
}
if (!res.isBuffered) return res.close().then(_cleanup);

View file

@ -14,6 +14,7 @@ import 'dart:io'
import 'package:angel_container/angel_container.dart';
import 'package:http_parser/http_parser.dart';
import 'package:http_server/http_server.dart';
import 'package:meta/meta.dart';
import 'package:mime/mime.dart';
import 'package:path/path.dart' as p;
@ -26,8 +27,12 @@ part 'injection.dart';
/// A convenience wrapper around an incoming [RawRequest].
abstract class RequestContext<RawRequest> {
/// Similar to [Angel.shutdownHooks], allows for logic to be executed
/// when a [RequestContext] is done being processed.
final List<FutureOr<void> Function()> shutdownHooks = [];
String _acceptHeaderCache, _extensionCache;
bool _acceptsAllCache, _hasParsedBody = false;
bool _acceptsAllCache, _hasParsedBody = false, _closed = false;
Map<String, dynamic> _bodyFields, _queryParameters;
List _bodyList;
Object _bodyObject;
@ -271,12 +276,16 @@ abstract class RequestContext<RawRequest> {
}
/// Disposes of all resources.
Future close() {
_acceptsAllCache = null;
_acceptHeaderCache = null;
serviceParams.clear();
params.clear();
return new Future.value();
@mustCallSuper
Future<void> close() async {
if (!_closed) {
_closed = true;
_acceptsAllCache = null;
_acceptHeaderCache = null;
serviceParams.clear();
params.clear();
await Future.forEach(shutdownHooks, (hook) => hook());
}
}
}

View file

@ -22,7 +22,7 @@ import 'service.dart';
//final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
/// A function that configures an [Angel] server in some way.
typedef FutureOr AngelConfigurer(Angel app);
typedef FutureOr<void> AngelConfigurer(Angel app);
/// A function that asynchronously generates a view from the given path and data.
typedef FutureOr<String> ViewGenerator(String path,

View file

@ -1,5 +1,6 @@
import 'dart:io';
import 'package:io/ansi.dart';
import '404_hole_test.dart' as hole404;
import 'accepts_test.dart' as accepts;
import 'anonymous_service_test.dart' as anonymous_service;
import 'body_test.dart' as body;
@ -30,6 +31,7 @@ import 'package:test/test.dart';
/// For running with coverage
main() {
print(cyan.wrap('Running tests on ${Platform.version}'));
group('404_hole', hole404.main);
group('accepts', accepts.main);
group('anonymous service', anonymous_service.main);
group('body', body.main);