Apollo 客户端查询报错:“Network error: Failed to fetch”如何排查?

Posted

技术标签:

【中文标题】Apollo 客户端查询报错:“Network error: Failed to fetch”如何排查?【英文标题】:Apollo client query error: "Network error: Failed to fetch" How to troubleshoot? 【发布时间】:2018-08-29 21:17:50 【问题描述】:

Apollo 服务器已设置,并且在使用 graphiql 时正确响应查询。

具有服务器端渲染的现有 react-redux 应用程序需要开始使用 graphql 并进行此查询。

此应用程序的一个组件已设置为执行相同的查询,它似乎正在执行网络请求,但它失败了 Error: "graphQLErrors":[],"networkError":,"message":"Network error: Failed to fetch"

任何故障排除建议?

【问题讨论】:

Network error的常见问题是DNS解析失败,连接因无响应而关闭。 【参考方案1】:

我在 localhost 上运行 apollo 客户端,在 someDomain.com 上运行 apollo 服务器,所以这是一个 CORS 问题。加载在chrome隐身模式下进行查询的页面并刷新后,在chrome开发工具控制台中发现了这个错误:

httpLink.js:71 OPTIONS https://someDomain.com/graphql 405 (Method Not Allowed) (anonymous) @ httpLink.js:71 ... (index):1 Failed to load https://someDomain.com/graphql: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost:8443' is therefore not allowed access. The response had HTTP status code 405. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

此(仅限测试)设置的快速解决方法是在 express apollo 服务器上设置 cors,就像这篇文章所建议的那样。 https://blog.graph.cool/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d

【讨论】:

【参考方案2】:

这确实是 cors 问题。我试图通过使用 express 来修复它。但它不适用于 Apollo GraphQL。

const corsOptions = 
    origin: "http://localhost:3000",
    credentials: true
  ;
app.use(cors(corsOptions));

所以,我尝试在 GraphQL 服务器中配置 cors 并且成功了。

对于 Apollo 服务器

const corsOptions = 
    origin: "http://localhost:3000",
    credentials: true
  ;

const server = new ApolloServer(
  typeDefs,
  resolvers,
  cors: corsOptions
);

server.listen().then(( url ) => 
  console.log(`? Server ready at $url`);
);

对于 GraphQL 瑜伽

const options = 
  cors: corsOptions
;

server.start(options, () =>
  console.log("Server is running on http://localhost:4000")
);

【讨论】:

【参考方案3】:

如果您通过 Apollo 在请求中传递 null HEADER 也可能出现此错误,例如:

const middlewareLink = setContext(() => (
    headers: 
        'authorization': `Bearer $FeedierExchanger.token` || null
    
));

改成:

const middlewareLink = setContext(() => (
    headers: 
        'authorization': `Bearer $FeedierExchanger.token` || ''
    
));

或者去掉这部分:

|| ''

如果您有正确的后端验证。

【讨论】:

【参考方案4】:

您需要做的就是为您的 Apollo-Graphql 服务器启用 cors 库

yarn add cors / npm install cors

现在找到你的 app.js 或 server.js(基本上是你的服务器的入口文件)

添加下面几行

const cors = require('cors');

app.use(cors()); // 确保你在这之前已经初始化了 express。

【讨论】:

【参考方案5】:

尝试在代码顶部使用 cors 中间件。这会在创建 graphql 端点之前首先初始化跨域资源共享。

enter const  urlencoded  = require("express");
const express = require("express");
const app = express(); //create an express application
const helmet = require("helmet"); //require helment from node modules
const cors = require("cors"); //cross-origin-resource sharing
const mR = require("./routes/main");
const schema = require("./graph-schema/schema");
const mongoose = require("mongoose");

//cross-origin-resources-sharing defined at the top before your graphql endpoint
app.use(
  cors(
    optionsSuccessStatus: 200, //option sucess status
    origin: "http://localhost:3000", //origin allowed to access the server
  )
);

//connect to database
mongoose.connect("mongodb://localhost:27017/Graphql_tutorial", 
  useNewUrlParser: true,
  useUnifiedTopology: true,
  useCreateIndex: true,
);

//graphql area
const  graphqlHTTP  = require("express-graphql"); //This allows express to understand graphql and lunch its api.

app.use(
  "/graphql",
  graphqlHTTP(
    schema,
    graphiql: true,
  )
);//code here

【讨论】:

以上是关于Apollo 客户端查询报错:“Network error: Failed to fetch”如何排查?的主要内容,如果未能解决你的问题,请参考以下文章

在查询组件之外显示 Apollo 客户端查询加载的最佳实践?

React - 带有输入变量的 Apollo 客户端查询

缓存对象上的 Apollo 客户端查询重复数据删除

带有 React 的 Apollo 客户端 2 无法进行查询

Apollo 客户端基于状态跳过查询

apollo 客户端,带过滤器的查询