查看使用 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/