跳到主要内容

使用 Cursor 构建 API:REST、GraphQL 和 FastAPI

Cursor API Development

构建健壮的 API 需要仔细规划、一致的模式和彻底的测试。Cursor 的 AI 能力可以加速 API 开发的每个阶段,从搭建端点到生成 OpenAPI 文档。本指南涵盖 REST、GraphQL 和 FastAPI 工作流。

前置条件​

在开始之前:

  • 安装 Cursor(建议使用 Pro 计划)
  • 安装 Node.js 或 Python
  • 熟悉 HTTP 概念和 JSON

REST API 开发​

项目脚手架​

让 Cursor 搭建一个完整的 REST API:

使用 Express.js 创建一个 REST API,包含:
- TypeScript
- 路由处理器位于 src/routes/
- 日志和错误处理中间件
- 使用 Zod 进行输入验证
- JWT 认证
- 速率限制
- Swagger 文档

Express.js 路由结构​

// src/routes/users.ts
import { Router } from 'express';
import { z } from 'zod';
import { authenticate } from '../middleware/auth';
import { validate } from '../middleware/validate';

const router = Router();

const createUserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
password: z.string().min(8),
});

router.post(
'/',
authenticate,
validate(createUserSchema),
async (req, res, next) => {
try {
const user = await createUser(req.body);
res.status(201).json({
success: true,
data: user,
});
} catch (error) {
next(error);
}
}
);

router.get('/:id', authenticate, async (req, res, next) => {
try {
const user = await getUserById(req.params.id);
if (!user) {
return res.status(404).json({
success: false,
error: 'User not found',
});
}
res.json({ success: true, data: user });
} catch (error) {
next(error);
}
});

export default router;

统一错误处理​

// src/middleware/errorHandler.ts
import { Request, Response, NextFunction } from 'express';

export class AppError extends Error {
constructor(
public statusCode: number,
public message: string,
public isOperational = true
) {
super(message);
Object.setPrototypeOf(this, AppError.prototype);
}
}

export const errorHandler = (
err: Error,
req: Request,
res: Response,
next: NextFunction
) => {
if (err instanceof AppError) {
return res.status(err.statusCode).json({
success: false,
error: err.message,
});
}

console.error('Unexpected error:', err);
res.status(500).json({
success: false,
error: 'Internal server error',
});
};

使用 Cursor 开发 FastAPI​

创建 FastAPI 端点​

# main.py
from fastapi import FastAPI, HTTPException, Depends, status
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel, EmailStr
from typing import List, Optional
import uvicorn

app = FastAPI(
title="My API",
description="A production-ready API built with FastAPI",
version="1.0.0",
)

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

# Pydantic 模型
class UserCreate(BaseModel):
email: EmailStr
name: str
password: str

class UserResponse(BaseModel):
id: int
email: str
name: str

class Config:
from_attributes = True

# 内存存储(替换为数据库)
users_db = {}
user_counter = 0

@app.post(
"/users",
response_model=UserResponse,
status_code=status.HTTP_201_CREATED,
tags=["users"],
)
async def create_user(user: UserCreate):
global user_counter
user_counter += 1
new_user = {
"id": user_counter,
"email": user.email,
"name": user.name,
}
users_db[user_counter] = new_user
return new_user

@app.get(
"/users/{user_id}",
response_model=UserResponse,
tags=["users"],
)
async def get_user(user_id: int):
if user_id not in users_db:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
return users_db[user_id]

@app.get("/users", response_model=List[UserResponse], tags=["users"])
async def list_users(
skip: int = 0,
limit: int = 100,
):
return list(users_db.values())[skip : skip + limit]

if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)

依赖注入​

# dependencies.py
from fastapi import Depends, HTTPException, status
from sqlalchemy.orm import Session
from database import SessionLocal

async def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

async def get_current_user(token: str = Depends(oauth2_scheme)):
user = verify_token(token)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication",
)
return user

# 用法
@app.get("/items")
async def read_items(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
):
return db.query(Item).filter(Item.owner_id == current_user.id).all()

GraphQL API 开发​

Apollo Server 设置​

// src/schema.ts
import { gql } from 'apollo-server-express';

export const typeDefs = gql`
type User {
id: ID!
email: String!
name: String!
posts: [Post!]!
}

type Post {
id: ID!
title: String!
content: String!
author: User!
}

type Query {
users: [User!]!
user(id: ID!): User
posts: [Post!]!
post(id: ID!): Post
}

type Mutation {
createUser(email: String!, name: String!, password: String!): User!
createPost(title: String!, content: String!, authorId: ID!): Post!
}
`;

使用 Cursor 的解析器​

// src/resolvers.ts
export const resolvers = {
Query: {
users: async (_, __, { dataSources }) => {
return dataSources.userAPI.getAllUsers();
},
user: async (_, { id }, { dataSources }) => {
return dataSources.userAPI.getUserById(id);
},
},
User: {
posts: async (parent, _, { dataSources }) => {
return dataSources.postAPI.getPostsByAuthor(parent.id);
},
},
Mutation: {
createUser: async (_, args, { dataSources }) => {
return dataSources.userAPI.createUser(args);
},
},
};
GraphQL 模式设计

使用 Cursor 从数据库模式生成 GraphQL 模式。粘贴您的 Prisma 模式并请求相应的 GraphQL 类型定义。

认证和授权​

JWT 实现​

// src/utils/jwt.ts
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';

const JWT_SECRET = process.env.JWT_SECRET!;
const SALT_ROUNDS = 12;

export const hashPassword = async (password: string): Promise<string> => {
return bcrypt.hash(password, SALT_ROUNDS);
};

export const comparePassword = async (
password: string,
hash: string
): Promise<boolean> => {
return bcrypt.compare(password, hash);
};

export const generateToken = (payload: object): string => {
return jwt.sign(payload, JWT_SECRET, { expiresIn: '24h' });
};

export const verifyToken = (token: string): any => {
return jwt.verify(token, JWT_SECRET);
};

中间件模式​

// src/middleware/rateLimit.ts
import rateLimit from 'express-rate-limit';

export const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 分钟
max: 100, // 每个 IP 每窗口限制 100 个请求
message: {
success: false,
error: 'Too many requests, please try again later',
},
standardHeaders: true,
legacyHeaders: false,
});

API 文档​

FastAPI 的 OpenAPI​

FastAPI 自动生成 OpenAPI 文档。访问地址:

  • Swagger UI: /docs
  • ReDoc: /redoc

Express.js 配合 Swagger​

// src/config/swagger.ts
import swaggerJsdoc from 'swagger-jsdoc';

const options = {
definition: {
openapi: '3.0.0',
info: {
title: 'My API',
version: '1.0.0',
description: 'API documentation',
},
servers: [
{
url: 'http://localhost:3000/api',
},
],
},
apis: ['./src/routes/*.ts'],
};

export const specs = swaggerJsdoc(options);

测试 API​

集成测试示例​

// tests/users.test.ts
import request from 'supertest';
import app from '../src/app';

describe('Users API', () => {
describe('POST /users', () => {
it('should create a new user', async () => {
const response = await request(app)
.post('/users')
.send({
name: 'Test User',
password: 'securePassword123',
})
.expect(201);

expect(response.body.success).toBe(true);
expect(response.body.data.email).toBe('[email protected]');
});

it('should reject invalid email', async () => {
await request(app)
.post('/users')
.send({
email: 'invalid-email',
name: 'Test',
password: 'password',
})
.expect(400);
});
});
});

API 设计最佳实践​

实践实现
版本控制在 URL 中使用 /api/v1/ 前缀
分页返回 { data, meta: { page, limit, total } }
过滤使用查询参数:?status=active&sort=created_at
错误格式一致的 { success: false, error: "message" }
速率限制公共端点每 15 分钟 100 个请求
缓存使用 ETag 头部和 Redis 进行响应缓存

常见 API 模式​

仓库模式​

// src/repositories/UserRepository.ts
export class UserRepository {
async findById(id: string): Promise<User | null> {
return prisma.user.findUnique({ where: { id } });
}

async findByEmail(email: string): Promise<User | null> {
return prisma.user.findUnique({ where: { email } });
}

async create(data: CreateUserInput): Promise<User> {
return prisma.user.create({ data });
}

async update(id: string, data: UpdateUserInput): Promise<User> {
return prisma.user.update({ where: { id }, data });
}

async delete(id: string): Promise<void> {
await prisma.user.delete({ where: { id } });
}
}

环境配置​

# .env
NODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://user:pass@localhost:5432/myapp
JWT_SECRET=your-secret-key
REDIS_URL=redis://localhost:6379
RATE_LIMIT_MAX=100

快速参考​

任务Cursor 提示
生成 CRUD 端点"为 Product 资源创建带有验证的 CRUD 端点"
添加认证"为所有受保护路由添加 JWT 认证中间件"
创建 GraphQL 模式"从此 Prisma 模式生成 GraphQL 类型"
编写测试"为用户注册端点编写集成测试"
添加速率限制"为 API 添加速率限制,认证和公共端点使用不同层级"

相关资源​

最后更新:2025 年 7 月