Node.js与Express: 如何重定向POST请求

56

我想要将一个URL请求重定向到另一个“POST”请求,就像这样:

var app = require('express')();

app.get('/', function(req, res) {
  res.redirect('/test');
});

app.post('/test', function(req, res) {
  res.send('/test page');
});

app.listen(3000, function() {
  console.log('listenning on port:3000');
});

但是我无法重定向到“/test”页面,因为它是一个POST请求。
那么,我应该怎么做才能使重定向工作,并保持“/test”请求的POST方式?


我对“页面”这个术语有点困惑,您是要从一个端点重定向到另一个端点吗?例如,将 / 的 {GET} 请求重定向到 /test 的 {POST} 请求。 - Samuel Toh
抱歉造成困惑。我的意思是从“localhost:3000/”重定向到“localhost:3000/test”。 - neolicd
5个回答

95

你可以这样做:

app.post('/', function(req, res) {
  res.redirect(307, '/test');
});

保留send方法的方式是使用307临时重定向HTTP状态码:

307临时重定向(自HTTP / 1.1起)。 在这种情况下,应该使用另一个URI重复请求,但是将来的请求仍然可以使用原始URI。与303相比,重新发出原始请求时不应更改请求方法。例如,必须使用另一个POST请求重复POST请求。

更多信息请参见:http://www.alanflavell.org.uk/www/post-redirect.html


明白了。如果我使用app.get('/'),那么我就不能重定向到app.post('/test'),对吗? - neolicd
1
不使用标准的HTTP重定向,您需要设置某种代理。 - ldg
2
这个解决方案强制执行另一个浏览器请求。服务器指示浏览器,浏览器然后发出另一个请求。这是一种迂回的方法。无论如何,我是否可以直接在Express中重定向,而不必一路到浏览器发出请求? - Koder
1
@Koder - 如果你在Express/Node中进行操作(而不更改URL),那么这并不是真正的重定向,因此你可以使用代理。如果你有具体问题,最好提出一个新问题,并提供你情况的详细信息。 - ldg
@Koder - 如果您打算在服务器内处理端点,您可以进行内部重新路由 - 即重新进入路由器。 - Radagast the Brown
显示剩余2条评论

6
记住中间件架构:每个处理程序都可以操作上下文,并且要么响应,要么调用 next()
按照这个前提,Express路由器基本上是一个中间件函数,您可以在“修正”URL后使用它。
(顺便说一下,请求应用程序也是一个函数,尽管我不确定是否建议在链条的早期返回)
以下是一个示例:
const router = new require('express').Router()
const user = require('../model/user') 
//assume user implements:
//  user.byId(id) -> Promise<user>
//  user.byMail(email) -> Promise<user>

const reqUser = userPromise => (req, res, next) =>
   req.user
     ? next()
     : userPromise(req)
       .then(user => { req.user = user })
       .then(next, next)
//assume the sever that uses this router has a 
//standard (err, req, res, next) handler in the end of the chain...

const byId = reqUser( req => user.byId(req.params.id) )
const byMail = reqUser( req => user.byMail(req.params.mail) )

router.post('/by-id/:id/friends',
  byId,
  (req, res) => res.render('user-friends', req.user)
)

router.post('/by-email/:email/friends',
  byMail,
  (req, res, next) => {
     req.url = `/by-id/${req.user.id}/friends`
     next()
  }, 
  router
)

1
这个对于使用单个函数中的Express路由的Firebase函数对我有效。 - Javascript Hupp Technologies

5

4

我相信问题在于节点服务器接收到POST请求,但需要将其重定向为GET请求发送到另一台服务器。我最近也遇到了类似的情况。这是我的解决方法:

var proxy = require('express-http-proxy');

app.use('incomin/url', proxy('forwarding:server', {
    //The proxyRqDecorator allows us to change a few things including the request type.

proxyReqOptDecorator: (proxyReqOpts, srcReq) => {
    proxyReqOpts.method = 'GET';
    return proxyReqOpts;
},

//The proxyReqPathResolver takes the Given URL and updates it to the forward path
proxyReqPathResolver: function (req) {
    return new Promise( (resolve, reject) => {
        setTimeout( () =>{
            var value = req.body.key;
            var resolvedPathValue = 'forwarding/url' + value;
            console.log(`Inside forward path. The resolved path is ${resolvedPathValue}`);
            resolve(resolvedPathValue);
        }, 200);
    });
}
}));

请记住,上述的proxyReqPathResolver是异步设置的。关于express-http-proxy的同步版本和更多信息,请参见此处: https://www.npmjs.com/package/express-http-proxy


0
这些天我也会考虑使用代码 308 进行重定向,例如使用 express
app.post('/', (req, res) => res.redirect(308, '/graphql'));

根据文档308不仅保留了HTTP方法,还表明这是一个永久重定向。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接