【问题标题】:Redux Toolkit RTK-Query Cors issueRedux Toolkit RTK-Query Cors 问题
【发布时间】:2023-01-15 15:13:45
【问题描述】:

我正在尝试从位于此处的公共 Deezer Api 获取数据:https://api.deezer.com/

为了获取该数据,我正在使用来自 reduxtoolkit 的 RTK-Query,就像这样(然后使用我从每个端点获得的钩子在我的组件中使用它):

export const deezerApi = createApi({
    reducerPath: 'deezerApi',
    baseQuery: fetchBaseQuery({ baseUrl: 'https://api.deezer.com/', 
    mode: "cors", ==> enable cors here
    prepareHeaders: (headers) => {
      headers.set('Access-Control-Allow-Origin', '*') ==> what i tried but still not working
      // headers.set('Access-Control-Allow-Methods', 'GET') //
      // headers.set('Access-Control-Allow-Headers', '*') //
      return headers
    },
  }),
    
    endpoints: (builder) => ({

      
      getChartArtists: builder.query({
        query: () => `chart/artists`,
      }),

// More endpoints 

    }),
    
  })

这是我得到的错误:

CORS 策略已阻止从来源“http://localhost:3000”访问“https://api.deezer.com/chart/albums”:对预检请求的响应未通过访问控制检查:否请求的资源上存在“Access-Control-Allow-Origin”标头。如果不透明响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源

无论我是否添加这行代码,我都会收到此错误:

headers.set('Access-Control-Allow-Origin', '*')

当我查看网络控制台时,它似乎已添加到我的请求标头中......

有没有人发生了什么事或有解决办法?

谢谢你的帮助 !

【问题讨论】:

    标签: javascript reactjs redux redux-toolkit rtk-query


    【解决方案1】:

    CORS 标头是响应标头,而不是请求标头。这意味着服务器必须在响应时设置它们,而不是客户端在请求资源时设置它们。或者:你不能设置它们。 CORS 是一种由服务器控制允许与它交谈的人的方法。

    您可以做的是首先启用 CORS。将 mode: "cors" 添加到您的 fetchBaseQuery 参数中。

    【讨论】:

    • 感谢您的回答 !我尝试启用在我的问题中编辑的 cors,但它似乎不起作用,我仍然遇到相同的错误
    • deezer 很可能只是不允许其他网页访问他们的 api。在那种情况下,您无法直接访问他们的 api,如果没有第三方在代理服务器端播放,就没有办法解决这个问题。这个答案似乎暗示了类似的东西:*.com/a/45486594/2075944
    • Deezer 自己有点暗示:support.deezer.com/hc/en-gb/articles/…“我的身份验证令牌请求因 CORS 而被阻止。为什么?” “您似乎正试图通过另一个域上的 Javascript 进行调用。如果您希望在 JavaScript 实现中使用我们的 API,请使用我们的 Javascript SDK。”
    【解决方案2】:

    如果您确定您的后端已在开发模式下为所有域启用 CORS,您可能需要像这样调整您的 fetchBaseQuery 凭据:

    import { fetchBaseQuery } from "@reduxjs/toolkit/query";
    import type { BaseQueryFn, FetchArgs, FetchBaseQueryError } from "@reduxjs/toolkit/query";
    import { API } from "../common/const";
    
    const baseQuery = fetchBaseQuery({
        baseUrl: API.BASE_URL,
        // crendentials: "include" will face CORS if credential is not provided
        credentials: "same-origin", 
        prepareHeaders: (headers) => {
            const accessToken = localStorage.getItem("token");
            if (accessToken) {
                headers.set("authorization", `Bearer ${accessToken}`);
                headers.set("Content-Type", "application/json");
            }
    
            return headers;
        },
    });
    
    export const baseQueryWithReauth: BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError> = async (
        args,
        api,
        extraOptions
    ) => {
        return await baseQuery(args, api, extraOptions);
    };
    

    【讨论】: