Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to recover the modification of Middleware #4157

Closed
wll8 opened this issue Jan 13, 2020 · 4 comments
Closed

How to recover the modification of Middleware #4157

wll8 opened this issue Jan 13, 2020 · 4 comments
Labels

Comments

@wll8
Copy link

wll8 commented Jan 13, 2020

How to recover the modification of Middleware ?

I'm using the proxy function, but before the proxy, I want to use middleware to get the content in the body easily

let REQ_RAW = {}
server.use((req, res, next) => {
  REQ_RAW = cloneDeep(req)
  next()
})

server.use(middlewares) // I want to get the parsed content here, e.g. bodyParser
server.use((req, res, next) => {
  req = REQ_RAW
  next()
})

// server.use(other)  
// Then use the `original request` to continue execution, such as proxy
// In fact, the req obtained here is the content processed by middlewares middleware
@wesleytodd
Copy link
Member

Hi @wll8, the approach you show above will not work as you expect. There are a few issues:

  1. REQ_RAW would be shared between concurrent requests, so what you get later could be the request from another user
  2. assigning to req does not mutate what the caller has, which is what calls the next middleware
  3. clone deep on this is a HUGE perf issue

Can I ask you why you want to "recover" the raw body?

If you have a really good reason which cannot be done in another way, here is one approach to this problem:

server.use((req, res, next) => {
  const rawBody = req.body
  bodyParser.json(req, res, (err) => {
    req.body = rawBody
    next(err)
  })
})

@wll8
Copy link
Author

wll8 commented Jan 15, 2020

Thank you. @wesleytodd

Can I ask you why you want to "recover" the raw body?

My original idea was:
How do I know the content of the request I forwarded to the proxy server? For example, file, body, query, even params.
I want to use the features of middleware to get these contents, because they are more convenient.

// Some requests are forwarded to the target server, which requires the original request
server.use(proxy('/api', {
  target: 'http://www.example.org',
  onProxyReq: (proxyReq, req, res) => {
    // I want to parse the `req` through middleware here, the purpose is to make it easy for me to get what is forwarded
    // But do not want to change the content of the `req`. Because the target server needs the original `req` content.
  },
}))

// For requests that do not need to be forwarded, use middleware to easily obtain the content of the request
server.use(middlewares)
server.post('/file/upload', () => {})

I tried the following scenarios:

The target server needs the original request

server.use([...middlewares, (req, res, next) => {
  req.body // The `middlewares` are used to easily obtain the `body`
  // But unfortunately, because `req` was parsed by the middleware, the proxy target server does not accept this request.
  next()
}])
server.use(proxy())

Try using server2

server.use('*', server2)
server2.use([...middlewares, (req, res, next) => {
  req.body // I thought the new `server2` would no longer affect` server`
  next()
}])
server.use(proxy())  // Unfortunately, In fact, the `req` obtained here is the content processed by middlewares middleware

Try to copy the original request

let REQ_RAW = {}
server.use((req, res, next) => {
  REQ_RAW = cloneDeep(req)
  next()
})

server.use(middlewares) // I want to get the parsed content here, e.g. bodyParser
server.use((req, res, next) => {
  req = REQ_RAW
  next()
})
server.use(proxy()) // Unfortunately, In fact, the `req` obtained here is the content processed by middlewares middleware

On gitter, no one replied to my questions T_T.

bodyParser.json(req, res, () => {})

I worry that some middleware does not provide callbacks.

@jonchurch
Copy link
Member

If I understand correctly, your issue is that using the typical bodyParser middlewares mutates the request that passes through it? You want to send the intact request to your proxy, the request as it is before it passes through body-parser. But you also want to log/inspect the request on your server as well, so you want to serialize the request into something you can work with, like the body-parser middleware does.

I found some issues on other repos where others have had similar issues (working with body-parser and express proxy)
chimurai/http-proxy-middleware#320
chimurai/http-proxy-middleware#299

And finally here is an implementation which re-streams the request body to the proxy after it has been parsed by body-parser
https://github.com/http-party/node-http-proxy/blob/9bbe486c5efcc356fb4d189ef38eee275bbde345/examples/middleware/bodyDecoder-middleware.js

@wll8
Copy link
Author

wll8 commented Jan 18, 2020

Thank you. I found a simple solution

server.use((req, res, next) => {
  // Method 1
  // middlewaresObj from jsonServer.defaults
  middlewaresObj.jsonParser(req, res, () => {
    console.log('req.body', req.body)
  })
  next()

  // // Method 2
  // const bodyParser = require('body-parser')
  // bodyParser.json({
  //   limit: '10mb',
  //   extended: false
  // })(req, res, () => {
  //   console.log('req.body', req.body)
  // })
  // next()
})
server.use(proxy())

If you need more methods, you can refer to these links:

@wll8 wll8 closed this as completed Jan 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants