Next.js 14中RTK Query遇CORS问题,Axios无此问题求解决
Next.js 14 + RTK Query 出现CORS跨域错误,Axios请求却正常的解决办法
我正在开发Next.js 14应用,使用Redux Toolkit的RTK Query时遇到CORS跨域错误:请求https://xxxxx.amazonaws.com/dev/login/admin/auth时,因响应无'Access-Control-Allow-Origin'头被浏览器拦截。但用Axios发起相同请求时没有这个问题。
我的RTK Query代码:
import { BaseQueryApi, FetchArgs, RootState, createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' import { setCredentials, logOut } from '@/store/slices/auth/authSlice' const baseQuery = fetchBaseQuery({ baseUrl: 'https://xxxxxxxxxx.amazonaws.com/dev/login/admin', method: 'POST', body: { "emailAddress": "t.m.parakrama+101@gmail.com", "password": "Visio@1234" }, credentials: 'include', prepareHeaders: (headers, { getState }) => { const token = getState().auth.token if (token) { //headers.set("authorization", `Bearer ${token}`) headers.set("x-api-key", `WhKzV4ZUxaaao8w7ytOcc5kQt169ffpQhDHQlBf4TiDrFIF`) } return headers } }) const baseQueryWithReauth = async (args, api, extraOptions) => { let result = await baseQuery(args, api, extraOptions) if (result?.error?.originalStatus === 403) { console.log('sending refresh token') const refreshResult = await baseQuery('/refresh', api, extraOptions) console.log(refreshResult) if (refreshResult?.data) { const user = api.getState().auth.user api.dispatch(setCredentials({ ...refreshResult.data, user })) result = await baseQuery(args, api, extraOptions) } else { api.dispatch(logOut()) } } return result } export const apiSlice = createApi({ baseQuery: baseQueryWithReauth, endpoints: builder => ({}) })
CORS错误信息:
https://xxxxx.amazonaws.com/dev/login/admin/auth' from origin 'http://localhost:3001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
我的Axios代码(无CORS问题):
const axios = require('axios'); const baseQuery = async (getState) => { // Extract the token from the state const token = getState().auth.token; // Prepare the headers const headers = { 'Content-Type': 'application/json', }; if (token) { // headers['Authorization'] = `Bearer ${token}`; headers['x-api-key'] = 'WhKzV4ZUxo8wzxc7ytO5kQt169pQhDHQzxclBf4TiDrFIF'; } // Make the POST request using Axios try { const response = await axios.post( 'https://xxxxxxx.amazonaws.com/dev/login/admin', { emailAddress: 't.m.parakrama+101@gmail.com', password: 'Visio@1234', }, { headers: headers, withCredentials: true, } ); return response.data; } catch (error) { console.error('Error making request:', error); throw error; } }; // Example usage: // Assuming you have a function to get the state const getState = () => ({ auth: { token: 'your_token_here', // Replace with actual token retrieval logic }, }); // Call the baseQuery function with the state baseQuery(getState).then(data => { console.log('Response data:', data); }).catch(error => { console.error('Request failed:', error); });
问题根源
对比两段代码,核心差异是RTK Query的fetchBaseQuery配置错误:你把method、body这类请求专属参数写在了全局baseQuery配置中,导致RTK Query发送OPTIONS预请求时也携带了这些内容,触发了服务器更严格的CORS校验;而Axios是在具体请求中指定这些参数,预请求不会包含额外内容,因此能通过校验。
具体修复步骤
1. 修正fetchBaseQuery的全局配置
只保留通用配置项,移除method、body:
const baseQuery = fetchBaseQuery({ baseUrl: 'https://xxxxxxxxxx.amazonaws.com/dev/login/admin', credentials: 'include', prepareHeaders: (headers, { getState }) => { const token = getState().auth.token if (token) { // headers.set("authorization", `Bearer ${token}`) headers.set("x-api-key", `WhKzV4ZUxaaao8w7ytOcc5kQt169ffpQhDHQlBf4TiDrFIF`) } return headers } })
2. 创建具体的登录Endpoint
在createApi中定义登录请求,把method、body移到这里:
export const apiSlice = createApi({ baseQuery: baseQueryWithReauth, endpoints: builder => ({ login: builder.mutation({ query: (credentials) => ({ url: '/auth', // 拼接baseUrl后得到完整接口地址 method: 'POST', body: credentials // 传入登录参数 }) }) }) }) // 导出自动生成的Hook export const { useLoginMutation } = apiSlice
3. 在组件中调用登录接口
使用生成的Hook发起请求:
// 登录组件示例 const [login, { isLoading, error }] = useLoginMutation() const handleLogin = async () => { try { const result = await login({ emailAddress: "t.m.parakrama+101@gmail.com", password: "Visio@1234" }).unwrap() // 处理登录成功逻辑 } catch (err) { // 处理错误 } }
4. 额外注意
确保baseQueryWithReauth中调用的/refresh接口也支持CORS,否则刷新token时会出现同样的跨域问题。
内容的提问来源于stack exchange,提问作者Nuwan Chamikara
相关产品推荐
相关产品推荐

