Call RequestContext.close
in Driver.sendResponse
.
This commit is contained in:
parent
28b6f84051
commit
1ed6736257
5 changed files with 28 additions and 10 deletions
|
@ -1,6 +1,10 @@
|
||||||
# 2.0.1
|
# 2.0.1
|
||||||
* Tracked down a bug in `Driver.runPipeline` that allowed fallback
|
* Tracked down a bug in `Driver.runPipeline` that allowed fallback
|
||||||
handlers to run, even after the response was closed.
|
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
|
# 2.0.0
|
||||||
* Angel 2! :angel: :rocket:
|
* Angel 2! :angel: :rocket:
|
||||||
|
|
|
@ -280,12 +280,15 @@ abstract class Driver<
|
||||||
Future sendResponse(Request request, Response response, RequestContext req,
|
Future sendResponse(Request request, Response response, RequestContext req,
|
||||||
ResponseContext res,
|
ResponseContext res,
|
||||||
{bool ignoreFinalizers = false}) {
|
{bool ignoreFinalizers = false}) {
|
||||||
void _cleanup(_) {
|
Future<void> _cleanup(_) {
|
||||||
if (!app.environment.isProduction && app.logger != null) {
|
if (!app.environment.isProduction &&
|
||||||
|
app.logger != null &&
|
||||||
|
req.container.has<Stopwatch>()) {
|
||||||
var sw = req.container.make<Stopwatch>();
|
var sw = req.container.make<Stopwatch>();
|
||||||
app.logger.info(
|
app.logger.info(
|
||||||
"${res.statusCode} ${req.method} ${req.uri} (${sw?.elapsedMilliseconds ?? 'unknown'} ms)");
|
"${res.statusCode} ${req.method} ${req.uri} (${sw?.elapsedMilliseconds ?? 'unknown'} ms)");
|
||||||
}
|
}
|
||||||
|
return req.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res.isBuffered) return res.close().then(_cleanup);
|
if (!res.isBuffered) return res.close().then(_cleanup);
|
||||||
|
|
|
@ -14,6 +14,7 @@ import 'dart:io'
|
||||||
import 'package:angel_container/angel_container.dart';
|
import 'package:angel_container/angel_container.dart';
|
||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
import 'package:http_server/http_server.dart';
|
import 'package:http_server/http_server.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
import 'package:mime/mime.dart';
|
import 'package:mime/mime.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
|
@ -26,8 +27,12 @@ part 'injection.dart';
|
||||||
|
|
||||||
/// A convenience wrapper around an incoming [RawRequest].
|
/// A convenience wrapper around an incoming [RawRequest].
|
||||||
abstract class RequestContext<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;
|
String _acceptHeaderCache, _extensionCache;
|
||||||
bool _acceptsAllCache, _hasParsedBody = false;
|
bool _acceptsAllCache, _hasParsedBody = false, _closed = false;
|
||||||
Map<String, dynamic> _bodyFields, _queryParameters;
|
Map<String, dynamic> _bodyFields, _queryParameters;
|
||||||
List _bodyList;
|
List _bodyList;
|
||||||
Object _bodyObject;
|
Object _bodyObject;
|
||||||
|
@ -271,12 +276,16 @@ abstract class RequestContext<RawRequest> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disposes of all resources.
|
/// Disposes of all resources.
|
||||||
Future close() {
|
@mustCallSuper
|
||||||
|
Future<void> close() async {
|
||||||
|
if (!_closed) {
|
||||||
|
_closed = true;
|
||||||
_acceptsAllCache = null;
|
_acceptsAllCache = null;
|
||||||
_acceptHeaderCache = null;
|
_acceptHeaderCache = null;
|
||||||
serviceParams.clear();
|
serviceParams.clear();
|
||||||
params.clear();
|
params.clear();
|
||||||
return new Future.value();
|
await Future.forEach(shutdownHooks, (hook) => hook());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import 'service.dart';
|
||||||
//final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
//final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||||
|
|
||||||
/// A function that configures an [Angel] server in some way.
|
/// 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.
|
/// A function that asynchronously generates a view from the given path and data.
|
||||||
typedef FutureOr<String> ViewGenerator(String path,
|
typedef FutureOr<String> ViewGenerator(String path,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:io/ansi.dart';
|
import 'package:io/ansi.dart';
|
||||||
|
import '404_hole_test.dart' as hole404;
|
||||||
import 'accepts_test.dart' as accepts;
|
import 'accepts_test.dart' as accepts;
|
||||||
import 'anonymous_service_test.dart' as anonymous_service;
|
import 'anonymous_service_test.dart' as anonymous_service;
|
||||||
import 'body_test.dart' as body;
|
import 'body_test.dart' as body;
|
||||||
|
@ -30,6 +31,7 @@ import 'package:test/test.dart';
|
||||||
/// For running with coverage
|
/// For running with coverage
|
||||||
main() {
|
main() {
|
||||||
print(cyan.wrap('Running tests on ${Platform.version}'));
|
print(cyan.wrap('Running tests on ${Platform.version}'));
|
||||||
|
group('404_hole', hole404.main);
|
||||||
group('accepts', accepts.main);
|
group('accepts', accepts.main);
|
||||||
group('anonymous service', anonymous_service.main);
|
group('anonymous service', anonymous_service.main);
|
||||||
group('body', body.main);
|
group('body', body.main);
|
||||||
|
|
Loading…
Reference in a new issue