express icon indicating copy to clipboard operation
express copied to clipboard

Feature request: ability to set settings per response

Open bradvogel opened this issue 6 years ago • 8 comments

I'd like to implement middleware that returns formatted json in the response when pretty_ouput is present on the query. I attempted this with the following code:

  // This code does not work as expected.
  app.use(function(req, res, next) {
    // Querystring `pretty_output` should prettify json output.
    if (req.query['pretty_ouput']) {
      app.set('json spaces', 2); // I'd like to set this only for this one request.
    }
    next();
  });

However, subsequent requests without the pretty_ouput querystring are also formatted.

Is there a way to set the setting json spaces for only one request? Ideally I could call res.set('json spaces', 2) that would set this option for only this one response. I'd think this would be generically useful for any Express option.

bradvogel avatar Jan 15 '18 22:01 bradvogel

@bradvogel What if you disable the setting when the request does not contain the query string?

if (req.query['pretty_output']) {
    app.set('json spaces', 2);
} else {
    app.disable('json spaces'); // or app.set('json spaces', false)
}

graphicbeacon avatar Jan 15 '18 23:01 graphicbeacon

The above will most likely not work as you want it. This would result in a race condition between incoming requests. At the moment I think your best bet is just returning your own json response logic. Here is a reference for what the internal res.json is doing, maybe that would help:

https://github.com/expressjs/express/blob/b7817ab1b0bbadabe79fc88819c8338838ead707/lib/response.js#L239-L268

wesleytodd avatar Jan 15 '18 23:01 wesleytodd

You could do something simple like:

function sendPrettyJson (req, res, value) {
  this.set('Content-Type', 'application/json')
  var body = req.query['pretty_output'] ? JSON.stringify(value, null, 2) : JSON.stringify(value)
  res.send(body)
}  

wesleytodd avatar Jan 15 '18 23:01 wesleytodd

Yes - thanks. I know I can take over res.json and format it myself - but I'd prefer to keep using the built-in res.json and benefit from its future improvements.

Isn't there still a generic need for setting options at the response level, e.g. to temporarily disable something like x-powered-by for a single response? Or any future options that are added?

bradvogel avatar Jan 16 '18 02:01 bradvogel

There is a generic need for this, and I believe there are some issues open for this. I am at work right now and so cant dig for them, but if you search the issues and pr's you can probably find them. I do not remember if anyone has created a strong enough proposal for it to get marked for inclusion into 5.x, but feel free to do so :)

wesleytodd avatar Jan 16 '18 17:01 wesleytodd

@wesleytodd I also thought this was discussed before, but I wasn't able to locate. I think this is useful, though even just looking at the way it's used now it likely wouldn't be compatible with Express 4.x due to a few places where the settings are looked up without any references to req or res to key off of.

dougwilson avatar Jan 17 '18 03:01 dougwilson

Same, I could not find it either. I think we should add this to the 5.x road map. It should be simple enough to pass req/res to those places, and the value add is worth it IMO.

wesleytodd avatar Jan 17 '18 23:01 wesleytodd

Hi, I have investigated some open issues involving races (as a research project) and took a look at the solution of @graphicbeacon. I created a small app (https://github.com/sanji-programmer/express-issue-3536-race) and as correctly pointed out by @wesleytodd this solution is subjected to races (https://github.com/sanji-programmer/express-issue-3536-race/blob/master/express01/server-test.js). Using a tool we have developed, I could explore different callback interleavings that reveal the race.

I also verified the solution proposed by @wesleytodd (https://github.com/sanji-programmer/express-issue-3536-race/blob/master/express01/server-test-fixed.js) and this seems alright and no subjected to races.

I also noticed that modifying global settings of express may also causes races in different scenarios.

sanji-programmer avatar Sep 16 '19 10:09 sanji-programmer