You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在KeyStoneJS v6中调用REST API并对接NextJS GraphQL客户端

KeystoneJS v6 调用外部REST API并通过GraphQL返回的实现思路

1. 扩展GraphQL Schema

在Keystone v6主配置文件(keystone.ts)中,通过extendGraphQLSchema选项添加自定义查询(Query)和突变(Mutation),作为调用外部API的入口。

示例代码:

import { config } from '@keystone-6/core';
import { extendGraphQLSchema } from '@keystone-6/core/graphql';

export default config({
  // 其他配置(如数据库、列表定义)...
  extendGraphQLSchema: (schema) => {
    return schema.extend({
      types: [
        // 定义外部API返回数据的GraphQL类型
        `type ExternalData {
          id: ID!
          title: String!
          content: String
        }`,
        // 定义POST请求的输入参数类型
        `input ExternalPostInput {
          title: String!
          content: String!
        }`,
        // 定义POST请求的返回结果类型
        `type ExternalPostResponse {
          success: Boolean!
          message: String
          data: ExternalData
        }`,
      ],
      queries: [
        // 添加GET请求对应的查询
        {
          schema: 'getExternalData(id: ID!): ExternalData',
          resolver: async (parent, args, context) => {
            // 此处编写外部API调用逻辑
          },
        },
      ],
      mutations: [
        // 添加POST请求对应的突变
        {
          schema: 'postToExternal(input: ExternalPostInput!): ExternalPostResponse',
          resolver: async (parent, args, context) => {
            // 此处编写外部API POST逻辑
          },
        },
      ],
    });
  },
});

2. 在Resolver中实现外部API调用

使用node-fetch或axios在Resolver里发送HTTP请求,处理异步逻辑。

GET请求示例

// 先安装依赖:npm install node-fetch
import fetch from 'node-fetch';

// 填充getExternalData的resolver逻辑
resolver: async (parent, { id }, context) => {
  try {
    const response = await fetch(`https://your-external-api.com/data/${id}`);
    if (!response.ok) {
      throw new Error(`外部API请求失败:${response.statusText}`);
    }
    const rawData = await response.json();
    // 映射外部API数据到GraphQL定义的类型结构
    return {
      id: rawData.id.toString(),
      title: rawData.title,
      content: rawData.content || '',
    };
  } catch (error) {
    // 抛出GraphQL错误,供客户端捕获
    throw new Error(`获取外部数据失败:${(error as Error).message}`);
  }
},

POST请求示例

// 填充postToExternal的resolver逻辑
resolver: async (parent, { input }, context) => {
  try {
    const response = await fetch('https://your-external-api.com/submit', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        // 若外部API需要认证,在此添加token
        // 'Authorization': `Bearer ${process.env.EXTERNAL_API_TOKEN}`
      },
      body: JSON.stringify(input),
    });
    if (!response.ok) {
      throw new Error(`外部API POST请求失败:${response.statusText}`);
    }
    const result = await response.json();
    return {
      success: true,
      message: '数据提交成功',
      data: {
        id: result.id.toString(),
        title: result.title,
        content: result.content,
      },
    };
  } catch (error) {
    return {
      success: false,
      message: `提交数据失败:${(error as Error).message}`,
      data: null,
    };
  }
},

3. 权限控制(可选)

通过context.session校验用户身份,限制接口调用权限:

resolver: async (parent, args, context) => {
  // 检查用户是否登录
  if (!context.session?.itemId) {
    throw new Error('请登录后访问');
  }
  // 可选:校验用户角色
  const user = await context.db.User.findOne({
    where: { id: context.session.itemId },
    select: { role: true },
  });
  if (user?.role !== 'admin') {
    throw new Error('权限不足');
  }
  // 后续API调用逻辑...
},

4. NextJS客户端调用

在NextJS中通过GraphQL客户端(如Apollo Client)或直接fetch调用Keystone的GraphQL API:

示例:用fetch调用GET查询

async function fetchExternalData(id: string) {
  const response = await fetch('http://your-keystone-api.com/api/graphql', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      // 若Keystone开启认证,添加用户session token
      // 'Authorization': `Bearer ${userSessionToken}`
    },
    body: JSON.stringify({
      query: `
        query GetExternalData($id: ID!) {
          getExternalData(id: $id) {
            id
            title
            content
          }
        }
      `,
      variables: { id },
    }),
  });
  const { data, errors } = await response.json();
  if (errors) throw new Error(errors[0].message);
  return data.getExternalData;
}

5. 错误处理与优化

  • 添加请求超时机制,避免Resolver长时间阻塞:
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒超时
    const response = await fetch(url, { signal: controller.signal });
    clearTimeout(timeoutId);
    
  • 对高频请求的外部数据添加缓存,减少重复API调用。

内容的提问来源于stack exchange,提问作者Ronier Ramos Sanchez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 16:52:50