考虑在Apollo服务器上使用下一个js和新的api路由。但是,我并没有使用一种数据源。我将使用内容丰富和购物的方式,但是可能会使用更多的第三方API。
您如何使用多个第三方API并通过自定义端点访问所有数据? 有例子吗?
答案 0 :(得分:0)
您可以使用称为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服务器的基本设置如下:
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查询。为此,您必须将字段缝合在一起。我建议您深入上面的链接,它们会更深入地解释这一点。