api - Apollo 服务器多个第三方 API

标签 api graphql next.js apollo apollo-server

查看使用 next js 和新的 API 路由与 Apollo 服务器。然而我并没有使用单一的数据源。我将使用 contentful 和 shopify,但也可以使用更多第 3 方 API。

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

最佳答案

您可以使用称为 GraphQL 模式拼接的技术将多个 GraphQL API 组合成一个统一的端点。 Apollo 有一个 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 进行查询。为此,您必须将字段缝合在一起。我建议您深入研究上面的链接,它们对此进行了更深入的解释。

关于api - Apollo 服务器多个第三方 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63530981/

相关文章:

javascript - 在函数中初始化的 typescript 继承属性被覆盖

reactjs - SWR:改变数据时立即更新 UI

javascript - 尝试使用 API 从交易所获取价格

postgresql - 如何在非英语语言中使用 GraphQL 枚举?邮寄的

node.js - 使用 Jest、Graphql 和 Sequelize 测试数据库时如何避免 EADDRINUSE

reactjs - Semantic-UI-React 无法启用调试

api - REST 风格的 API : Modelling a collection of resources that have access to another resource

javascript - PubNub Twitter 数据流设置不返回数据

android - 如何知道 Retrofit 调用何时完成

mysql - 如何将 Prisma/GraphQL 连接到现有的 MySQL 数据库(特别是 WordPress)?