44

In express.js, I would like to provide an additional attribute on the request object for each of my URI listeners. This would provide the protocol, hostname, and port number. For example:

app.get('/users/:id', function(req, res) {
  console.log(req.root); // https://12.34.56.78:1324/
});

I could of course concatenate req.protocol, req.host, and somehow pass around the port number (seems to be missing from the req object) for each one of my URI listeners, but I'd like to be able to do it in a way that all of them could access this information.

Also, the hostname can vary between request (the machine has multiple interfaces) so I can't just concatenate this string when the application launches.

The goal is to provide URI's to the consumer which point to further resources in this API.

Is there some sort of way to tell Express that I want req objects to have this additional information? Is there a better way to do this than what I'm outlining?

0

5 Answers 5

77

You can add a custom middleware that sets the property for each request:

app.use(function (req, res, next) {
    req.root = req.protocol + '://' + req.get('host') + '/';
    next();
});

Using req.get to obtain the Host header, which should include the port if it was needed.

Just be sure to add it before:

app.use(app.router);
2
  • @AdamPietrasiak it is not constant, if you have more than one domain (for example 'your-app.com', 'your-app.com.ar' and 'your-app.com.br'), it will be necessary to check the domain for each request. Commented Aug 27, 2016 at 5:50
  • app.router is deprecated btw
    – Thecave3
    Commented Mar 30, 2020 at 17:00
37

You can extend the express.request prototype.

3
  • like require("express").request.prototype.foo = function(){} ?
    – redben
    Commented Dec 6, 2013 at 11:11
  • Extend express.request just don't apply in this case, unless for some reason https on his root property never change, otherwise you need to use a middleware and get req.protocol... Anyway, if you want to extend request (and thats actually why I found this question) just use express.request.getFooParam = function () { return this.param('foo'); }
    – neiker
    Commented Jul 31, 2014 at 1:33
  • Exactly what I was looking for. Logged in to give a thumbs up, no need for middleware when you can go to the root and extend the prototype. Commented Oct 18, 2014 at 15:03
9

The best way to modify the request object is to add your own middleware function before the app.router declaration.

    app.use(function(req, res, next){
      // Edit request object here
      req.root = 'Whatever I want';
      next();
    });
    app.use(app.router);

This will modify the request object and every route will be able to access req.root property, so

    app.get('/',function(req, res, next){
      console.log(req.root); // will print "Whatever I want";
    });
4

You can use a middleware. Add this to your app.configure block:

app.use(function (req, res, next) {
  req.root = 'WHAT YOU WANT';
  next();
});

Every request will go tough this function, and afterwards go to the right url-block thanks to next().

0

Express was designed to support this in the response object, not the request. The response object support custom variables in res.locals. See http://expressjs.com/en/4x/api.html#res.locals

This is particularly useful for typescript users. The locals property is typed Record<string, any>

2
  • 1
    This has nothing to do with the question. We are looking for ways to modify request object.
    – olegario
    Commented Jul 11, 2021 at 18:39
  • 1
    res.locals says it is for template rendering... PassportJS, for example, updates the request to add a user field, so this is definitely not correct. Commented Nov 18, 2022 at 16:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.