加入我们,于10月8日至10日在纽约市学习最新的GraphQL联合和API平台工程技巧、趋势和新闻。加入2024年纽约市GraphQL峰会
文档
免费开始

高级 HTTP 网络技术

使用 Apollo Link 完全控制网络


Apollo Link 库让您可以精确控制由 发送的 HTTP 请求。您还可以使用它来用完全定制的网络层(如 WebSocket 转发或模拟服务器数据)替换 Apollo 客户端的网络层。

当使用 时,您将定义网络行为为一系列 对象的集合,这些对象按顺序执行以控制数据流。默认情况下, Apollo 客户端 使用 Apollo LinkHttpLink 以发送 HTTP 上的 查询。

Apollo Link 包含各种支持使用情况的可安装链接,您也可以创建自己的自定义链接。

自定义请求逻辑

以下示例演示了向 Apollo 客户端 添加自定义链接。此链接在 HttpLink 发送之前向每个 HTTP 请求添加一个 Authorization 标头:

import { ApolloClient, HttpLink, ApolloLink, InMemoryCache, concat } from '@apollo/client';
const httpLink = new HttpLink({ uri: '/graphql' });
const authMiddleware = new ApolloLink((operation, forward) => {
// add the authorization to the headers
operation.setContext(({ headers = {} }) => ({
headers: {
...headers,
authorization: localStorage.getItem('token') || null,
}
}));
return forward(operation);
})
const client = new ApolloClient({
cache: new InMemoryCache(),
link: concat(authMiddleware, httpLink),
});

以下示例展示了在数组中提供多个自定义链接

import { ApolloClient, HttpLink, ApolloLink, InMemoryCache, from } from '@apollo/client';
const httpLink = new HttpLink({ uri: '/graphql' });
const authMiddleware = new ApolloLink((operation, forward) => {
// add the authorization to the headers
operation.setContext(({ headers = {} }) => ({
headers: {
...headers,
authorization: localStorage.getItem('token') || null,
}
}));
return forward(operation);
})
const activityMiddleware = new ApolloLink((operation, forward) => {
// add the recent-activity custom header to the headers
operation.setContext(({ headers = {} }) => ({
headers: {
...headers,
'recent-activity': localStorage.getItem('lastOnlineTime') || null,
}
}));
return forward(operation);
})
const client = new ApolloClient({
cache: new InMemoryCache(),
link: from([
authMiddleware,
activityMiddleware,
httpLink
]),
});

在上面的示例中,authMiddleware 链接设置了每个请求的 Authorization 头,然后 activityMiddleware 会设置每个请求的 Recent-Activity 头。最后,HttpLink 会发送修改后的请求。

自定义响应逻辑

您可以使用 Apollo Link 在 Apollo Client 收到请求的响应时自定义其行为。

以下示例展示了使用 @apollo/client/link/error 处理包含在响应中的网络错误:

import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client';
import { onError } from '@apollo/client/link/error';
import { logout } from './logout';
const httpLink = new HttpLink({ uri: '/graphql' });
const logoutLink = onError(({ networkError }) => {
if (networkError.statusCode === 401) logout();
})
const client = new ApolloClient({
cache: new InMemoryCache(),
link: logoutLink.concat(httpLink),
});

在这个示例中,如果服务器返回 401 代码(未经授权),用户会从应用程序中登出。

修改响应数据

您可以创建一个自定义链接来编辑或删除 response.data 中。为此,您需要调用链接的 forward(operation) 调用的结果上的 map 。在 map 函数中,对 response.data 进行所需的更改,然后返回它:

import { ApolloClient, InMemoryCache, HttpLink, ApolloLink } from '@apollo/client';
const httpLink = new HttpLink({ uri: '/graphql' });
const formatDateLink = new ApolloLink((operation, forward) => {
return forward(operation).map(response => {
if (response.data.date) {
response.data.date = new Date(response.data.date);
}
return response;
});
});
const client = new ApolloClient({
cache: new InMemoryCache(),
link: formatDateLink.concat(httpLink),
});

在上面的示例中,formatDateLink 将每个响应的最高层中的一个 date 字段更改为 JavaScript 日期对象。

请注意,forward(operation).map(func) 不支持异步执行 func 映射函数。如果需要执行异步修改,使用 @apollo/client/utilities 中的 asyncMap 函数,如下所示:

import {
ApolloClient,
InMemoryCache,
HttpLink,
ApolloLink
} from "@apollo/client";
import { asyncMap } from "@apollo/client/utilities";
import { usdToEur } from './currency';
const httpLink = new HttpLink({ uri: '/graphql' });
const usdToEurLink = new ApolloLink((operation, forward) => {
return asyncMap(forward(operation), async (response) => {
let data = response.data;
if (data.price && data.currency === "USD") {
data.price = await usdToEur(data.price);
data.currency = "EUR";
}
return response;
});
});
const client = new ApolloClient({
cache: new InMemoryCache(),
link: usdToEurLink.concat(httpLink)
});

在上面的示例中,usdToEurLink 使用 asyncMap 将响应对象的 price 字段从美元转换为欧元,使用外部 API。

虽然此技术可用来修改 现有 字段(或在 data 列表中添加额外的对象)是有用的,但在大多数情况下,将新字段添加到 data 中将不起作用,因为在 ApolloLink 请求流水线内无法安全地修改操作文档。

Apollo客户端使用HttpLink来通过HTTP向服务器发送GraphQL。该链路支持POST和GET请求,并且可以根据单个查询修改HTTP选项。这在实现身份验证、、动态URI和其他细粒度更新时非常方便。

如果你的客户端不需要复杂的HTTP需求,你可能不需要创建自定义的HttpLink实例。有关详细信息,请参阅基本HTTP网络

用法

import { HttpLink } from "@apollo/client";
const link = new HttpLink({ uri: "/graphql" });

构造函数选项

HttpLink构造函数接受以下选项:

选项描述
uri一个字符串终点或函数,该函数解析您想要执行操作的GraphQL服务器。(默认:/graphql)
includeExtensions如果为true,则可以传递一个extensions字段到您的GraphQL服务器。(默认:false)
fetch一个用于发起请求的兼容fetch的API。请参阅为特定环境提供fetch替换
headers一个包含要包含在每次请求中的头部名称和值的对象。
preserveHeaderCase如果为true,则头部值将保留其大写字母形式用于非HTTP规范的服务器。(默认:false)
credentials一个表示用于fetch调用的凭证策略的字符串。(有效值:omitincludesame-origin)
fetchOptions包含此选项以覆盖传递给fetch调用的某些选项的值。
useGETForQueries如果为true,则HttpLink使用GET请求而不是使用POST请求来执行查询操作(但不执行突变操作)。(默认:false)
print一个函数,用于自定义请求中的AST格式化。请参阅重写默认的print函数

为特定环境提供fetch替换

HttpLink需要您的运行时环境中存在fetch。这对于React Native和大多数现代浏览器是正确的。如果您针对的环境不包含包含fetch(例如较古老的浏览器或服务器),您需要通过构造函数选项将其自己的fetch传递给HttpLink。我们推荐使用cross-fetch用于较旧的浏览器和Node。

覆盖默认的 print 函数

print 选项用于自定义在对象发送到网络之前如何将 DocumentNode 对象转换回字符串。如果没有提供自定义 print 函数,则会使用 GraphQL print 函数。自定义 print 函数应接受一个 ASTNode(通常是一个 DocumentNode),以及原始 print 函数作为参数,并返回一个字符串。此选项可以与 stripIgnoredCharacters 一起使用,以从查询中删除空格:

import { ASTNode, stripIgnoredCharacters } from 'graphql';
const httpLink = new HttpLink({
uri: '/graphql',
print(
ast: ASTNode,
originalPrint: (ast: ASTNode) => string,
) {
return stripIgnoredCharacters(originalPrint(ast));
},
});

覆盖选项

您可以通过修改操作 context 对象以基于操作覆盖大多数 HttpLink 构造函数选项。例如,您可以将 headers 字段设置为操作以传递特定操作的自定义标题。 context 还支持 credentials 字段,用于定义凭证策略,使用 uri 动态更改端点,以及 fetchOptions 以允许通用的 fetch 覆盖(例如, method: "GET")。

请注意,如果您将 fetchOptions.method 设置为 GETHttpLink 将遵循 标准 GraphQL HTTP GET 编码。查询、(')、操作名和扩展都将作为查询参数传递,而不是放在 HTTP 请求体中(因为没有请求体)。如果您想继续以非幂等的 作为 POST 请求发送,请将顶层 useGETForQueries 选项设置为 true,而不是将 fetchOptions.method 设置为 GET

HttpLink 也会将 fetch 操作的响应附加到上下文中作为 response,这样您就可以在其他链接中访问它。

上下文选项

选项描述
headers一个包含要包含在每次请求中的头部名称和值的对象。
credentials一个表示用于fetch调用的凭证策略的字符串。(有效值:omitincludesame-origin)
uri一个字符串端点或函数,该端点或函数解析为您想要执行操作的服务器。
fetchOptions传递到 fetch 调用的-fetch 选项的任何覆盖。
response在执行之后从 fetch 请求的原始响应。
http一个对象,让您可以控制 HttpLink 本身的细微方面,如持久查询(见下文)。

以下示例显示了如何使用 context 将特殊头传递给单个 查询

import { ApolloClient, InMemoryCache } from "@apollo/client";
const client = new ApolloClient({
cache: new InMemoryCache(),
uri: "/graphql"
});
client.query({
query: MY_QUERY,
context: {
// example of setting the headers with context per operation
headers: {
special: "Special header value"
}
}
});

自定义获取

HttpLink's fetch 选项可以用来联接自定义网络。如果您想根据计算出的头修改请求,或根据操作来计算 URI,这非常有用。例如:

自定义认证

const customFetch = (uri, options) => {
const { header } = Hawk.client.header(
"http://example.com:8000/resource/1?b=1&a=2",
"POST",
{ credentials: credentials, ext: "some-app-data" }
);
options.headers.Authorization = header;
return fetch(uri, options);
};
const link = new HttpLink({ fetch: customFetch });

动态 URI

const customFetch = (uri, options) => {
const { operationName } = JSON.parse(options.body);
return fetch(`${uri}/graph/graphql?opname=${operationName}`, options);
};
const link = new HttpLink({ fetch: customFetch });

Apollo Link 包含许多针对特定使用情况的链接,例如用于通过 WebSocket 通信的 WebSocketLink 和用于将多个 GraphQL 操作组合到单个 HTTP 请求中的 BatchHttpLink

要了解更多有关它所提供的功能,请参阅 Apollo Link API 文档

上一页
基本 HTTP 网络连接
下一页
认证
评分文章评分在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc.,又称为Apollo GraphQL。

隐私政策

公司