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

GraphQL(Nodejs+Reactjs)跨域CORS错误排查求助

解决你的CORS配置错误问题

先看你遇到的错误:

Access to fetch at 'http://localhost:4000/' from origin 'http://localhost:3000/' has been blocked by CORS policy: 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.

这个错误的核心是服务器没有正确返回CORS允许的响应头,你的配置里有两个关键错误,分别在服务器和客户端代码里,我来帮你逐个修复:


一、服务器端的配置错误

你的GraphQL Server配置里有两处写法错误:

1. 配置项名称写错 + CORS origin格式错误

GraphQLServer的构造函数里,CORS配置应该放在options字段(注意是复数),而不是opt;另外origin的写法错误,你写成了{['http://localhost:3000/']}(一个包含数组的对象),正确的格式应该是字符串或者数组。

2. server.start的参数传递错误

server.start方法不需要单独传opt变量,构造时的配置会自动生效,或者你也可以在这里覆盖配置。

修改后的服务器代码:

import { GraphQLServer } from 'graphql-yoga'
import { prisma } from './generated/prisma-client'
import resolvers from './resolvers'

const server = new GraphQLServer({
  typeDefs: './src/schema.graphql',
  resolvers,
  context: request => ({
    ...request,
    resolverValidationOptions: { requireResolversForResolveType: false },
    prisma,
  }),
  // 正确配置CORS:使用options字段,origin设置为允许的域名
  options: {
    cors: {
      credentials: true,
      origin: 'http://localhost:3000' // 单个域名用字符串,多个域名可以传数组:['http://localhost:3000', 'https://your-prod-domain.com']
    }
  }
})

// start方法直接启动即可,无需额外传配置
server.start(() => console.log(`Server is running on http://localhost:4000`));

二、客户端的配置错误

你在authLink里添加了Access-Control-Allow-*系列请求头,这是完全错误的:

这些Access-Control-Allow-*头是服务器响应给浏览器的,用来告诉浏览器允许哪些域名、方法访问资源,客户端发送请求时不需要添加这些头,反而会导致预检请求失败。

另外你的ApolloClient链路拼接也有问题,错误处理链路没有正确加入请求链路中。

修改后的客户端代码:

import { ApolloProvider } from 'react-apollo'
import ApolloClient from 'apollo-client'
import {BrowserRouter} from 'react-router-dom'
import { setContext } from 'apollo-link-context'
import { AUTH_TOKEN } from './constants'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory';
import history from './history';
import { onError } from "apollo-link-error";
import { SnackbarProvider, useSnackbar } from 'notistack';

const httpLink = createHttpLink({ uri: 'http://localhost:4000/' });

const authLink = setContext((_, { headers }) => {
  const token = localStorage.getItem(AUTH_TOKEN);
  return {
    headers: {
      // 只保留authorization头,移除所有Access-Control-*的头
      authorization: token ? `Bearer ${token}` : ''
    }
  }
});

const linkError = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) graphQLErrors.map(({ message, locations, path }) => console.log(
    `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
  ));
  if (networkError) console.log(`[Network error]: ${networkError}`);
});

// 正确拼接所有链路:auth链路 -> http链路 -> 错误处理链路
const client = new ApolloClient({
  link: authLink.concat(httpLink).concat(linkError),
  cache: new InMemoryCache(),
  fetchOptions: { mode: 'cors' },
});

ReactDOM.render(
  <BrowserRouter>
    <ApolloProvider client={client}>
      <SnackbarProvider>
        <App />
      </SnackbarProvider>
    </ApolloProvider>
  </BrowserRouter>,
  document.getElementById('root'),
);

为什么这样修改能解决问题?

  1. 服务器端正确配置了cors.origin,会在响应头里返回Access-Control-Allow-Origin: http://localhost:3000,浏览器就会允许来自localhost:3000的请求。
  2. 客户端移除了多余的Access-Control-*请求头,避免了预检请求被服务器拒绝。
  3. 修复了ApolloClient的链路拼接,确保错误处理逻辑正常生效。

现在重启服务器和客户端,CORS问题应该就能解决了。

内容的提问来源于stack exchange,提问作者Natali Hachok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 20:17:50