【发布时间】:2024-01-24 11:16:01
【问题描述】:
我在一个端口上有一个 express 应用,在另一个端口上有一个 react 应用。我的 express 应用程序启用了 cors 并通过 Passport 对用户进行身份验证。这有效,当我通过我的反应应用程序点击登录路线时,我被带到 twitter,提示并重定向到我的反应应用程序。但是,在返回我的反应应用程序后,我从我的快速应用程序中收到一个 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()
}
}
)
这就是我在我的 react 应用程序中提出请求的方式。 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
【问题讨论】:
-
是一个请求
OPTIONS请求,然后下一个是GET- 这称为 CORS 预检 - 它不是一个请求的两个响应,而是两个不同请求的两个响应 -
@JaromandaX 它们都是 GET 请求。并且不应该对 GET 请求进行任何预检检查。我也尝试过在 CORS 中间件中禁用 preflight-continue 并遇到类似问题。我将使用我的快速控制台结果更新原始帖子。
-
They are both GET requests- 奇怪,什么浏览器?there shouldn't be any preflight checks for a GET request你不知道 CORS:p GET/POST 可能需要预检,其他方法,预检是强制性的 - 检查你的请求标头...是否根据 CORS 触发预检文档? -
所以......是否涉及CORS?浏览器开发者工具网络标签中显示了什么?
-
@JaromandaX 所以我在使用 safari。但是,我刚刚在 chrome 中进行了测试,并意识到我在 chrome 中只收到一个 404 响应,没有 200。我可以仔细检查是否有任何 CORS 中间件默认标头触发预检。现在我必须弄清楚为什么 safari 会导致多次调用,但是 chrome、postman 甚至直接在 safari 中访问路由而不是使用我的应用程序,都不会导致多次响应。浏览器网络选项卡显示通用 404,而不是访问控制问题,这将是一个 CORS 问题。
标签: javascript node.js reactjs express redux