4

我有一个微服务,它代理每个请求,增加一个字段。对于普通请求,这很容易,只需在request.body中添加字段并正确设置标题,但对于 multipart/form-data 请求,我从几天以来就遇到了麻烦,因为如果我在request.body中添加一个字段,它会消失。

const router = express()
const routes = require('~/routes')
const passport = require('passport')
const proxy = require('http-proxy-middleware')

router.use(passport.initialize())
require('./modules/passport-jwt')(passport)

router.use('/', routes)

router.use(
    '/account',
    passport.authenticate('jwt', { session: false }),
    proxy({
        target: process.env.ACCOUNT_SERVICE,
        pathRewrite: { '/account': '/' },
        onProxyReq: restream
    })
)

const restream = async function (proxyReq, req, res, options) {
    if (req.user) {
        if (
            req.headers['content-type'] &&
            req.headers['content-type'].match(/^multipart\/form-data/)
        ) {
            req.body.reqUser = req.user
        } else {
            const requestBody = JSON.stringify({ ...req.body, reqUser: req.user })
            proxyReq.setHeader('Content-Type', 'application/json')
            proxyReq.setHeader('Content-Length', Buffer.byteLength(requestBody))
            proxyReq.write(requestBody)
        }
    }
}

当请求到达另一个微服务时,request.body是空的,之后它将由multer写入,将 multipart/form-data 参数放入request.body

我真的需要一个解决方案,让我将一个字段附加到代理重新流功能中的 multipart/form-data 请求

我尝试了一切以取得成功,但我被困住了。我希望一切都清楚。如果您需要,请不要害怕询问更多详细信息。我在乞求你的帮助。

4

1 回答 1

8

我终于知道如何成功了。我的代码现在看起来像这样:

const router = express()
const routes = require('~/routes')
const passport = require('passport')
const proxy = require('http-proxy-middleware')

router.use(passport.initialize())
require('./modules/passport-jwt')(passport)

router.use('/', routes)

router.use(
    '/account',
    passport.authenticate('jwt', { session: false }),
    proxy({
        target: process.env.ACCOUNT_SERVICE,
        pathRewrite: { '/account': '/' },
        onProxyReq: restream
    })
)

const restream = async function (proxyReq, req, res, options) {
    if (req.user) {
        if (
            req.headers['content-type'] &&
            req.headers['content-type'].match(/^multipart\/form-data/)
        ) {
            // build a string in multipart/form-data format with the data you need
            const formdataUser =
                `--${request.headers['content-type'].replace(/^.*boundary=(.*)$/, '$1')}\r\n` +
                `Content-Disposition: form-data; name="reqUser"\r\n` +
                `\r\n` +
                `${JSON.stringify(request.user)}\r\n`

            // set the new content length
            proxyReq.setHeader(
                'Content-Length',
                parseInt(request.headers['content-length']) + Buffer.byteLength(formdataUser)
            )

            proxyReq.write(formdataUser)
        } else {
            const body = JSON.stringify({ ...req.body, reqUser: req.user })
            proxyReq.setHeader('Content-Type', 'application/json')
            proxyReq.setHeader('Content-Length', Buffer.byteLength(body))
            proxyReq.write(body)
        }
    }
}

正如我在代码注释中所写:

  1. 构建一个 multipart/form-data 格式的字符串,它必须如下所示:

    ------WebKitFormBoundaryiBtoTWFkpAG6CgXO\r\n
    Content-Disposition: form-data; name="firstname"\r\n
    \r\n\
    Andrea\r\n
    

    (在我的代码中,我对数据进行了字符串化,因为它是一个对象);

  2. 通过将上述字符串的字节长度添加到原始请求长度来设置标头“Content-Length”;

  3. 使用proxyReq.write函数发送新数据。

于 2019-10-24T07:44:23.260 回答