Fix 404 hole
This commit is contained in:
parent
23bc65e257
commit
28b6f84051
5 changed files with 125 additions and 3 deletions
|
@ -1,3 +1,7 @@
|
|||
# 2.0.1
|
||||
* Tracked down a bug in `Driver.runPipeline` that allowed fallback
|
||||
handlers to run, even after the response was closed.
|
||||
|
||||
# 2.0.0
|
||||
* Angel 2! :angel: :rocket:
|
||||
|
||||
|
|
|
@ -354,12 +354,16 @@ abstract class Driver<
|
|||
RequestContextType req,
|
||||
ResponseContextType res,
|
||||
Angel app) async {
|
||||
var broken = false;
|
||||
while (it.moveNext()) {
|
||||
var current = it.current.handlers.iterator;
|
||||
|
||||
while (current.moveNext()) {
|
||||
while (!broken && current.moveNext()) {
|
||||
var result = await app.executeHandler(current.current, req, res);
|
||||
if (result != true) break;
|
||||
if (result != true) {
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,6 @@ dependencies:
|
|||
tuple: ^1.0.0
|
||||
uuid: ^2.0.0-rc.1
|
||||
dev_dependencies:
|
||||
http: ^0.11.3
|
||||
http: ^0.12.0
|
||||
io: ^0.3.0
|
||||
test: ^1.0.0
|
||||
|
|
78
test/404_hole_test.dart
Normal file
78
test/404_hole_test.dart
Normal file
|
@ -0,0 +1,78 @@
|
|||
import 'dart:async';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_framework/http.dart';
|
||||
import 'package:charcode/ascii.dart';
|
||||
import 'package:http/io_client.dart' as http;
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'pretty_log.dart';
|
||||
|
||||
void main() {
|
||||
http.IOClient client;
|
||||
AngelHttp driver;
|
||||
Logger logger;
|
||||
|
||||
setUp(() async {
|
||||
client = http.IOClient();
|
||||
hierarchicalLoggingEnabled = true;
|
||||
|
||||
logger = Logger.detached('404_hole')
|
||||
..level = Level.ALL
|
||||
..onRecord.listen(prettyLog);
|
||||
|
||||
var app = Angel(logger: logger);
|
||||
|
||||
app.fallback(hello);
|
||||
app.fallback(throw404);
|
||||
|
||||
// The error handler in the boilerplate.
|
||||
var oldErrorHandler = app.errorHandler;
|
||||
app.errorHandler = (e, req, res) async {
|
||||
if (req.accepts('text/html', strict: true)) {
|
||||
if (e.statusCode == 404 && req.accepts('text/html', strict: true)) {
|
||||
await res
|
||||
.render('error', {'message': 'No file exists at ${req.uri}.'});
|
||||
} else {
|
||||
await res.render('error', {'message': e.message});
|
||||
}
|
||||
} else {
|
||||
return await oldErrorHandler(e, req, res);
|
||||
}
|
||||
};
|
||||
|
||||
driver = AngelHttp(app);
|
||||
await driver.startServer();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
logger.clearListeners();
|
||||
client.close();
|
||||
scheduleMicrotask(driver.close);
|
||||
});
|
||||
|
||||
test('does not continue processing after streaming', () async {
|
||||
var url = driver.uri.replace(path: '/hey');
|
||||
for (int i = 0; i < 100; i++) {
|
||||
var r = await client.get(url);
|
||||
print('#$i: ${r.statusCode}: ${r.body}');
|
||||
expect(r.statusCode, 200);
|
||||
expect(r.body, 'Hello!');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Simulate angel_static
|
||||
Future<void> hello(RequestContext req, ResponseContext res) {
|
||||
if (req.path == 'hey') {
|
||||
var bytes = [$H, $e, $l, $l, $o, $exclamation];
|
||||
var s = Stream<List<int>>.fromIterable([bytes]);
|
||||
return s.pipe(res);
|
||||
} else {
|
||||
return Future.value(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// 404
|
||||
void throw404(RequestContext req, ResponseContext res) {
|
||||
throw AngelHttpException.notFound();
|
||||
}
|
36
test/pretty_log.dart
Normal file
36
test/pretty_log.dart
Normal file
|
@ -0,0 +1,36 @@
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:io/ansi.dart';
|
||||
|
||||
/// Prints the contents of a [LogRecord] with pretty colors.
|
||||
void prettyLog(LogRecord record) {
|
||||
var code = chooseLogColor(record.level);
|
||||
|
||||
if (record.error == null) print(code.wrap(record.toString()));
|
||||
|
||||
if (record.error != null) {
|
||||
var err = record.error;
|
||||
print(code.wrap(record.toString() + '\n'));
|
||||
print(code.wrap(err.toString()));
|
||||
|
||||
if (record.stackTrace != null) {
|
||||
print(code.wrap(record.stackTrace.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Chooses a color based on the logger [level].
|
||||
AnsiCode chooseLogColor(Level level) {
|
||||
if (level == Level.SHOUT)
|
||||
return backgroundRed;
|
||||
else if (level == Level.SEVERE)
|
||||
return red;
|
||||
else if (level == Level.WARNING)
|
||||
return yellow;
|
||||
else if (level == Level.INFO)
|
||||
return cyan;
|
||||
else if (level == Level.CONFIG ||
|
||||
level == Level.FINE ||
|
||||
level == Level.FINER ||
|
||||
level == Level.FINEST) return lightGray;
|
||||
return resetAll;
|
||||
}
|
Loading…
Reference in a new issue