:)
This commit is contained in:
parent
0057f11661
commit
530eb11bf8
5 changed files with 89 additions and 9 deletions
|
@ -1,6 +1,6 @@
|
||||||
# angel_framework
|
# angel_framework
|
||||||
|
|
||||||
[![pub 1.0.0-dev.35](https://img.shields.io/badge/pub-1.0.0--dev.35-red.svg)](https://pub.dartlang.org/packages/angel_framework)
|
[![pub 1.0.0-dev.36](https://img.shields.io/badge/pub-1.0.0--dev.36-red.svg)](https://pub.dartlang.org/packages/angel_framework)
|
||||||
[![build status](https://travis-ci.org/angel-dart/framework.svg)](https://travis-ci.org/angel-dart/framework)
|
[![build status](https://travis-ci.org/angel-dart/framework.svg)](https://travis-ci.org/angel-dart/framework)
|
||||||
|
|
||||||
Core libraries for the Angel Framework.
|
Core libraries for the Angel Framework.
|
|
@ -4,6 +4,11 @@ import 'dart:async';
|
||||||
import 'request_context.dart';
|
import 'request_context.dart';
|
||||||
import 'response_context.dart';
|
import 'response_context.dart';
|
||||||
|
|
||||||
|
abstract class AngelMiddleware {
|
||||||
|
Future<bool> call(RequestContext req, ResponseContext res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Use AngelMiddleware instead')
|
||||||
abstract class BaseMiddleware {
|
abstract class BaseMiddleware {
|
||||||
Future<bool> call(RequestContext req, ResponseContext res);
|
Future<bool> call(RequestContext req, ResponseContext res);
|
||||||
}
|
}
|
|
@ -79,6 +79,8 @@ class ResponseContext extends Extensible {
|
||||||
ResponseContext(this.io, this.app);
|
ResponseContext(this.io, this.app);
|
||||||
|
|
||||||
/// Set this to true if you will manually close the response.
|
/// Set this to true if you will manually close the response.
|
||||||
|
///
|
||||||
|
/// If `true`, all response finalizers will be skipped.
|
||||||
bool willCloseItself = false;
|
bool willCloseItself = false;
|
||||||
|
|
||||||
/// Sends a download as a response.
|
/// Sends a download as a response.
|
||||||
|
@ -209,14 +211,34 @@ class ResponseContext extends Extensible {
|
||||||
redirect('$head/$tail'.replaceAll(_straySlashes, ''), code: code);
|
redirect('$head/$tail'.replaceAll(_straySlashes, ''), code: code);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Streams a file to this response as chunked data.
|
/// Copies a file's contents into the response buffer.
|
||||||
Future streamFile(File file,
|
Future sendFile(File file,
|
||||||
{int chunkSize, int sleepMs: 0, bool resumable: true}) async {
|
{int chunkSize, int sleepMs: 0, bool resumable: true}) async {
|
||||||
if (!isOpen) return;
|
if (!isOpen) return;
|
||||||
|
|
||||||
headers[HttpHeaders.CONTENT_TYPE] = lookupMimeType(file.path);
|
headers[HttpHeaders.CONTENT_TYPE] = lookupMimeType(file.path);
|
||||||
end();
|
|
||||||
buffer.add(await file.readAsBytes());
|
buffer.add(await file.readAsBytes());
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Streams a file to this response.
|
||||||
|
///
|
||||||
|
/// You can optionally transform the file stream with a [codec].
|
||||||
|
Future streamFile(File file,
|
||||||
|
{int chunkSize,
|
||||||
|
int sleepMs: 0,
|
||||||
|
bool resumable: true,
|
||||||
|
Codec<List<int>, List<int>> codec}) async {
|
||||||
|
if (!isOpen) return;
|
||||||
|
|
||||||
|
headers[HttpHeaders.CONTENT_TYPE] = lookupMimeType(file.path);
|
||||||
|
end();
|
||||||
|
willCloseItself = true;
|
||||||
|
|
||||||
|
var stream = codec != null
|
||||||
|
? file.openRead().transform(codec.encoder)
|
||||||
|
: file.openRead();
|
||||||
|
await stream.pipe(io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes data to the response.
|
/// Writes data to the response.
|
||||||
|
|
|
@ -38,6 +38,8 @@ class Angel extends AngelBase {
|
||||||
new StreamController<AngelFatalError>.broadcast();
|
new StreamController<AngelFatalError>.broadcast();
|
||||||
StreamController<Controller> _onController =
|
StreamController<Controller> _onController =
|
||||||
new StreamController<Controller>.broadcast();
|
new StreamController<Controller>.broadcast();
|
||||||
|
final List<Angel> _children = [];
|
||||||
|
Angel _parent;
|
||||||
final Random _rand = new Random.secure();
|
final Random _rand = new Random.secure();
|
||||||
|
|
||||||
ServerGenerator _serverGenerator = HttpServer.bind;
|
ServerGenerator _serverGenerator = HttpServer.bind;
|
||||||
|
@ -48,14 +50,26 @@ class Angel extends AngelBase {
|
||||||
/// Fired before a request is processed. Always runs.
|
/// Fired before a request is processed. Always runs.
|
||||||
Stream<HttpRequest> get beforeProcessed => _beforeProcessed.stream;
|
Stream<HttpRequest> get beforeProcessed => _beforeProcessed.stream;
|
||||||
|
|
||||||
|
/// All child application mounted on this instance.
|
||||||
|
List<Angel> get children => new List<Angel>.unmodifiable(_children);
|
||||||
|
|
||||||
/// Fired on fatal errors.
|
/// Fired on fatal errors.
|
||||||
Stream<AngelFatalError> get fatalErrorStream => _fatalErrorStream.stream;
|
Stream<AngelFatalError> get fatalErrorStream => _fatalErrorStream.stream;
|
||||||
|
|
||||||
|
/// Indicates whether the application is running in a production environment.
|
||||||
|
///
|
||||||
|
/// The criteria for this is the `ANGEL_ENV` environment variable being set to
|
||||||
|
/// `'production'`.
|
||||||
|
bool get isProduction => Platform.environment['ANGEL_ENV'] == 'production';
|
||||||
|
|
||||||
/// Fired whenever a controller is added to this instance.
|
/// Fired whenever a controller is added to this instance.
|
||||||
///
|
///
|
||||||
/// **NOTE**: This is a broadcast stream.
|
/// **NOTE**: This is a broadcast stream.
|
||||||
Stream<Controller> get onController => _onController.stream;
|
Stream<Controller> get onController => _onController.stream;
|
||||||
|
|
||||||
|
/// Returns the parent instance of this application, if any.
|
||||||
|
Angel get parent => _parent;
|
||||||
|
|
||||||
/// Always run before responses are sent.
|
/// Always run before responses are sent.
|
||||||
///
|
///
|
||||||
/// These will only not run if an [AngelFatalError] occurs.
|
/// These will only not run if an [AngelFatalError] occurs.
|
||||||
|
@ -79,10 +93,10 @@ class Angel extends AngelBase {
|
||||||
AngelErrorHandler get errorHandler => _errorHandler;
|
AngelErrorHandler get errorHandler => _errorHandler;
|
||||||
|
|
||||||
/// [RequestMiddleware] to be run before all requests.
|
/// [RequestMiddleware] to be run before all requests.
|
||||||
List before = [];
|
final List before = [];
|
||||||
|
|
||||||
/// [RequestMiddleware] to be run after all requests.
|
/// [RequestMiddleware] to be run after all requests.
|
||||||
List after = [];
|
final List after = [];
|
||||||
|
|
||||||
/// The native HttpServer running this instancce.
|
/// The native HttpServer running this instancce.
|
||||||
HttpServer httpServer;
|
HttpServer httpServer;
|
||||||
|
@ -327,16 +341,55 @@ class Angel extends AngelBase {
|
||||||
}, onError: _onError);
|
}, onError: _onError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mounts the child on this router.
|
||||||
|
///
|
||||||
|
/// If the router is an [Angel] instance, all controllers
|
||||||
|
/// will be copied, as well as services and response finalizers.
|
||||||
|
///
|
||||||
|
/// [before] and [after] will be preserved.
|
||||||
|
///
|
||||||
|
/// NOTE: The above will not be properly copied if [path] is
|
||||||
|
/// a [RegExp].
|
||||||
@override
|
@override
|
||||||
use(Pattern path, Routable routable,
|
use(Pattern path, Routable routable,
|
||||||
{bool hooked: true, String namespace: null}) {
|
{bool hooked: true, String namespace: null}) {
|
||||||
if (routable is Angel) {
|
|
||||||
final head = path.toString().replaceAll(_straySlashes, '');
|
final head = path.toString().replaceAll(_straySlashes, '');
|
||||||
|
|
||||||
|
if (routable is Angel) {
|
||||||
|
_children.add(routable.._parent = this);
|
||||||
|
|
||||||
|
if (routable.before.isNotEmpty) {
|
||||||
|
all(path, (req, res) {
|
||||||
|
return true;
|
||||||
|
}, middleware: routable.before);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (routable.after.isNotEmpty) {
|
||||||
|
all(path, (req, res) {
|
||||||
|
return true;
|
||||||
|
}, middleware: routable.after);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (routable.responseFinalizers.isNotEmpty) {
|
||||||
|
responseFinalizers.add((req, res) async {
|
||||||
|
if (req.path.replaceAll(_straySlashes, '').startsWith(head)) {
|
||||||
|
for (var finalizer in routable.responseFinalizers)
|
||||||
|
await finalizer(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
routable.controllers.forEach((k, v) {
|
routable.controllers.forEach((k, v) {
|
||||||
final tail = k.toString().replaceAll(_straySlashes, '');
|
final tail = k.toString().replaceAll(_straySlashes, '');
|
||||||
controllers['$head/$tail'.replaceAll(_straySlashes, '')] = v;
|
controllers['$head/$tail'.replaceAll(_straySlashes, '')] = v;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
routable.services.forEach((k, v) {
|
||||||
|
final tail = k.toString().replaceAll(_straySlashes, '');
|
||||||
|
services['$head/$tail'.replaceAll(_straySlashes, '')] = v;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routable is Service) {
|
if (routable is Service) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
name: angel_framework
|
name: angel_framework
|
||||||
version: 1.0.0-dev.35
|
version: 1.0.0-dev.36
|
||||||
description: Core libraries for the Angel framework.
|
description: Core libraries for the Angel framework.
|
||||||
author: Tobe O <thosakwe@gmail.com>
|
author: Tobe O <thosakwe@gmail.com>
|
||||||
homepage: https://github.com/angel-dart/angel_framework
|
homepage: https://github.com/angel-dart/angel_framework
|
||||||
|
|
Loading…
Reference in a new issue