我正在重新表述我之前提出的这个问题,并提供更多信息,希望能够清楚地了解为什么会发生这种奇怪的行为。
我正在构建一个 NextJS 项目。如果我尝试使用 API 的几个给定路由,例如 login
和 logout
,我很快就会看到一些意想不到的结果
步骤:
api/users/login
发送“POST”请求第一反应:
//Comes from createAndSendToken util method -- expected result of login API call
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYwYjZkNTVlZGRkYTEzNWFlMzZiMTk2YSIsImlhdCI6MTYyNzMxMzc0MCwiZXhwIjoxNjMyNDk3NzQwfQ.fb-kpSbpngSJfAJxDDbi7xbItTfSv1Ha8FMnsGBe9Dg",
"user": {
"id": "60b6d55eddda135ae36b196a",
"role": "admin",
"name": "admin",
"email": "admin@test.com"
}
}
控制台输出:
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info - Loaded env from /home/john/code/projects/current/next-with-api/.env.local
info - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
event - compiled successfully
event - build page: /api/users/login
wait - compiling...
event - compiled successfully
步骤,续
api/users/logout
发送“POST”请求第二反应:
//Comes from api/users/logout -- correct response for this API call
{
"success": true,
"message": "logged out"
}
控制台输出
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info - Loaded env from /home/john/code/projects/current/next-with-api/.env.local
info - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
event - compiled successfully
event - build page: /api/users/login
wait - compiling...
event - compiled successfully
event - build page: /api/users/logout
wait - compiling...
event - compiled successfully
步骤,续
api/users/login
发送“POST”请求预期结果:
与上面的第一个响应相同的响应。响应应该来自 createAndSendToken
函数。
实际结果
响应来自 logout
API 路由,即使请求未发送到此端点。请求已发送至 api/users/login
,因此不应从 api/users/logout
端点运行代码。
第三次回应:
{
"success": true,
"message": "logged out"
}
控制台输出:
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info - Loaded env from /home/john/code/projects/current/next-with-api/.env.local
info - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
event - compiled successfully
event - build page: /api/users/login
wait - compiling...
event - compiled successfully
event - build page: /api/users/logout
wait - compiling...
event - compiled successfully
请注意,在上面的控制台输出中,最近构建的页面是 logout
--> 值得注意,因为我收到来自 logout
的响应而不是预期的 login
.. . 预期的行为是,当我向指定的 API 端点(在本例中为 api/users/login
,服务器将运行事件 > build page: /api/users/login
> 并且我将收到来自那里。相反,这似乎并没有发生,而且我从最近构建的页面收到了我的回复 - api/users/logout
- 这没有任何意义,也不是我所期望的。
登录文件:
const handler = nc.use(dbConnect).post(async (req, res) => {
const { email, password } = req.body
if (!email || !password) {
res.status(400).json({
success: false,
message: 'Email and password required.',
})
}
const user = await User.findOne({ email }).select('+password')
if (!user || !(await user.correctPassword(password, user.password))) {
res.status(401).json({
success: false,
message: 'Incorrect email or password',
})
} else createAndSendToken(user, 200, req, res)
})
注销文件:
const handler = nc.post((req, res) => {
const cookies = new Cookies(req, res)
cookies.set('jwt', 'logged_out', {
expires: new Date(Date.now() + 10 * 1000),
httpOnly: true,
})
res.status(200).json({
success: true,
message: 'logged out',
})
})
createAndSendToken
实用函数
export const createAndSendToken = (user, statusCode, req, res) => {
const token = signToken(user._id)
const cookies = new Cookies(req, res)
const cookieOptions = {
expires: new Date(Date.now() + process.env.JWT_COOKIE_EXPIRES_IN * 1000),
httpOnly: true,
}
if (process.env.NODE_ENV === 'production') cookieOptions.secure = true
cookies.set('jwt', token, cookieOptions)
user.password = undefined
const { id, role, name, email } = user
res.status(statusCode).json({
success: true,
token,
user: {
id,
role,
name,
email,
},
})
}
请注意,如果我颠倒顺序也会发生这种情况,并且我的应用程序中的其他 API 路由可能也会发生这种情况。例如,有时当我在最近登录后尝试退出时,我会收到来自 api/users/login
而不是预期的 api/users/logout
的响应。
另请注意,无论我使用什么客户端,都会发生这种情况。我首先在浏览器中注意到了这种行为,但我也一直使用 Postman 重新创建它。在客户端,我可以验证请求是否被发送到正确的端点。在服务器端,请求被错误的处理程序处理的地方似乎发生了一些奇怪的事情。
最后请注意,这与 React 文件无关。如果您查看项目,请忽略这些。我创建了一个 git 分支,并在其中删除了那些并严格仅与 API 交互,但仍然遇到此问题。
其他环境注意事项:
有人遇到过这种情况吗?我应该完全重新考虑我的整个 API 吗?我在使用 NextJS 时做错了什么吗?看起来这应该是构建 API 的合适方法,而且我当然希望能够可靠地使用这些端点。我真的很困惑为什么会这样。