为一个请求接收两个http响应

时间:2018-02-22 01:13:56

标签: javascript node.js reactjs express redux

我在一个端口上有一个快速应用程序,在另一个端口上有一个反应应用程序我的快递应用已启用cors并通过Passport验证用户身份。这是有效的,当我通过我的反应应用程序点击登录路线时,我被带到推特,提示并重定向到我的反应应用程序。但是在返回我的反应应用程序后,我的快递应用程序出现了一个404错误。当我刷新页面时,我收到正确的200状态和用户JSON对象,该对象存储在我的快递应用程序中的会话上。

这就是事情变得奇怪的地方。如果我再次刷新,在我的快速应用程序控制台中,我得到200(使用正确的用户),然后立即出现404错误(没有用户信息)。在我的反应应用程序控制台上,我看到我只对我的函数进行了一次调用,该函数向快递应用程序发送请求。

这是我的快递应用代码

var app = express()

app.use(require('morgan')('combined'))
app.use(require('cookie-parser')())
app.use(require('body-parser').urlencoded({ extended: true }))
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }))

app.use(passport.initialize())
app.use(passport.session())

app.use(cors())

app.get('/getUser',
  function (req, res, next) {
    if (req.user) {
      req.session.user = req.user
      return res.status(200).send(req.user)
    } else {
      next()
    }
  }
) 

以下是我在反应应用中提出请求的方法。 loginWithTwitter从redux存储调度,并在我的react组件中的componentDidMount内调用。

export function loginWithTwitter () {
  return function thunk (dispatch) {
    console.log('run once')
    axios({
      method: 'get',
      url: 'http://localhost:8080/getUser',
      responseType: 'json',
      headers: {'Accept': 'application/json'}
    })
      .then(res =>
        res.data
      )
      .then(user => {
        const action = twitterLogin(user)
        dispatch(action)
      })
      .catch(console.error())
  }
}

一些没有意义的怪癖:

  • 如果我使用代理而不是启用CORS,那么整个过程完全正常(无需刷新且没有404错误)。如果我在safari / chrome
  • 中禁用CORS检查,它也可以工作
  • 即使我在浏览器中使用代理或禁用CORS,我仍会收到双重http响应,但双重调用都会返回200并返回正确的数据。
  • 这让我相信这是一个问题,我如何调用我的函数,也许在其中一个调用中间CORS头没有从中间件正确设置或服务器不知道如何处理连续调用。但是我显然没有两次调用loginWithTwitter,因为我已经记录了它以检查通话数。

为什么会这样?

编辑:这是我的快速控制台中的双重响应。请注意它们是如何在一秒内完成的。

::1 - - [22/Feb/2018:01:00:18 +0000] "GET /getUser HTTP/1.1" 200 9135 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Safari/604.1.38"
::1 - - [22/Feb/2018:01:00:19 +0000] "GET /getUser HTTP/1.1" 404 20 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Safari/604.1.38"

以下是我的请求的请求标头

Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9
Connection:keep-alive
content-type:application/json; charset=utf-8
Host:localhost:8080
Origin:http://localhost:3000
Referer:http://localhost:3000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36

1 个答案:

答案 0 :(得分:0)

这是由于标题的设置方式。它正在触发预检但是通过我的中间件启用预检并没有帮助。我最后做的是,令人难以置信的hacky并且仍然没有解释问题,如果使用OPTIONS方法(在发送预检请求时触发),则调用next()。这会导致调用下一个相关方法,在这种情况下,这将是我的getUser路由。

  if (req.method == 'OPTIONS') { res.send(200) }

  next()