mcpField
A
api-development

api-development

github.com/lubusin开发68130 次安装4 天前更新
代码仓库

关于 api-development

面向 Frappe 开发者的 API 开发技能,指导设计 REST 与 RPC 接口,并涵盖身份验证、权限、输入校验和错误处理。

主要功能

  1. 01选择 REST、RPC、Webhook 或后台任务模式
  2. 02配置 API 身份验证
  3. 03检查端点权限并校验输入
  4. 04设计结构化响应与错误处理
  5. 05处理长时间运行的后台任务

适用场景

  1. 01创建 DocType CRUD 接口
  2. 02通过 RPC 暴露自定义业务操作
  3. 03为外部系统配置 Webhook
  4. 04安全地向前端开放业务逻辑

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/lubusin/frappe-skills --skill api-development

安装后在 Claude Code 中输入/api-development确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
authentication.md
oauth.md
permissions.md
python-api.md
rate-limiting.md
rest-api.md
server-scripts.md
webhooks.md

详细介绍

Frappe API 开发

使用 Frappe 的 REST 和 RPC 模式构建安全、设计完善的 API。

使用场景

  • 创建自定义 RPC 端点(@frappe.whitelist)
  • 构建 REST API 集成
  • 为外部系统实现 Webhook
  • 设置 API 身份验证(令牌、OAuth)
  • 向前端开放业务逻辑

所需输入

  • API 用途(CRUD、操作、集成)
  • 身份验证要求(公开、用户、API 密钥)
  • 各端点的权限要求
  • 请求和响应格式预期

流程

0) 选择 API 模式
需求模式
DocType CRUD使用内置 REST API
自定义操作使用 @frappe.whitelist 的 RPC
外部回调Webhook DocType
批量操作后台作业 + 状态端点
1) 内置 REST API(DocType CRUD)

Frappe 会为所有 DocType 自动提供 REST 端点:

# Create
POST /api/resource/Customer
{"customer_name": "Acme Corp"}

# Read
GET /api/resource/Customer/CUST-001

# Update
PUT /api/resource/Customer/CUST-001
{"customer_name": "Acme Corporation"}

# Delete
DELETE /api/resource/Customer/CUST-001

# List with filters
GET /api/resource/Customer?filters=[["status","=","Active"]]
2) 自定义 RPC 端点

在应用中创建白名单方法:

# my_app/api.py
import frappe

@frappe.whitelist()
def process_order(order_id, action):
    """Process an order with the given action."""
    # Always verify permissions
    doc = frappe.get_doc("Sales Order", order_id)
    if not frappe.has_permission("Sales Order", "write", doc):
        frappe.throw("Not permitted", frappe.PermissionError)
    
    # Business logic
    if action == "approve":
        doc.status = "Approved"
        doc.save()
    
    return {"status": "success", "order": doc.name}

@frappe.whitelist(allow_guest=True)
def public_endpoint():
    """Public endpoint - no auth required."""
    return {"message": "Hello, World!"}

通过以下方式调用:

POST /api/method/my_app.api.process_order
{"order_id": "SO-001", "action": "approve"}
3) 实现身份验证

API 密钥 + 密钥(推荐用于集成):

# Header format
Authorization: token api_key:api_secret

Bearer 令牌:

Authorization: Bearer <token>

会话(适用于已登录用户): 通过 Cookie 自动完成。

4) 权限检查

务必在 RPC 方法中检查权限:

@frappe.whitelist()
def sensitive_action(docname):
    doc = frappe.get_doc("My DocType", docname)
    
    # Check document-level permission
    if not frappe.has_permission("My DocType", "write", doc):
        frappe.throw("Not permitted", frappe.PermissionError)
    
    # Check role-based permission
    if "Manager" not in frappe.get_roles():
        frappe.throw("Manager role required")
    
    # Proceed with action
    ...
5) 输入验证
@frappe.whitelist()
def create_item(name, qty, price):
    # Validate required fields
    if not name:
        frappe.throw("Name is required")
    
    # Validate types
    qty = frappe.utils.cint(qty)
    price = frappe.utils.flt(price)
    
    # Validate ranges
    if qty <= 0:
        frappe.throw("Quantity must be positive")
    
    # Proceed
    ...
6) 响应格式

成功响应:

return {
    "status": "success",
    "data": {...}
}

错误处理:

# User-facing error
frappe.throw("Validation failed", title="Error")

# Permission error
frappe.throw("Not allowed", frappe.PermissionError)

# Standard exceptions become {"exc_type": "...", "exc": "..."}
7) 长时间操作的后台作业
@frappe.whitelist()
def start_export(filters):
    job = frappe.enqueue(
        "my_app.jobs.run_export",
        filters=filters,
        queue="long",
        timeout=600
    )
    return {"job_id": job.id}

@frappe.whitelist()
def check_job_status(job_id):
    from frappe.utils.background_jobs import get_job
    job = get_job(job_id)
    return {"status": job.get_status()}

验证

  • 端点能正确响应有效请求
  • 未经授权的访问会返回权限错误
  • 输入验证会拒绝无效数据
  • 错误响应格式清晰且有帮助
  • 运行:bench --site <site> console → 手动测试端点

故障模式 / 调试

  • 找不到方法:检查 URL 中的模块路径是否与 Python 路径匹配
  • 权限被拒绝:确认 @frappe.whitelist() 装饰器和用户权限设置正确
  • CSRF 错误:为 API 调用使用正确的身份验证标头
  • 500 错误:检查错误日志:bench --site <site> show-log

升级处理

参考资料

防护措施

  • 始终验证输入:切勿信任客户端数据;在服务端验证类型、长度和格式
  • 使用权限回调:在白名单方法中显式检查 frappe.has_permission()
  • 清理用户输入:对 SQL 使用 frappe.db.escape(),避免使用 eval() 和动态代码执行
  • 处理速率限制:为公开 API 实施速率限制,防止滥用
  • 返回结构化错误:使用 frappe.throw() 并设置恰当的 HTTP 状态码

常见错误

错误失败原因修复方法
缺少 @frappe.whitelist()方法返回“找不到方法”错误添加装饰器,通过 API 暴露方法
使用 GET 执行修改操作违反 REST 约定,并引发 CSRF 问题使用 POST/PUT/DELETE 修改数据
未处理错误500 错误会暴露堆栈跟踪使用 try/except 包裹,并调用 frappe.throw()
暴露敏感数据安全漏洞过滤响应字段并检查权限
缺少 allow_guest=True公开端点返回 403添加 @frappe.whitelist(allow_guest=True),允许未经身份验证的访问
查询中存在 SQL 注入数据库遭到入侵使用 Query Builder 或 frappe.db.escape()

评论

支持 Markdown