Force all handlers to (req, res) { ... }
This commit is contained in:
parent
b9127251a6
commit
3c37747f07
12 changed files with 74 additions and 61 deletions
|
@ -34,4 +34,9 @@ as well as `query`.
|
|||
* Removed a dependency on `package:pool`, which also meant removing `AngelHttp.throttle`.
|
||||
* Remove the `RequestMiddleware` typedef; from now on, one should use `ResponseContext.end`
|
||||
exclusively to close responses.
|
||||
* `waterfall` will now only accept `RequestHandler`.
|
||||
* `waterfall` will now only accept `RequestHandler`.
|
||||
* `Routable`, and all of its subclasses, now extend `Router<RequestHandler>`, and therefore only
|
||||
take routes in the form of `FutureOr myFunc(RequestContext, ResponseContext res)`.
|
||||
* `@Middleware` now takes an `Iterable` of `RequestHandler`s.
|
||||
* `@Expose.path` now *must* be a `String`, not just any `Pattern`.
|
||||
* `@Expose.middleware` now takes `Iterable<RequestHandler>`, instead of just `List`.
|
|
@ -32,15 +32,16 @@ serverMain(_) async {
|
|||
var app = new Angel(reflector: MirrorsReflector());
|
||||
var http = new AngelHttp.custom(app, startShared); // Run a cluster
|
||||
|
||||
app.get('/', {
|
||||
"foo": "bar",
|
||||
"one": [2, "three"],
|
||||
"bar": {"baz": "quux"}
|
||||
app.get('/', (req, res) {
|
||||
res.serialize({
|
||||
"foo": "bar",
|
||||
"one": [2, "three"],
|
||||
"bar": {"baz": "quux"}
|
||||
});
|
||||
});
|
||||
|
||||
// Performance tuning
|
||||
app
|
||||
..serializer = json.encode;
|
||||
app..serializer = json.encode;
|
||||
|
||||
app.errorHandler = (e, req, res) {
|
||||
print(e.message ?? e.error ?? e);
|
||||
|
|
|
@ -8,7 +8,7 @@ main() async {
|
|||
'View generator invoked with name $name and data: $data';
|
||||
|
||||
// Index route. Returns JSON.
|
||||
app.get('/', (ResponseContext res) => res.render('index', {'foo': 'bar'}));
|
||||
app.get('/', (req, res) => res.render('index', {'foo': 'bar'}));
|
||||
|
||||
var http = new AngelHttp(app);
|
||||
var server = await http.startServer('127.0.0.1', 3000);
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'dart:async';
|
|||
import '../util.dart';
|
||||
import 'request_context.dart';
|
||||
import 'response_context.dart';
|
||||
import 'routable.dart';
|
||||
import 'metadata.dart';
|
||||
import 'service.dart';
|
||||
|
||||
|
@ -119,7 +120,7 @@ class HookedService extends Service {
|
|||
applyListeners(inner.remove, afterRemoved, true);
|
||||
}
|
||||
|
||||
List get bootstrappers => new List.from(super.bootstrappers)
|
||||
List<RequestHandler> get bootstrappers => new List<RequestHandler>.from(super.bootstrappers)
|
||||
..add((RequestContext req, ResponseContext res) {
|
||||
req.serviceParams
|
||||
..['__requestctx'] = req
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
library angel_framework.http.metadata;
|
||||
|
||||
import 'hooked_service.dart' show HookedServiceEventListener;
|
||||
import 'package:angel_http_exception/angel_http_exception.dart';
|
||||
|
||||
import 'hooked_service.dart' show HookedServiceEventListener;
|
||||
import 'request_context.dart';
|
||||
import 'routable.dart';
|
||||
|
||||
/// Annotation to map middleware onto a handler.
|
||||
class Middleware {
|
||||
final List handlers;
|
||||
final Iterable<RequestHandler> handlers;
|
||||
|
||||
const Middleware(this.handlers);
|
||||
}
|
||||
|
@ -22,8 +24,8 @@ class Hooks {
|
|||
/// Exposes a [Controller] to the Internet.
|
||||
class Expose {
|
||||
final String method;
|
||||
final Pattern path;
|
||||
final List middleware;
|
||||
final String path;
|
||||
final Iterable<RequestHandler> middleware;
|
||||
final String as;
|
||||
final List<String> allowNull;
|
||||
|
||||
|
@ -91,7 +93,8 @@ class Parameter {
|
|||
return req.headers.value(header) ?? defaultValue;
|
||||
if (session?.isNotEmpty == true)
|
||||
return req.session[session] ?? defaultValue;
|
||||
if (query?.isNotEmpty == true) return req.uri.queryParameters[query] ?? defaultValue;
|
||||
if (query?.isNotEmpty == true)
|
||||
return req.uri.queryParameters[query] ?? defaultValue;
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ RequestHandler waterfall(Iterable<RequestHandler> handlers) {
|
|||
}
|
||||
|
||||
/// A routable server that can handle dynamic requests.
|
||||
class Routable extends Router {
|
||||
class Routable extends Router<RequestHandler> {
|
||||
final Map<Pattern, Service> _services = {};
|
||||
final Map configuration = {};
|
||||
|
||||
|
@ -71,16 +71,17 @@ class Routable extends Router {
|
|||
_services[path.toString().replaceAll(_straySlashes, '')];
|
||||
|
||||
@override
|
||||
Route addRoute(String method, String path, Object handler,
|
||||
{Iterable middleware: const []}) {
|
||||
final List handlers = [];
|
||||
Route<RequestHandler> addRoute(
|
||||
String method, String path, RequestHandler handler,
|
||||
{Iterable<RequestHandler> middleware: const <RequestHandler>[]}) {
|
||||
final handlers = <RequestHandler>[];
|
||||
// Merge @Middleware declaration, if any
|
||||
Middleware middlewareDeclaration = getAnnotation(handler, Middleware);
|
||||
if (middlewareDeclaration != null) {
|
||||
handlers.addAll(middlewareDeclaration.handlers);
|
||||
}
|
||||
|
||||
final List handlerSequence = [];
|
||||
final handlerSequence = <RequestHandler>[];
|
||||
handlerSequence.addAll(middleware ?? []);
|
||||
handlerSequence.addAll(handlers);
|
||||
|
||||
|
@ -94,8 +95,8 @@ class Routable extends Router {
|
|||
/// an [Angel] instance.
|
||||
///
|
||||
/// Returns either a [Route] or a [Service] (if one was mounted).
|
||||
use(path, [Router router, String namespace = null]) {
|
||||
Router _router = router;
|
||||
use(path, [Router<RequestHandler> router, String namespace = null]) {
|
||||
Router<RequestHandler> _router = router;
|
||||
Service service;
|
||||
|
||||
// If we need to hook this service, do it here. It has to be first, or
|
||||
|
|
|
@ -162,8 +162,8 @@ class Angel extends Routable {
|
|||
};
|
||||
|
||||
@override
|
||||
Route addRoute(String method, Pattern path, Object handler,
|
||||
{List middleware: const []}) {
|
||||
Route addRoute(String method, String path, Object handler,
|
||||
{Iterable middleware: const []}) {
|
||||
if (_flattened != null) {
|
||||
logger?.warning(
|
||||
'WARNING: You added a route ($method $path) to the router, after it had been optimized.');
|
||||
|
|
|
@ -58,7 +58,7 @@ class Service extends Routable {
|
|||
];
|
||||
|
||||
/// Handlers that must run to ensure this service's functionality.
|
||||
List get bootstrappers => [];
|
||||
List<RequestHandler> get bootstrappers => [];
|
||||
|
||||
/// The [Angel] app powering this service.
|
||||
Angel app;
|
||||
|
@ -150,8 +150,9 @@ class Service extends Routable {
|
|||
_addRoutesInner(service ?? this, bootstrappers);
|
||||
}
|
||||
|
||||
void _addRoutesInner(Service service, List handlers) {
|
||||
Map restProvider = {'provider': Providers.rest};
|
||||
void _addRoutesInner(Service service, Iterable<RequestHandler> handlerss) {
|
||||
var restProvider = {'provider': Providers.rest};
|
||||
var handlers = new List<RequestHandler>.from(handlerss);
|
||||
|
||||
// Add global middleware if declared on the instance itself
|
||||
Middleware before = getAnnotation(service, Middleware);
|
||||
|
@ -168,7 +169,7 @@ class Service extends Routable {
|
|||
]));
|
||||
});
|
||||
},
|
||||
middleware: []
|
||||
middleware: <RequestHandler>[]
|
||||
..addAll(handlers)
|
||||
..addAll((indexMiddleware == null) ? [] : indexMiddleware.handlers));
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class Controller {
|
|||
}
|
||||
|
||||
void Function(Symbol, MethodMirror) _routeBuilder(
|
||||
InstanceMirror instanceMirror, Routable routable, List handlers) {
|
||||
InstanceMirror instanceMirror, Routable routable, Iterable<RequestHandler> handlers) {
|
||||
return (Symbol methodName, MethodMirror method) {
|
||||
if (method.isRegularMethod &&
|
||||
methodName != #toString &&
|
||||
|
@ -76,7 +76,7 @@ class Controller {
|
|||
|
||||
var reflectedMethod =
|
||||
instanceMirror.getField(methodName).reflectee as Function;
|
||||
var middleware = []..addAll(handlers)..addAll(exposeDecl.middleware);
|
||||
var middleware = <RequestHandler>[]..addAll(handlers)..addAll(exposeDecl.middleware);
|
||||
String name = exposeDecl.as?.isNotEmpty == true
|
||||
? exposeDecl.as
|
||||
: MirrorSystem.getName(methodName);
|
||||
|
|
|
@ -13,8 +13,8 @@ main() {
|
|||
|
||||
setUp(() async {
|
||||
app = new Angel(reflector: MirrorsReflector())
|
||||
..post('/foo', () => {'hello': 'world'})
|
||||
..all('*', () => throw new AngelHttpException.notFound());
|
||||
..post('/foo', (req, res) => res.serialize({'hello': 'world'}))
|
||||
..all('*', (req, res) => throw new AngelHttpException.notFound());
|
||||
client = new http.Client();
|
||||
|
||||
server = await new AngelHttp(app).startServer();
|
||||
|
|
|
@ -1,25 +1,37 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:angel_container/mirrors.dart';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:io/ansi.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'common.dart';
|
||||
|
||||
@Middleware(const ['interceptor'])
|
||||
@Middleware([interceptor])
|
||||
testMiddlewareMetadata(RequestContext req, ResponseContext res) async {
|
||||
return "This should not be shown.";
|
||||
}
|
||||
|
||||
@Middleware(const ['intercept_service'])
|
||||
@Middleware([interceptService])
|
||||
class QueryService extends Service {
|
||||
@override
|
||||
@Middleware(const ['interceptor'])
|
||||
@Middleware([interceptor])
|
||||
read(id, [Map params]) async => params;
|
||||
}
|
||||
|
||||
void interceptor(RequestContext req, ResponseContext res) {
|
||||
res
|
||||
..write('Middleware')
|
||||
..end();
|
||||
}
|
||||
|
||||
void interceptService(RequestContext req, ResponseContext res) {
|
||||
res.write("Service with ");
|
||||
}
|
||||
|
||||
main() {
|
||||
Angel app;
|
||||
Angel nested;
|
||||
|
@ -44,16 +56,6 @@ main() {
|
|||
});
|
||||
});
|
||||
|
||||
app.requestMiddleware
|
||||
..['interceptor'] = (req, res) async {
|
||||
res.write('Middleware');
|
||||
return false;
|
||||
}
|
||||
..['intercept_service'] = (RequestContext req, res) async {
|
||||
res.write("Service with ");
|
||||
return true;
|
||||
};
|
||||
|
||||
todos.get('/action/:action', (req, res) => res.json(req.params));
|
||||
|
||||
Route ted;
|
||||
|
@ -67,8 +69,7 @@ main() {
|
|||
|
||||
app.use('/nes', nested);
|
||||
app.get('/meta', testMiddlewareMetadata);
|
||||
app.get('/intercepted', 'This should not be shown',
|
||||
middleware: ['interceptor']);
|
||||
app.get('/intercepted', 'This should not be shown', middleware: ['interceptor']);
|
||||
app.get('/hello', 'world');
|
||||
app.get('/name/:first/last/:last', (req, res) => req.params);
|
||||
app.post('/lambda', (RequestContext req, res) => req.parseBody());
|
||||
|
@ -90,16 +91,14 @@ main() {
|
|||
|
||||
app.use('/query', new QueryService());
|
||||
|
||||
RequestMiddleware write(String message) {
|
||||
return (req, res) async {
|
||||
RequestHandler write(String message) {
|
||||
return (req, res) {
|
||||
res.write(message);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
app
|
||||
.chain(write('a'))
|
||||
.chain([write('b'), write('c')]).get('/chained', () => false);
|
||||
app.chain([write('a')]).chain([write('b'), write('c')]).get(
|
||||
'/chained', () => false);
|
||||
|
||||
app.use('MJ');
|
||||
|
||||
|
@ -179,7 +178,7 @@ main() {
|
|||
});
|
||||
|
||||
test('Can name routes', () {
|
||||
Route foo = app.get('/framework/:id', [])..name = 'frm';
|
||||
Route foo = app.get('/framework/:id', null)..name = 'frm';
|
||||
print('Foo: $foo');
|
||||
String uri = foo.makeUri({'id': 'angel'});
|
||||
print(uri);
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io' show stderr;
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:angel_container/mirrors.dart';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:mock_request/mock_request.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'encoders_buffer_test.dart' show encodingTests;
|
||||
|
||||
main() {
|
||||
|
@ -30,18 +32,18 @@ main() {
|
|||
},
|
||||
);
|
||||
|
||||
app.get('/hello', (ResponseContext res) {
|
||||
app.get('/hello', (req, res) {
|
||||
new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits]).pipe(res);
|
||||
});
|
||||
|
||||
app.get('/write', (res) async {
|
||||
app.get('/write', (req, res) async {
|
||||
await res.addStream(
|
||||
new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits]));
|
||||
res.write('bye');
|
||||
await res.close();
|
||||
});
|
||||
|
||||
app.get('/multiple', (res) async {
|
||||
app.get('/multiple', (req, res) async {
|
||||
await res.addStream(
|
||||
new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits]));
|
||||
await res
|
||||
|
@ -49,7 +51,7 @@ main() {
|
|||
await res.close();
|
||||
});
|
||||
|
||||
app.get('/overwrite', (ResponseContext res) async {
|
||||
app.get('/overwrite', (req, res) async {
|
||||
res.statusCode = 32;
|
||||
await new Stream<List<int>>.fromIterable(['Hello, world!'.codeUnits])
|
||||
.pipe(res);
|
||||
|
@ -63,7 +65,7 @@ main() {
|
|||
}
|
||||
});
|
||||
|
||||
app.get('/error', (res) => res.addError(new StateError('wtf')));
|
||||
app.get('/error', (req, res) => res.addError(new StateError('wtf')));
|
||||
|
||||
app.errorHandler = (e, req, res) async {
|
||||
stderr..writeln(e.error)..writeln(e.stackTrace);
|
||||
|
|
Loading…
Reference in a new issue