Skip to content

Lifecycle

Mapl request lifecycle can be illustrated as follows:

Lifecycle

Middlewares

Middlewares are functions that get executed on every request, after the route matching phase.

app.use((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 date
app.set('date', () => new Date());

The value can be used in any handler or middleware after it:

// Chaining should be used so you get type hint
app
.set('date', () => new Date())
.get('/time', (c) => `Current time: ${c.date.toUTCString()}`);

Exceptions

Exception is a much faster and lighter version of Error.

import { staticException, dynamicException } from '@mapl/app';
// This exception cannot hold payloads
const authException = staticException();
// This exception can hold payloads
const bodyException = dynamicException<string>();

To handle exceptions, use app.catch or app.catchAll:

// Handle static exception
app.catch(authException, (c) => {
c.status = 403;
return 'Forbidden!';
});
// Handle dynamic exception
app.catch(bodyException, (payload, c) => {
c.status = 400;
return `Body should be longer than 8 chars, instead recieved: ${payload}`;
});
// Handle all uncaught exceptions
app.catchAll((c) => {
c.status = 400;
return 'Bad request!';
});

Exceptions are meant to be used with validators and parsers to handle edge cases.

Validators

Validator is a type of middleware to validate requests.

app.validate(async (c) => {
const body = await c.req.text();
if (body.length < 9)
// Return the error with the payload
return bodyException.init(body);
});

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.

// Chaining should be used so you get type hint
app
.parse('token', (c) => {
const authHeader = c.req.headers.get('authorization');
// Get the bearer token
return authHeader === null || !authHeader.startsWith('Bearer ')
// You can return the static exception directly
? authException
// Return the value to be attached to the context
: authHeader.slice(7);
})
.get('/', (c) => `Your token: ${c.token}`);