Skip to content

Handlers

A handler is a function that recieves a Context object and return a response.

As in previous examples, handlers can return anything that is supported by the Response constructor.

app.get('/', () => 'Hi');

The handler can access the Context object, which contains the original request object and response options.

app.get('/', (c) => {
// Set status code. Default value is 200
c.status = 201;
// This property is not set by default as it's not frequently used
c.statusText = 'Hi';
// Add a header pair
c.headers.push(['Server', 'Mapl']);
});

Note that response headers are stored as key-value pairs in an array.

Why store headers in an array instead of an object?

To have multiple header values, the headers need to be appended later to the Headers object of the final Response, which is much slower than arrays and objects as Headers has to do additional operations to normalize the header key and value on insertion.

Furthermore, JS engines often create internal structures for optimizing property accesses, which leads to more memory being used compared to arrays.

Mapl also includes handlers to send different types of data.

  • To return HTML directly without appending headers:

    app.get('/page/*', {
    type: 'html',
    fn: (c) => `<p>${c.params[0]}</p>`
    });

    This is in fact faster than writing it using normal handlers (try to see it yourself :]).

  • To return JSON directly without appending headers:

    app.get('/info/*', {
    type: 'json',
    fn: (c) => ({
    name: c.params[0],
    id: Math.random()
    })
    });

    This is also faster than writing it using normal handlers, as it uses the same optimization as HTML handlers.

  • To return static content:

    app.get('/', {
    type: 'static',
    body: 'Hi',
    options: { status: 200 }
    });

    The body and options get cached under the hood to reduce unnecessary operations on every request.

If the handler function returns a Promise object, it must be marked as an async function for the compiler to detect and generate correct code.

Prebuilts

This feature runs the handler with a sample GET request to the corresponding path, the result Response is cached and served later in request time.

app.build('/', () => 'Hi');

You can do any expensive operations inside the handler without affecting request performance.

app.build('/', (c) => {
const result = runExpensiveOperation(c.req);
return `Your result: ${result}`;
});

This is designed to mimic Bun static routes behavior, which means HEAD and OPTIONS methods are also handled automatically.

You can also make it runs faster in Bun by handing the routes to Bun directly:

const result = await jitc(app, {
exposeStatic: true
});
result.static;