使用docker network时apollo-client报GET/HEAD请求不能含body错误如何解决
问题根因分析
- 错误
Request with GET/HEAD method cannot have body的本质是:你的Apollo客户端默认对查询类请求使用GET方法,但是请求头里携带了和请求体相关的字段(比如content-length、content-type),底层HTTP客户端判定该请求存在请求体,触发GET方法不能携带请求体的规范限制。 - 非Docker网络地址正常的原因:外部地址通常经过Nginx等反向代理,会自动清理无效的请求体相关头,而Docker内部网络直接调用目标服务时没有这层处理,错误被直接抛出。
- 你的代码中直接全量展开
...req.headers是核心诱因:这里的req通常是服务端渲染场景下的上游用户请求对象,包含大量不属于你要发往Apollo服务的请求头,其中就包含触发错误的请求体相关字段。 - 原有代码还存在多处语法错误,也可能导致运行时的非预期行为。
修复方案
按以下步骤修改即可在保留Docker网络配置的前提下解决问题:
- 清理透传的请求头,仅保留必要的授权字段,不要全量展开上游请求的headers
- 强制Apollo客户端所有请求使用POST方法,从根源避免GET请求的限制
- 修复原有代码中的语法错误
修复后的完整代码如下:
import { ApolloClient, InMemoryCache } from '@apollo/client'; import { setContext } from '@apollo/client/link/context'; import { createUploadLink } from 'apollo-upload-client'; const authLink = req => { return setContext(_ => { return { headers: { // 仅传递需要的授权头,不全量透传上游请求的headers authorization: `Bearer ${req.cookies.token}`, }, }; }); }; export const client = (req) => { const uri = 'http://dockerNetwork:3000'; return new ApolloClient({ link: authLink(req).concat(createUploadLink({ uri: uri, // 显式关闭查询用GET的配置 useGETForQueries: false })), cache: new InMemoryCache(), // 强制所有请求使用POST方法 defaultOptions: { watchQuery: { fetchPolicy: 'network-only', method: 'POST', }, query: { fetchPolicy: 'network-only', method: 'POST', }, mutate: { method: 'POST', } } }); };
内容的提问来源于stack exchange,提问作者new dev
相关产品推荐
相关产品推荐

