Lifecycle
Mapl request lifecycle can be illustrated as follows:
Middlewares
Middlewares are functions that get executed on every request, after the route matching phase.
app.apply((c) => { c.headers.push(['Server', 'Mapl']);});
The above snippet adds the Server
header to every response if the request path matched any of the defined patterns.
Note that middlewares share the same limitation as handlers, as if a middleware function returns a
Promise object it must be marked as an async
function.
Setters
Setter is a type of middleware that its returned value will be attached to the Context object.
// 'c.date' is now the current dateapp.set('date', () => new Date());
The value can be used in any handler or middleware after it:
// Chaining should be used so you get type hintapp .set('date', () => new Date()) .get('/time', (c) => `Current time: ${c.date.toUTCString()}`);
Errors
Mapl uses a much lighter and faster error implementation based on safe-throw
.
To handle exceptions, use app.err
:
import * as st from 'safe-throw';
// Error type is inferred based on previous middlewaresapp.err((error, c) => { c.status = 400; return st.payload(error);});
Exceptions are meant to be used with validators and parsers to handle edge cases.
Validators
Validator is a type of middleware to validate requests.
import * as st from 'safe-throw';
const bodyTooShort = st.err('Body too short');
app.check(async (c) => { const body = await c.req.text();
if (body.length < 9) return bodyTooShort;});
If an exception is returned, the correct exception handler will be called.
If no exception handler is registered for that error (including the handler for all exceptions),
a 400 Bad Request
response will be returned.
Parsers
Parsers can return exceptions like validators, but if the return value is anything other than an exception it gets attached to the context.
const invalidAuthHeader = st.err('Invalid Authorization header');
// Chaining should be used so you get type hintapp .parse('token', (c) => { const authHeader = c.req.headers.get('authorization');
// Get the bearer token return authHeader === null || !authHeader.startsWith('Bearer ') ? invalidAuthHeader // Return the value to be attached to the context : authHeader.slice(7); }) .get('/', (c) => `Your token: ${c.token}`)
// Handle returned errors .err((error, c) => { c.status = 403;
// Return the text of the error return st.payload(error); });