BackendStack21 / restana

Restana is a lightweight and fast Node.js framework for building RESTful APIs.
MIT License
467 stars 27 forks source link

removal of response event #71

Closed timotejroiko closed 4 years ago

timotejroiko commented 4 years ago

Hello,

What is the best way to have a middleware wait for the response after the removal of the response event? Do i need to use express middlewares such as onHeaders like the response-time module does?

Thanks!

jkyberneees commented 4 years ago

Hi @timotejroiko , thanks for reaching out. Do you need this behaviour globally? Or just for a certain endpoint? You can use alternatives such as onHeaders, on-http-end, ..., you can also build your own middleware that overrides the target methods on the response object...

I kindly ask you to share your concrete use case here, so I can suggest what can work better IMO.

Thanks

timotejroiko commented 4 years ago

Hello, thanks for the reply!

I have an API which does astronomical calculations based on user input, and with version 3.x.x i was using the response event globally to measure and log performance of all endpoints, log some key results and do some database operations.

So basically i want to measure performance and ensure all requests are calculated successfully and validated before sending, like a global "before send" middleware.

Thanks a lot!

jkyberneees commented 4 years ago

Hi @timotejroiko here I have prepared an example on how to achieve what you want, also supporting an async pre-send handler. Please let me know if this satisfies your requirements:

const service = require('restana')({})

const beforeSendAsyncHook = (req, res, sendArgs) => {
  sendArgs[0] += 'Timotej Rojko'

  return Promise.resolve()
}

service.use((req, res, next) => {
  const send = res.send

  res.send = function (...args) {
    return beforeSendAsyncHook(req, res, args)
      .then(() => {
        return send.apply(res, args)
      })
      .catch(err => {
        return send.apply(res, err)
      })
  }

  return next()
})

service.get('/hi', (req, res) => {
  res.send('Hello World: ')
})

service.start()

Please notice that you would need to use the .send method to response to requests.

timotejroiko commented 4 years ago

hey @jkyberneees thanks for the response.

I followed your great example but applied it to res.end instead to allow for parsing of headers and status codes by your built in send handler.

server.use((req, res, next) => {
    let end = res.end;
    res.end = function(...args) {
        let response = {
            data:args[0],
            status:res.statusCode,
            headers:res.getHeaders()
        }
        console.log(response);
        return end.apply(res,args);
    }
    return next();
});

I might actually use both versions, a send hook for appending data and an end hook for performance metrics and logging.

Thanks a lot!

jkyberneees commented 4 years ago

I am happy that it worked out for you. Do not hesitate to get in touch again in the future if needed.