Handler
After creating an app instance, you can start defining your application logic using event handlers. An event handler is a function that receive an Event
instance and returns a response. You can compare it to controllers in other frameworks.
Defining event handlers
You can define event handlers using Handler
interface.
class MyHandler implements Handler {
Future<Response> handle(Event event) async {
return Response.text('Result string');
}
}
But usually you don't need to do this. Because Spry's logic registration API provides a simpler closure type method:
app.use((event) {
return 'Result string';
});
Responsible
Values returned from event handlers are automatically converted to responses. It can be:
- JSON serializable value. If returning a JSON object or serializable value, it will be stringified and sent with default
application/json
content-type. String
/num
/bool
: Sent as-is using defaulttext/plain
content-type.Map
/List
: Sent as-is using defaultapplication/json
content-type.null
/void
: Spry with end response with204 - No Content
status code.- Any
Object
includetoJson()
method: Sent as-is using defaultapplication/json
content-type. Stream<List<int>>
Responsible
Any of above values could also be wrapped in a Future
. This means that you can return a Future
from your event handler and Spry will wait for it to resolve before sending the response.
Example: Send text response:
app.use((event) => 'Hello, Spry!');
app.use((event) => 1);
app.use((event) => 2.1);
app.use((event) => true);
Example: Send JSON response:
app.use((event) => {"url": event.uri.toString()});
app.use((event) => [1, 2, 3]);
class User {
late String name;
toJson() => {'name': name};
}
app.use((event) => User()..name = 'Bob');
Example: Send a Future value:
app.use((event) {
final completer = Completer();
Timer(Duration(seconds: 1), () {
completer.complete('One second later');
});
return completer.future;
});
Example: Send a Stream:
app.use((event) {
return File("foo.txt").openRead();
});
Handlers stack
In Spry, we abandoned the so-called middleware design and designed the concept of Handlers stack, where each layer interrupts the call by default.
app.use((event) => 'value');
app.use((event) => 'value 2'); // Will never be executed!
The app expects that each Handler call will return a value, so the Handler needs to actively tell the app to call the next Handler (using the next
function):
app.use((event) {
print(1);
return next(event);
});
app.use((event) {
print(2);
});
// console: 1, 2
It can also perform functions similar to After-middleware:
app.use((event) async {
final res = next(event);
print(1);
return res;
});
app.use((event) {
print(2);
});
// console: 2, 1