Fixed a bunch of issues

This commit is contained in:
thosakwe 2016-11-23 14:50:17 -05:00
parent fc13db72ff
commit 0e5f315773
7 changed files with 111 additions and 58 deletions

View file

@ -1,6 +1,6 @@
# angel_framework
![version 1.0.0-dev](https://img.shields.io/badge/version-1.0.0--dev.23-red.svg)
![version 1.0.0-dev.24](https://img.shields.io/badge/version-1.0.0--dev.24-red.svg)
![build status](https://travis-ci.org/angel-dart/framework.svg)
Core libraries for the Angel Framework.

View file

@ -73,19 +73,30 @@ class Controller {
var arg = req.params[name];
if (arg == null) {
if (parameter.type.reflectedType != dynamic) {
try {
arg = app.container.make(parameter.type.reflectedType);
if (arg != null) {
args.add(arg);
if (req.injections.containsKey(name)) {
args.add(req.injections[name]);
continue;
}
final type = parameter.type.reflectedType;
if (req.injections.containsKey(type)) {
args.add(req.injections[type]);
continue;
}
if (type != dynamic) {
try {
args.add(app.container.make(type));
continue;
} catch (e) {
//
print(e);
print(req.injections);
}
}
if (!exposeMirror.reflectee.allowNull.contain(name))
if (!exposeMirror.reflectee.allowNull.contains(name))
throw new AngelHttpException.BadRequest(
message: "Missing parameter '$name'");
} else

View file

@ -10,26 +10,32 @@ import 'angel_base.dart';
class RequestContext extends Extensible {
BodyParseResult _body;
ContentType _contentType;
HttpRequest _io;
String _path;
HttpRequest _underlyingRequest;
/// The [Angel] instance that is responding to this request.
AngelBase app;
/// Any cookies sent with this request.
List<Cookie> get cookies => underlyingRequest.cookies;
List<Cookie> get cookies => io.cookies;
/// All HTTP headers sent with this request.
HttpHeaders get headers => underlyingRequest.headers;
HttpHeaders get headers => io.headers;
/// The requested hostname.
String get hostname => underlyingRequest.headers.value(HttpHeaders.HOST);
String get hostname => io.headers.value(HttpHeaders.HOST);
/// A [Map] of values that should be DI'd.
final Map injections = {};
/// The underlying [HttpRequest] instance underneath this context.
HttpRequest get io => _io;
/// The user's IP.
String get ip => remoteAddress.address;
/// This request's HTTP method.
String get method => underlyingRequest.method;
String get method => io.method;
/// All post data submitted to the server.
Map get body => _body.body;
@ -51,24 +57,27 @@ class RequestContext extends Extensible {
/// The remote address requesting this resource.
InternetAddress get remoteAddress =>
underlyingRequest.connectionInfo.remoteAddress;
io.connectionInfo.remoteAddress;
/// The user's HTTP session.
HttpSession get session => underlyingRequest.session;
HttpSession get session => io.session;
/// The [Uri] instance representing the path this request is responding to.
Uri get uri => underlyingRequest.uri;
Uri get uri => io.uri;
/// Is this an **XMLHttpRequest**?
bool get xhr =>
underlyingRequest.headers
io.headers
.value("X-Requested-With")
?.trim()
?.toLowerCase() ==
'xmlhttprequest';
/// The underlying [HttpRequest] instance underneath this context.
HttpRequest get underlyingRequest => _underlyingRequest;
@deprecated
HttpRequest get underlyingRequest {
throw new Exception(
'`RequestContext#underlyingRequest` is deprecated. Please update your application to use the newer `RequestContext#io`.');
}
/// Magically transforms an [HttpRequest] into a [RequestContext].
static Future<RequestContext> from(HttpRequest request, AngelBase app) async {
@ -80,10 +89,14 @@ class RequestContext extends Extensible {
.toString()
.replaceAll("?" + request.uri.query, "")
.replaceAll(new RegExp(r'/+$'), '');
ctx._underlyingRequest = request;
ctx._io = request;
ctx._body = await parseBody(request);
return ctx;
}
void inject(Type type, value) {
injections[type] = value;
}
}

View file

@ -25,16 +25,22 @@ class ResponseContext extends Extensible {
/// Sets the status code to be sent with this response.
void status(int code) {
underlyingResponse.statusCode = code;
io.statusCode = code;
}
/// The underlying [HttpResponse] under this instance.
final HttpResponse underlyingResponse;
final HttpResponse io;
ResponseContext(this.underlyingResponse, this.app);
@deprecated
HttpResponse get underlyingRequest {
throw new Exception(
'`ResponseContext#underlyingResponse` is deprecated. Please update your application to use the newer `ResponseContext#io`.');
}
ResponseContext(this.io, this.app);
/// Any and all cookies to be sent to the user.
List<Cookie> get cookies => underlyingResponse.cookies;
List<Cookie> get cookies => io.cookies;
/// Set this to true if you will manually close the response.
bool willCloseItself = false;
@ -57,9 +63,9 @@ class ResponseContext extends Extensible {
/// Sets a response header to the given value, or retrieves its value.
header(String key, [String value]) {
if (value == null)
return underlyingResponse.headers[key];
return io.headers[key];
else
underlyingResponse.headers.set(key, value);
io.headers.set(key, value);
}
/// Serializes JSON to the response.
@ -163,7 +169,7 @@ class ResponseContext extends Extensible {
header(HttpHeaders.CONTENT_TYPE, lookupMimeType(file.path));
willCloseItself = true;
await file.openRead().pipe(underlyingResponse);
await file.openRead().pipe(io);
}
/// Writes data to the response.

View file

@ -105,6 +105,8 @@ class Angel extends AngelBase {
/// Loads some base dependencies into the service container.
void bootstrapContainer() {
container.singleton(this, as: AngelBase);
container.singleton(this, as: Routable);
container.singleton(this, as: Router);
container.singleton(this);
if (runtimeType != Angel) container.singleton(this, as: Angel);
@ -130,7 +132,7 @@ class Angel extends AngelBase {
}
if (handler is RawRequestHandler) {
var result = await handler(req.underlyingRequest);
var result = await handler(req.io);
if (result is bool)
return result == true;
else if (result != null) {
@ -167,8 +169,8 @@ class Angel extends AngelBase {
}
res.willCloseItself = true;
res.underlyingResponse.write(god.serialize(handler));
await res.underlyingResponse.close();
res.io.write(god.serialize(handler));
await res.io.close();
return false;
}
@ -177,23 +179,34 @@ class Angel extends AngelBase {
final req = await RequestContext.from(request, this);
final res = new ResponseContext(request.response, this);
String requestedUrl = request.uri
.path
.replaceAll(_straySlashes, '');
String requestedUrl = request.uri.path.replaceAll(_straySlashes, '');
if (requestedUrl.isEmpty) requestedUrl = '/';
final route = resolve(requestedUrl, method: request.method);
_printDebug('Resolved ${requestedUrl} -> $route');
final resolved = [];
if (requestedUrl == '/') {
resolved.add(root.indexRoute);
} else {
resolved.addAll(resolveAll(requestedUrl, method: request.method));
final route = resolved.first;
req.params.addAll(route?.parseParameters(requestedUrl) ?? {});
req.inject(Match, route.match(requestedUrl));
}
final handlerSequence = []..addAll(before);
if (route != null) handlerSequence.addAll(route.handlerSequence);
handlerSequence.addAll(after);
final pipeline = []..addAll(before);
_printDebug('Handler sequence on $requestedUrl: $handlerSequence');
if (resolved.isNotEmpty) {
for (final route in resolved) {
pipeline.addAll(route.handlerSequence);
}
}
for (final handler in handlerSequence) {
pipeline.addAll(after);
_printDebug('Handler sequence on $requestedUrl: $pipeline');
for (final handler in pipeline) {
try {
_printDebug('Executing handler: $handler');
final result = await executeHandler(handler, req, res);
@ -249,8 +262,7 @@ class Angel extends AngelBase {
// Run a function after injecting from service container
Future runContained(Function handler, RequestContext req, ResponseContext res,
{Map<String, dynamic> namedParameters,
Map<Type, dynamic> injecting}) async {
{Map<String, dynamic> namedParameters}) async {
ClosureMirror closureMirror = reflect(handler);
List args = [];
@ -261,9 +273,9 @@ class Angel extends AngelBase {
args.add(res);
else {
// First, search to see if we can map this to a type
if (parameter.type.reflectedType != dynamic) {
args.add(container.make(parameter.type.reflectedType,
namedParameters: namedParameters, injecting: injecting));
if (req.injections.containsKey(parameter.type.reflectedType)) {
args.add(req.injections[parameter.type.reflectedType]);
continue;
} else {
String name = MirrorSystem.getName(parameter.simpleName);
@ -273,7 +285,12 @@ class Angel extends AngelBase {
args.add(req);
else if (name == "res")
args.add(res);
else {
else if (req.injections.containsKey(name))
args.add(req.injections[name]);
else if (parameter.type.reflectedType != dynamic) {
args.add(container.make(parameter.type.reflectedType,
injecting: req.injections));
} else {
throw new Exception(
"Cannot resolve parameter '$name' within handler.");
}
@ -324,20 +341,22 @@ class Angel extends AngelBase {
/// Provide paths to a certificate chain and server key (both .pem).
/// If no password is provided, a random one will be generated upon running
/// the server.
Angel.secure(String certificateChainPath, String serverKeyPath,
{bool debug: false, String password})
: super(debug: debug) {
bootstrapContainer();
_serverGenerator = (InternetAddress address, int port) async {
factory Angel.secure(String certificateChainPath, String serverKeyPath,
{bool debug: false, String password}) {
final app = new Angel(debug: debug);
app._serverGenerator = (InternetAddress address, int port) async {
var certificateChain =
Platform.script.resolve(certificateChainPath).toFilePath();
var serverKey = Platform.script.resolve(serverKeyPath).toFilePath();
var serverContext = new SecurityContext();
serverContext.useCertificateChain(certificateChain);
serverContext.usePrivateKey(serverKey,
password: password ?? _randomString(8));
password: password ?? app._randomString(8));
return await HttpServer.bindSecure(address, port, serverContext);
};
return app;
}
}

View file

@ -1,5 +1,5 @@
name: angel_framework
version: 1.0.0-dev.23
version: 1.0.0-dev.24
description: Core libraries for the Angel framework.
author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_framework

View file

@ -22,12 +22,12 @@ main() {
app.container.singleton(new Todo(text: TEXT, over: OVER));
app.get("/errands", (Todo singleton) => singleton);
app.get("/errands3", (Errand singleton, Todo foo, RequestContext req) => singleton.text);
app.get("/errands3",
(Errand singleton, Todo foo, RequestContext req) => singleton.text);
await app.configure(new SingletonController());
await app.configure(new ErrandController());
server = await app.startServer();
print('server: $server, httpServer: ${app.httpServer}');
url = "http://${server.address.host}:${server.port}";
});
@ -77,7 +77,11 @@ class SingletonController extends Controller {
@Expose("/errands4")
class ErrandController extends Controller {
@Expose("/")
errand(Errand errand) => errand.text;
errand(Errand errand, Match match) {
expect(match, isNotNull);
print('Match: ${match.group(0)}');
return errand.text;
}
}
class Errand {