使用 express / request-promise 的条件重定向
Conditional redirect with express / request-promise
我对 express 和 request-promise 模块比较陌生,
并且需要创建一个 service S
从 serverA 调用
在 S 向 ServerB 询问一些额外信息后,
它重定向 serverA 到ServerC 的请求。
自从我得到一个
错误:发送后无法设置 headers。
尽管我自己没有添加任何东西,但我想知道有人可以帮助我直接完成这个工作流程。
这是代码:
`
const express = require('express')
const rp = require('request-promise')
...
app.get('/dispatch', cors(), (req, res, next) => {
var options = {
uri: 'https://ServerB/calc-something..',
headers: {
'User-Agent': 'its-me',
'Data': data_from_serverA
},
resolveWithFullResponse: true, // Get statuscode
json: true // Parse the JSON string in the response
};
rp(options) // Do request to serverB
.then(function (response) {
console.log(`ServerB responded with statuscode ${response.statusCode}`)
// No error, so redirect original res
res.redirect('https://serverC/...') // error occurs here
return next(response)
})
.catch(function (err) {
console.log(`ServerB responded with error ${err}`)
return next(err) // send 500 to serverA
})
})
`
您的 cors()
中间件正在设置 CORS headers。这导致 headers 在您的承诺正在解决时被发送。
重定向也会发送 headers,这就是问题所在。重定向设置了 location
header,但您已经发送了 header,因此不会起作用。
解决方案是将最终的中间件一分为二。首先,检查是否需要重定向,如果需要,则执行此操作。否则,在 req
object 上设置你需要的任何数据,并在 cors 调用后处理它。
您的最终路线将类似于:
app.get('/dispatch', checkRedirect, cors(), (req, res, next) => {
//do something useful, or send your error
})
checkRedirect 函数的内容与上面的内容非常相似。但是,您不会将数据传递给 next()
函数。这只是将控制权传递给下一个中间件。相反,将您需要的任何数据放在 req
object 上,并在最终的中间件中处理它,在 cors 之后。如果您所做的只是设置 500 错误,那么您甚至不需要 CORS。
根据@Rampant 的回答,
这就是我用 request-promise (rp):
做的
function checkPrecondition(req, res, next){
req.precondition = false
rp({ method: 'POST',
...
})
.then((data) => {
...
req.precondition = true
next()
})
.catch((data) => {
...
next()
})
}
并在 express 处理程序中:
app.post('/query', checkPrecondition, cors(), (req, res, next) => {
if(!req.precondition){
res.status(400).send(JSON.stringify({status: 'insufficient'}))
return
}
res.redirect('target.host')
})
感谢您解决 CORS 问题。
我对 express 和 request-promise 模块比较陌生, 并且需要创建一个 service S 从 serverA 调用 在 S 向 ServerB 询问一些额外信息后, 它重定向 serverA 到ServerC 的请求。 自从我得到一个 错误:发送后无法设置 headers。 尽管我自己没有添加任何东西,但我想知道有人可以帮助我直接完成这个工作流程。
这是代码: `
const express = require('express')
const rp = require('request-promise')
...
app.get('/dispatch', cors(), (req, res, next) => {
var options = {
uri: 'https://ServerB/calc-something..',
headers: {
'User-Agent': 'its-me',
'Data': data_from_serverA
},
resolveWithFullResponse: true, // Get statuscode
json: true // Parse the JSON string in the response
};
rp(options) // Do request to serverB
.then(function (response) {
console.log(`ServerB responded with statuscode ${response.statusCode}`)
// No error, so redirect original res
res.redirect('https://serverC/...') // error occurs here
return next(response)
})
.catch(function (err) {
console.log(`ServerB responded with error ${err}`)
return next(err) // send 500 to serverA
})
})
`
您的 cors()
中间件正在设置 CORS headers。这导致 headers 在您的承诺正在解决时被发送。
重定向也会发送 headers,这就是问题所在。重定向设置了 location
header,但您已经发送了 header,因此不会起作用。
解决方案是将最终的中间件一分为二。首先,检查是否需要重定向,如果需要,则执行此操作。否则,在 req
object 上设置你需要的任何数据,并在 cors 调用后处理它。
您的最终路线将类似于:
app.get('/dispatch', checkRedirect, cors(), (req, res, next) => {
//do something useful, or send your error
})
checkRedirect 函数的内容与上面的内容非常相似。但是,您不会将数据传递给 next()
函数。这只是将控制权传递给下一个中间件。相反,将您需要的任何数据放在 req
object 上,并在最终的中间件中处理它,在 cors 之后。如果您所做的只是设置 500 错误,那么您甚至不需要 CORS。
根据@Rampant 的回答, 这就是我用 request-promise (rp):
做的function checkPrecondition(req, res, next){
req.precondition = false
rp({ method: 'POST',
...
})
.then((data) => {
...
req.precondition = true
next()
})
.catch((data) => {
...
next()
})
}
并在 express 处理程序中:
app.post('/query', checkPrecondition, cors(), (req, res, next) => {
if(!req.precondition){
res.status(400).send(JSON.stringify({status: 'insufficient'}))
return
}
res.redirect('target.host')
})
感谢您解决 CORS 问题。