hckr.fyi // thoughts

Accessing Express Request Headers in a Handlebar Template

by Michael Szul on

Express is the most popular Node.JS framework for a good reason. There is a lot of power and configuration behind it. I actually prefer to use Express' little cousin Restify for most things to keep the overall cruft low, but Express has it's advantages.

Most of the members of my team at work became familiar with front-end JavaScript templates through using the Handlebars template language. As a result, when I spin up an Express instance, I often switch the view template to Handlebars using the Express-Handlebars package.

Express is very restrictive, which I love. It makes you work very hard to include code in your templates, forcing you to hide most everything behind a helper.

Sometimes, however, you need some advanced transference of variables that can be pretty difficult to architect out. For example, what if you need to access the request headers, and your handlebar templates are registered when the template engine is initialized? For example:

app.engine(".hbs", hbs({
        defaultLayout: "_layout",
        extname: ".hbs",
        helpers: require("./helpers/handlebars")
    }));
    

In templates like these, your handlebar functions will get whatever is passed in via the view, as well as the opts parameter for functions like fn and inverse when you're returning a boolean.

In this case, the Express request is not available in the view, so how do you add it without having to pass the request back to every single view rendering that needs to execute the handlebar helper?

To accomplish this, you can actually use an anonymous middleware function to create a local variable accessible in the view:

app.use(function(req, res, next) {
        app.locals.expreq = req;
        next();
    })
    

This function will make the current request data available in all Express views via the expreq variable.

We can then pass that variable to a handlebar helper in a view file. For a simple example, imagine something like an isAdmin helper that needs to read from the request headers. We can just pass the expreq variable into it:

{{#isAdmin expreq }}
        <strong>Important admin stuff here!</strong>
    {{/isAdmin}}
    

Of course, there are other ways to accomplish this too, but the quick-and-dirty of it is that you can pass data around pretty easily in Express, even when the template engine is restrictive.