platform/lib/src/http/server.dart

146 lines
4.1 KiB
Dart
Raw Normal View History

2016-02-28 13:11:17 +00:00
part of angel_framework.http;
2016-04-18 03:27:23 +00:00
/// A function that binds an [Angel] server to an Internet address and port.
2016-02-28 13:11:17 +00:00
typedef Future<HttpServer> ServerGenerator(InternetAddress address, int port);
2016-04-18 03:27:23 +00:00
/// A function that configures an [Angel] server in some way.
typedef AngelConfigurer(Angel app);
2016-02-28 13:11:17 +00:00
/// A powerful real-time/REST/MVC server class.
class Angel extends Routable {
2016-04-18 03:27:23 +00:00
ServerGenerator _serverGenerator = (address, port) async => await HttpServer
.bind(address, port);
2016-04-22 01:42:39 +00:00
var viewGenerator = (String view,
2016-04-22 02:40:37 +00:00
[Map data]) => "No view engine has been configured yet.";
2016-04-18 03:27:23 +00:00
HttpServer httpServer;
God god = new God();
startServer(InternetAddress address, int port) async {
2016-02-28 13:11:17 +00:00
var server = await _serverGenerator(
address ?? InternetAddress.LOOPBACK_IP_V4, port);
2016-04-18 03:27:23 +00:00
this.httpServer = server;
2016-02-28 13:11:17 +00:00
var router = new Router(server);
2016-04-18 03:27:23 +00:00
this.routes.forEach((Route route) {
2016-02-28 13:11:17 +00:00
router.serve(route.matcher, method: route.method).listen((
2016-04-18 03:27:23 +00:00
HttpRequest request) async {
RequestContext req = await RequestContext.from(
request, route.parseParameters(request.uri.toString()), this,
route);
ResponseContext res = await ResponseContext.from(
request.response, this);
bool canContinue = true;
2016-02-28 13:11:17 +00:00
2016-04-18 03:27:23 +00:00
for (var handler in route.handlers) {
if (canContinue) {
canContinue = await new Future<bool>.sync(() async {
return _applyHandler(handler, req, res);
}).catchError((e) {
stderr.write(e.error);
canContinue = false;
return false;
});
}
}
2016-04-22 01:42:39 +00:00
_finalizeResponse(request, res);
2016-02-28 13:11:17 +00:00
});
});
2016-04-18 03:27:23 +00:00
2016-04-22 01:42:39 +00:00
router.defaultStream.listen((HttpRequest request) async {
RequestContext req = await RequestContext.from(
request, {}, this,
null);
ResponseContext res = await ResponseContext.from(
request.response, this);
2016-04-22 02:40:37 +00:00
on404(req, res);
2016-04-22 01:42:39 +00:00
_finalizeResponse(request, res);
});
2016-04-18 03:27:23 +00:00
return server;
}
Future<bool> _applyHandler(handler, RequestContext req,
ResponseContext res) async {
if (handler is Middleware) {
var result = await handler(req, res);
if (result is bool)
return result == true;
else if (result != null) {
res.json(result);
return false;
} else return true;
2016-04-18 03:27:23 +00:00
}
if (handler is RequestHandler) {
2016-04-18 03:27:23 +00:00
await handler(req, res);
return res.isOpen;
}
else if (handler is RawRequestHandler) {
var result = await handler(req.underlyingRequest);
if (result is bool)
return result == true;
else if (result != null) {
res.json(result);
return false;
} else return true;
2016-04-18 03:27:23 +00:00
}
else if (handler is Function || handler is Future) {
var result = await handler();
if (result is bool)
return result == true;
else if (result != null) {
res.json(result);
return false;
} else return true;
2016-04-18 03:27:23 +00:00
}
else if (middleware.containsKey(handler)) {
return await _applyHandler(middleware[handler], req, res);
}
else {
res.willCloseItself = true;
res.underlyingResponse.write(god.serialize(handler));
await res.underlyingResponse.close();
return false;
}
}
2016-04-22 01:42:39 +00:00
_finalizeResponse(HttpRequest request, ResponseContext res) async {
if (!res.willCloseItself) {
res.responseData.forEach((blob) => request.response.add(blob));
await request.response.close();
}
}
2016-04-18 03:27:23 +00:00
/// Applies an [AngelConfigurer] to this instance.
void configure(AngelConfigurer configurer) {
configurer(this);
2016-02-28 13:11:17 +00:00
}
/// Starts the server.
void listen({InternetAddress address, int port: 3000}) {
runZoned(() async {
2016-04-18 03:27:23 +00:00
await startServer(address, port);
2016-02-28 13:11:17 +00:00
}, onError: onError);
}
2016-04-22 01:42:39 +00:00
/// Responds to a 404.
RequestHandler on404 = (req, res) => res.write("404 Not Found");
2016-02-28 13:11:17 +00:00
/// Handles a server error.
2016-04-22 01:42:39 +00:00
onError(e, [StackTrace stackTrace]) {
2016-04-18 03:27:23 +00:00
stderr.write(e.toString());
if (stackTrace != null)
stderr.write(stackTrace.toString());
2016-04-22 01:42:39 +00:00
}
2016-04-18 03:27:23 +00:00
Angel() : super() {}
2016-02-28 13:11:17 +00:00
2016-04-18 03:27:23 +00:00
/// Creates an HTTPS server.
Angel.secure() : super() {}
2016-02-28 13:11:17 +00:00
}