Make redirects + download async
This commit is contained in:
parent
1c07aa5243
commit
2004877696
5 changed files with 26 additions and 16 deletions
|
@ -1,3 +1,6 @@
|
|||
# 2.0.0-rc.6
|
||||
* Make `redirect` and `download` methods asynchronous.
|
||||
|
||||
# 2.0.0-rc.5
|
||||
* Make `serializer` `FutureOr<String> Function(Object)`.
|
||||
* Make `ResponseContext.serialize` return `Future<bool>`.
|
||||
|
|
|
@ -139,7 +139,7 @@ abstract class ResponseContext<RawResponse>
|
|||
new StateError('Cannot modify a closed response.');
|
||||
|
||||
/// Sends a download as a response.
|
||||
void download(File file, {String filename}) {
|
||||
Future<void> download(File file, {String filename}) async {
|
||||
if (!isOpen) throw closed();
|
||||
|
||||
headers["Content-Disposition"] =
|
||||
|
@ -148,15 +148,15 @@ abstract class ResponseContext<RawResponse>
|
|||
headers['content-length'] = file.lengthSync().toString();
|
||||
|
||||
if (!isBuffered) {
|
||||
file.openRead().pipe(this);
|
||||
await file.openRead().pipe(this);
|
||||
} else {
|
||||
buffer.add(file.readAsBytesSync());
|
||||
close();
|
||||
await close();
|
||||
}
|
||||
}
|
||||
|
||||
/// Prevents more data from being written to the response, and locks it entire from further editing.
|
||||
Future close() {
|
||||
Future<void> close() {
|
||||
if (buffer is LockableBytesBuilder) {
|
||||
(buffer as LockableBytesBuilder).lock();
|
||||
}
|
||||
|
@ -173,16 +173,17 @@ abstract class ResponseContext<RawResponse>
|
|||
/// Returns a JSONP response.
|
||||
///
|
||||
/// You can override the [contentType] sent; by default it is `application/javascript`.
|
||||
void jsonp(value, {String callbackName = "callback", MediaType contentType}) {
|
||||
Future<void> jsonp(value,
|
||||
{String callbackName = "callback", MediaType contentType}) {
|
||||
if (!isOpen) throw closed();
|
||||
this.contentType =
|
||||
contentType ?? new MediaType('application', 'javascript');
|
||||
write("$callbackName(${serializer(value)})");
|
||||
close();
|
||||
return close();
|
||||
}
|
||||
|
||||
/// Renders a view to the response stream, and closes the response.
|
||||
Future render(String view, [Map<String, dynamic> data]) {
|
||||
Future<void> render(String view, [Map<String, dynamic> data]) {
|
||||
if (!isOpen) throw closed();
|
||||
contentType = new MediaType('text', 'html', {'charset': 'utf-8'});
|
||||
return Future<String>.sync(() => app.viewGenerator(
|
||||
|
@ -190,7 +191,7 @@ abstract class ResponseContext<RawResponse>
|
|||
new Map<String, dynamic>.from(renderParams)
|
||||
..addAll(data ?? <String, dynamic>{}))).then((content) {
|
||||
write(content);
|
||||
close();
|
||||
return close();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -201,7 +202,7 @@ abstract class ResponseContext<RawResponse>
|
|||
/// based on the provided params.
|
||||
///
|
||||
/// See [Router]#navigate for more. :)
|
||||
void redirect(url, {bool absolute = true, int code = 302}) {
|
||||
Future<void> redirect(url, {bool absolute = true, int code = 302}) {
|
||||
if (!isOpen) throw closed();
|
||||
headers
|
||||
..['content-type'] = 'text/html'
|
||||
|
@ -226,11 +227,11 @@ abstract class ResponseContext<RawResponse>
|
|||
</body>
|
||||
</html>
|
||||
''');
|
||||
close();
|
||||
return close();
|
||||
}
|
||||
|
||||
/// Redirects to the given named [Route].
|
||||
void redirectTo(String name, [Map params, int code]) {
|
||||
Future<void> redirectTo(String name, [Map params, int code]) async {
|
||||
if (!isOpen) throw closed();
|
||||
Route _findRoute(Router r) {
|
||||
for (Route route in r.routes) {
|
||||
|
@ -247,7 +248,7 @@ abstract class ResponseContext<RawResponse>
|
|||
Route matched = _findRoute(app);
|
||||
|
||||
if (matched != null) {
|
||||
redirect(
|
||||
await redirect(
|
||||
matched.makeUri(params.keys.fold<Map<String, dynamic>>({}, (out, k) {
|
||||
return out..[k.toString()] = params[k];
|
||||
})),
|
||||
|
@ -259,7 +260,7 @@ abstract class ResponseContext<RawResponse>
|
|||
}
|
||||
|
||||
/// Redirects to the given [Controller] action.
|
||||
void redirectToAction(String action, [Map params, int code]) {
|
||||
Future<void> redirectToAction(String action, [Map params, int code]) {
|
||||
if (!isOpen) throw closed();
|
||||
// UserController@show
|
||||
List<String> split = action.split("@");
|
||||
|
@ -291,7 +292,7 @@ abstract class ResponseContext<RawResponse>
|
|||
}))
|
||||
.replaceAll(_straySlashes, '');
|
||||
|
||||
redirect('$head/$tail'.replaceAll(_straySlashes, ''), code: code);
|
||||
return redirect('$head/$tail'.replaceAll(_straySlashes, ''), code: code);
|
||||
}
|
||||
|
||||
/// Serializes data to the response.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel_framework
|
||||
version: 2.0.0-rc.5
|
||||
version: 2.0.0-rc.6
|
||||
description: A high-powered HTTP server with dependency injection, routing and much more.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_framework
|
||||
|
|
|
@ -99,6 +99,12 @@ main() {
|
|||
expect(result[0]["angel"], equals("framework"));
|
||||
});
|
||||
|
||||
test('asStream() fires', () async {
|
||||
var stream = todoService.afterCreated.asStream();
|
||||
await todoService.create({'angel': 'framework'});
|
||||
expect(await stream.first.then((e) => e.result['angel']), 'framework');
|
||||
});
|
||||
|
||||
test('metadata', () async {
|
||||
final service = new HookedService(new IncrementService())..addHooks(app);
|
||||
expect(service.inner, isNot(const IsInstanceOf<MapService>()));
|
||||
|
|
|
@ -85,7 +85,7 @@ main() {
|
|||
(RequestContext req, res) async => "Hello ${req.params['name']}")
|
||||
.name = 'Named routes';
|
||||
app.get('/named', (req, ResponseContext res) async {
|
||||
res.redirectTo('Named routes', {'name': 'tests'});
|
||||
await res.redirectTo('Named routes', {'name': 'tests'});
|
||||
});
|
||||
app.get('/log', (RequestContext req, res) async {
|
||||
print("Query: ${req.queryParameters}");
|
||||
|
|
Loading…
Reference in a new issue