You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:18:22