Worked out some kinks in routing and hooked services. Services can use middleware.
This commit is contained in:
parent
80c6118544
commit
897a09d359
5 changed files with 98 additions and 33 deletions
|
@ -73,7 +73,7 @@ class RequestContext extends Extensible {
|
||||||
context.contentType = request.headers.contentType;
|
context.contentType = request.headers.contentType;
|
||||||
context.remoteAddress = request.connectionInfo.remoteAddress;
|
context.remoteAddress = request.connectionInfo.remoteAddress;
|
||||||
context.params = parameters;
|
context.params = parameters;
|
||||||
context.path = request.uri.toString();
|
context.path = request.uri.toString().replaceAll("?" + request.uri.query, "").replaceAll(new RegExp(r'\/+$'), '');
|
||||||
context.route = sourceRoute;
|
context.route = sourceRoute;
|
||||||
context.session = request.session;
|
context.session = request.session;
|
||||||
context.underlyingRequest = request;
|
context.underlyingRequest = request;
|
||||||
|
|
|
@ -52,7 +52,7 @@ class Angel extends Routable {
|
||||||
|
|
||||||
server.listen((HttpRequest request) async {
|
server.listen((HttpRequest request) async {
|
||||||
String req_url =
|
String req_url =
|
||||||
request.uri.toString().replaceAll(new RegExp(r'\/+$'), '');
|
request.uri.toString().replaceAll("?" + request.uri.query, "").replaceAll(new RegExp(r'\/+$'), '');
|
||||||
if (req_url.isEmpty) req_url = '/';
|
if (req_url.isEmpty) req_url = '/';
|
||||||
RequestContext req = await RequestContext.from(request, {}, this, null);
|
RequestContext req = await RequestContext.from(request, {}, this, null);
|
||||||
ResponseContext res = await ResponseContext.from(request.response, this);
|
ResponseContext res = await ResponseContext.from(request.response, this);
|
||||||
|
@ -95,7 +95,7 @@ class Angel extends Routable {
|
||||||
if (!canContinue) break;
|
if (!canContinue) break;
|
||||||
if (route.matcher.hasMatch(req_url) &&
|
if (route.matcher.hasMatch(req_url) &&
|
||||||
(request.method == route.method || route.method == '*')) {
|
(request.method == route.method || route.method == '*')) {
|
||||||
req.params = route.parseParameters(request.uri.toString());
|
req.params = route.parseParameters(req_url);
|
||||||
req.route = route;
|
req.route = route;
|
||||||
|
|
||||||
for (var handler in route.handlers) {
|
for (var handler in route.handlers) {
|
||||||
|
|
|
@ -60,22 +60,46 @@ class Service extends Routable {
|
||||||
Service() : super() {
|
Service() : super() {
|
||||||
Map restProvider = {'provider': Providers.REST};
|
Map restProvider = {'provider': Providers.REST};
|
||||||
|
|
||||||
|
Middleware indexMiddleware = _getAnnotation(this.index, Middleware);
|
||||||
get('/', (req, res) async {
|
get('/', (req, res) async {
|
||||||
return await this.index(mergeMap([req.query, restProvider]));
|
return await this.index(mergeMap([req.query, restProvider]));
|
||||||
});
|
}, middleware: (indexMiddleware == null) ? [] : indexMiddleware.handlers);
|
||||||
|
|
||||||
post('/', (req, res) async => await this.create(req.body, restProvider));
|
Middleware createMiddleware = _getAnnotation(this.create, Middleware);
|
||||||
|
post('/', (req, res) async => await this.create(req.body, restProvider),
|
||||||
|
middleware:
|
||||||
|
(createMiddleware == null) ? [] : createMiddleware.handlers);
|
||||||
|
|
||||||
get('/:id', (req, res) async =>
|
Middleware readMiddleware = _getAnnotation(this.read, Middleware);
|
||||||
await this.read(req.params['id'], mergeMap([req.query, restProvider])));
|
|
||||||
|
|
||||||
patch('/:id', (req, res) async => await this.modify(
|
get(
|
||||||
req.params['id'], req.body, restProvider));
|
'/:id',
|
||||||
|
(req, res) async => await this
|
||||||
|
.read(req.params['id'], mergeMap([req.query, restProvider])),
|
||||||
|
middleware: (readMiddleware == null) ? [] : readMiddleware.handlers);
|
||||||
|
|
||||||
post('/:id', (req, res) async => await this.update(
|
Middleware modifyMiddleware = _getAnnotation(this.modify, Middleware);
|
||||||
req.params['id'], req.body, restProvider));
|
patch(
|
||||||
|
'/:id',
|
||||||
|
(req, res) async =>
|
||||||
|
await this.modify(req.params['id'], req.body, restProvider),
|
||||||
|
middleware:
|
||||||
|
(modifyMiddleware == null) ? [] : modifyMiddleware.handlers);
|
||||||
|
|
||||||
delete('/:id', (req, res) async => await this.remove(
|
Middleware updateMiddleware = _getAnnotation(this.update, Middleware);
|
||||||
req.params['id'], mergeMap([req.query, restProvider])));
|
post(
|
||||||
|
'/:id',
|
||||||
|
(req, res) async =>
|
||||||
|
await this.update(req.params['id'], req.body, restProvider),
|
||||||
|
middleware:
|
||||||
|
(updateMiddleware == null) ? [] : updateMiddleware.handlers);
|
||||||
|
|
||||||
|
Middleware removeMiddleware = _getAnnotation(this.remove, Middleware);
|
||||||
|
delete(
|
||||||
|
'/:id',
|
||||||
|
(req, res) async => await this
|
||||||
|
.remove(req.params['id'], mergeMap([req.query, restProvider])),
|
||||||
|
middleware:
|
||||||
|
(removeMiddleware == null) ? [] : removeMiddleware.handlers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,29 +6,32 @@ class HookedService extends Service {
|
||||||
final Service inner;
|
final Service inner;
|
||||||
|
|
||||||
HookedServiceEventDispatcher beforeIndexed =
|
HookedServiceEventDispatcher beforeIndexed =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher beforeRead = new HookedServiceEventDispatcher();
|
HookedServiceEventDispatcher beforeRead = new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher beforeCreated =
|
HookedServiceEventDispatcher beforeCreated =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher beforeModified =
|
HookedServiceEventDispatcher beforeModified =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher beforeUpdated =
|
HookedServiceEventDispatcher beforeUpdated =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher beforeRemoved =
|
HookedServiceEventDispatcher beforeRemoved =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher afterIndexed =
|
HookedServiceEventDispatcher afterIndexed =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher afterRead = new HookedServiceEventDispatcher();
|
HookedServiceEventDispatcher afterRead = new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher afterCreated =
|
HookedServiceEventDispatcher afterCreated =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher afterModified =
|
HookedServiceEventDispatcher afterModified =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher afterUpdated =
|
HookedServiceEventDispatcher afterUpdated =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
HookedServiceEventDispatcher afterRemoved =
|
HookedServiceEventDispatcher afterRemoved =
|
||||||
new HookedServiceEventDispatcher();
|
new HookedServiceEventDispatcher();
|
||||||
|
|
||||||
HookedService(Service this.inner) : super() {}
|
HookedService(Service this.inner) {
|
||||||
|
// Clone all routes, including middleware
|
||||||
|
routes..clear()..addAll(inner.routes);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List> index([Map params]) async {
|
Future<List> index([Map params]) async {
|
||||||
|
|
|
@ -9,6 +9,14 @@ testMiddlewareMetadata(RequestContext req, ResponseContext res) async {
|
||||||
return "This should not be shown.";
|
return "This should not be shown.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class QueryService extends Service {
|
||||||
|
@override
|
||||||
|
@Middleware(const ['intercept_service', 'interceptor'])
|
||||||
|
read(id, [Map params]) {
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
group('routing', () {
|
group('routing', () {
|
||||||
Angel angel;
|
Angel angel;
|
||||||
|
@ -22,10 +30,16 @@ main() {
|
||||||
nested = new Angel();
|
nested = new Angel();
|
||||||
todos = new Angel();
|
todos = new Angel();
|
||||||
|
|
||||||
angel.registerMiddleware('interceptor', (req, res) async {
|
angel
|
||||||
res.write('Middleware');
|
..registerMiddleware('interceptor', (req, res) async {
|
||||||
return false;
|
res.write('Middleware');
|
||||||
});
|
return false;
|
||||||
|
})
|
||||||
|
..registerMiddleware('intercept_service',
|
||||||
|
(RequestContext req, res) async {
|
||||||
|
print("Intercepting a service!");
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
todos.get('/action/:action', (req, res) => res.json(req.params));
|
todos.get('/action/:action', (req, res) => res.json(req.params));
|
||||||
nested.post('/ted/:route', (req, res) => res.json(req.params));
|
nested.post('/ted/:route', (req, res) => res.json(req.params));
|
||||||
|
@ -37,12 +51,25 @@ main() {
|
||||||
angel.post('/lambda', (req, res) => req.body);
|
angel.post('/lambda', (req, res) => req.body);
|
||||||
angel.use('/nes', nested);
|
angel.use('/nes', nested);
|
||||||
angel.use('/todos/:id', todos);
|
angel.use('/todos/:id', todos);
|
||||||
angel.get('/greet/:name', (RequestContext req, res) async => "Hello ${req.params['name']}").as('Named routes');
|
angel
|
||||||
|
.get('/greet/:name',
|
||||||
|
(RequestContext req, res) async => "Hello ${req.params['name']}")
|
||||||
|
.as('Named routes');
|
||||||
angel.get('/named', (req, ResponseContext res) async {
|
angel.get('/named', (req, ResponseContext res) async {
|
||||||
res.redirectTo('Named routes', {'name': 'tests'});
|
res.redirectTo('Named routes', {'name': 'tests'});
|
||||||
});
|
});
|
||||||
|
angel.get('/log', (RequestContext req, res) async {
|
||||||
|
print("Query: ${req.query}");
|
||||||
|
return "Logged";
|
||||||
|
});
|
||||||
|
angel.use('/query', new QueryService());
|
||||||
angel.get('*', 'MJ');
|
angel.get('*', 'MJ');
|
||||||
|
|
||||||
|
print("DUMPING ROUTES: ");
|
||||||
|
for (Route route in angel.routes) {
|
||||||
|
print("${route.method} ${route.path} - ${route.handlers}");
|
||||||
|
}
|
||||||
|
|
||||||
client = new http.Client();
|
client = new http.Client();
|
||||||
await angel.startServer(InternetAddress.LOOPBACK_IP_V4, 0);
|
await angel.startServer(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||||
url = "http://${angel.httpServer.address.host}:${angel.httpServer.port}";
|
url = "http://${angel.httpServer.address.host}:${angel.httpServer.port}";
|
||||||
|
@ -97,8 +124,8 @@ main() {
|
||||||
test('Can serialize function result as JSON', () async {
|
test('Can serialize function result as JSON', () async {
|
||||||
Map headers = {'Content-Type': 'application/json'};
|
Map headers = {'Content-Type': 'application/json'};
|
||||||
String postData = god.serialize({'it': 'works'});
|
String postData = god.serialize({'it': 'works'});
|
||||||
var response = await client.post(
|
var response =
|
||||||
"$url/lambda", headers: headers, body: postData);
|
await client.post("$url/lambda", headers: headers, body: postData);
|
||||||
expect(god.deserialize(response.body)['it'], equals('works'));
|
expect(god.deserialize(response.body)['it'], equals('works'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -119,5 +146,16 @@ main() {
|
||||||
print(response.body);
|
print(response.body);
|
||||||
expect(god.deserialize(response.body), equals('Hello tests'));
|
expect(god.deserialize(response.body), equals('Hello tests'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Match routes, even with query params', () async {
|
||||||
|
var response =
|
||||||
|
await client.get("$url/log?foo=bar&bar=baz&baz.foo=bar&baz.bar=foo");
|
||||||
|
print(response.body);
|
||||||
|
expect(god.deserialize(response.body), equals('Logged'));
|
||||||
|
|
||||||
|
response = await client.get("$url/query/foo?bar=baz");
|
||||||
|
print(response.body);
|
||||||
|
expect(response.body, equals("Middleware"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue