Apollo 服务器多个 3rd 方 API

Posted

技术标签:

【中文标题】Apollo 服务器多个 3rd 方 API【英文标题】:Apollo server multiple 3rd party Apis 【发布时间】:2020-12-11 07:40:11 【问题描述】:

着眼于在 Apollo 服务器上使用 next js 和新的 api 路由。但是,我没有使用一种数据源。我将使用 contentful 和 shopify,但可能会使用更多的 3rd 方 API。

您如何使用多个第 3 方 API 并通过自定义端点访问所有数据? 有什么例子吗?

【问题讨论】:

【参考方案1】:

您可以使用称为 GraphQL 模式拼接的技术将多个 GraphQL API 组合成一个统一的端点。阿波罗有一个extensive guide on the topic。

我还编写了两部分指南,如何将 Contentful API 与其他 API 拼接在一起:Part 1、Part 2。

所有这些示例都是围绕 Apollo Server 构建的,但同样的方法也适用于 Apollo Client。因此,您可以选择将拼接作为 API 的一部分(将 GraphQL API、Shopify 和 Contentful 添加到统一端点)或在客户端进行拼接。这些都有优点和缺点。服务器端通常会减少从客户端发出的请求,而客户端会消除作为拼接代理的单点故障。

使用 Apollo Server 的基本设置如下:

const ApolloServer = require('apollo-server');
const HttpLink = require('apollo-link-http');
const setContext = require('apollo-link-context');
const 
 introspectSchema,
 makeRemoteExecutableSchema,
 mergeSchemas
 = require('graphql-tools');
const fetch = require('node-fetch');

const GITHUB_TOKEN, CONTENTFUL_SPACE, CONTENTFUL_TOKEN = require('./config.json');

const gitHubLink = setContext((request) => (
 headers: 
   'Authorization': `Bearer $GITHUB_TOKEN`,
 
)).concat(new HttpLink(uri: 'https://api.github.com/graphql', fetch));

const contentfulLink = setContext((request) => (
 headers: 
   'Authorization': `Bearer $CONTENTFUL_TOKEN`,
 
)).concat(new HttpLink(uri: `https://graphql.contentful.com/content/v1/spaces/$CONTENTFUL_SPACE`, fetch));

async function startServer() 
 const gitHubRemoteSchema = await introspectSchema(gitHubLink);

 const gitHubSchema = makeRemoteExecutableSchema(
   schema: gitHubRemoteSchema,
   link: gitHubLink,
 );

 const contentfulRemoteSchema = await introspectSchema(contentfulLink);

 const contentfulSchema = makeRemoteExecutableSchema(
   schema: contentfulRemoteSchema,
   link: contentfulLink,
 );

 const schema = mergeSchemas(
   schemas: [
     gitHubSchema,
     contentfulSchema
   ]
 );

 const server = new ApolloServer(schema);

 return await server.listen();


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

请注意,这只会合并两个 GraphQL 模式。如果两个 API 的类型或根字段名称相同,您可能会发生冲突。

两个确保您没有任何冲突我建议您转换所有模式以赋予类型和根字段唯一的前缀。这可能看起来像这样:

async function getContentfulSchema() 
 const contentfulRemoteSchema = await introspectSchema(contentfulLink);

 const contentfulSchema = makeRemoteExecutableSchema(
   schema: contentfulRemoteSchema,
   link: contentfulLink,
 );

 return transformSchema(contentfulSchema, [
   new RenameTypes((name) => 
     if (name.includes('Repository')) 
       return name.replace('Repository', 'RepositoryMetadata');
     

     return name;
   ),
   new RenameRootFields((operation, fieldName) => 
     if (fieldName.includes('repository')) 
       return fieldName.replace('repository', 'repositoryMetadata');
     

     return fieldName;
   )
 ]);

这将让您以统一的方式使用所有 API,但您无法跨不同的 API 进行查询。为此,您必须将字段拼接在一起。我建议您深入了解上面的链接,他们对此进行了更深入的解释。

【讨论】:

谢谢!周末一直在用 graphql-transform-federation 和 Apollo 网关研究联邦。还有我认为在引擎盖下使用联邦和缝合的graphql-mesh。试图找到最简单的方法 有趣,我没听说过graphql-transform-federation。正如最初设计的那样,Federation 并不是真正将第 3 方 API 缝合在一起。这种转换可能是一个有趣的解决方案。 GraphQL Mesh 很早。我确实想知道所有这些动态配置的开销最终会是多少。

以上是关于Apollo 服务器多个 3rd 方 API的主要内容,如果未能解决你的问题,请参考以下文章

我如何使用 websocket 让我了解 3rd 方 api 中的实时数据

是否可以通过 GraphQL/REST 后端共享 3rd 方 API websocket/实时连接?

如何确定我的后台任务将在生产中调用多少个 3rd 方 Web api 调用?

使用 3rd 方 API 将适配器设置为微调器

android 图像 exif 阅读器 3rd 方 api

如何在 3rd 方应用中基于 API 调用和回调触发函数