-
Notifications
You must be signed in to change notification settings - Fork 13
Working with controllers
Alakajam uses the Express web framework.
The entry point of all routes is the controllers/index.js
file. For instance, the following code registers the maincontroller.events(req, res)
method to be called everytime a user reaches the /events
URL:
router.all('/events', mainController.events)
When entering the events(req, res)
method, we will have access to everything we need about:
- The request (
req
), in particular the query parameters (req.query
) and form fields (req.body
) ; - The response (
res
), mostly to access context info (eg.res.locals.user
,res.locals.event
) and trigger the rendering of a pageres.render(templateName, context)
.
Typically, a controller has the following structure:
myController(req, res) {
// Read the request parameters
// Make relevant security checks
// Sanitize form data if needed (see core/forms.js)
// Call one or more services to gather/process data
// Render a page
}
Note that controllers are not meant to hold complicated algorithms nor database requests, instead delegating them to the services (see services/
folder).
Before the web requests even reach your controller, the res.locals
object is pre-filled with relevant variables according to the context. For instance, if the request comes from a logged user, res.locals.user
is always set for you.
This is made possible by registering request "filters" or "middleware" used to avoid code repetition:
router.use('*', mainController.anyPageMiddleware)
This special route means that mainController.anyPageMiddleware(req, res, next)
will be called for every single page request to the server. And that's where we set up data like res.locals.user
.
ℹ️ You may notice that controllers and filters are both registered the same way. Technically, for Express, they are both middleware. The only difference is how
anyPageMiddleware
hasnext
in its signature, meaning you can callnext()
from it to forward the request to any other middleware. Controllers on the other hand never callnext()
, making them the final handlers. Make sure in your controllers that all scenarios end with ares.render
orres.errorPage
, otherwise the request will hang forever.
If an error is thrown from your code, it will be caught appropriately and rendered as a 500 error page. You can also trigger error pages manually (eg. for "404 Not found" or "401 Forbidden" errors) by calling res.errorPage(code, error)
(*) instead of res.render()
.
If you're curious, this is made possible by custom methods and a special error handling middleware set up in core/middleware.js
.
(*)
res.errorPage
is not standard Express code but a homemade extension.