소스 정보
- 저장소
- microwind/ai-skills
- 최근 소스 활동
- 2026년 3월 23일 08:00
- 감지된 SKILL.md 언어
- 중국어
- 스타
- 68
- 포크
- 17
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/microwind/ai-skills --skill restful-api명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | RESTful API设计 |
| description | 当设计RESTful API时,分析资源模型,优化接口设计,解决性能问题。验证API架构,设计版本控制,和最佳实践。 |
| license | MIT |
RESTful API是现代Web服务的核心架构。不当的API设计会导致性能问题、安全漏洞和维护困难。需要系统化的API设计方法和规范。
核心原则: 好的RESTful API应该资源导向、状态清晰、版本可控、易于扩展。坏的RESTful API会导致接口混乱、性能下降、安全风险。
始终:
触发短语:
问题:
API端点命名不符合REST规范,导致接口混乱
错误示例:
- 使用动词而非名词: /getUser, /createUser
- 命名不一致: /users, /user_list
- 复数形式错误: /user, /userss
- 层级过深: /api/v1/users/1/posts/1/comments/1
解决方案:
1. 使用名词表示资源
2. 保持命名一致性
3. 使用正确的复数形式
4. 限制资源层级深度
问题:
不正确使用HTTP方法,违反REST原则
错误示例:
- GET用于创建资源
- POST用于查询操作
- PUT用于部分更新
- 所有操作都用POST
解决方案:
1. GET用于查询和获取
2. POST用于创建资源
3. PUT用于完整更新
4. PATCH用于部分更新
5. DELETE用于删除资源
问题:
HTTP状态码使用不规范,影响客户端处理
错误示例:
- 所有响应都返回200
- 错误时返回404而非400
- 成功时返回201而非200
- 缺少适当的错误信息
解决方案:
1. 200表示成功请求
2. 201表示资源创建成功
3. 400表示客户端错误
4. 404表示资源不存在
5. 500表示服务器错误
问题:
API缺少版本控制,导致升级困难
错误示例:
- 直接修改现有接口
- 强制客户端升级
- 不兼容的变更
- 缺少版本规划
解决方案:
1. 实施URL路径版本控制
2. 保持向后兼容性
3. 提前通知版本废弃
4. 制定版本迁移计划
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from datetime import datetime
from typing import Dict, Any, List, Optional
from dataclasses import dataclass
from enum import Enum
import uuid
import re
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///api.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
migrate = Migrate(app, db)
class HTTPStatus(Enum):
"""HTTP状态码"""
OK = 200
CREATED = 201
NO_CONTENT = 204
BAD_REQUEST = 400
UNAUTHORIZED = 401
FORBIDDEN = 403
NOT_FOUND = 404
CONFLICT = 409
UNPROCESSABLE_ENTITY = 422
INTERNAL_SERVER_ERROR = 500
@dataclass
class APIResponse:
"""API响应格式"""
success: bool
data: Optional[Any] = None
error: Optional[str] = None
message: [] =
meta: [[, ]] =
():
():
.message = message
.field = field
().__init__(message)
():
():
.message = message
.status_code = status_code
().__init__(message)
(db.Model):
__abstract__ =
= db.Column(db.String(), primary_key=, default=: (uuid.uuid4()))
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
():
__tablename__ =
name = db.Column(db.String(), nullable=)
email = db.Column(db.String(), unique=, nullable=)
password_hash = db.Column(db.String(), nullable=)
is_active = db.Column(db.Boolean, default=)
posts = db.relationship(, backref=, lazy=, cascade=)
():
{
: .,
: .name,
: .email,
: .is_active,
: .created_at.isoformat(),
: .updated_at.isoformat()
}
():
__tablename__ =
title = db.Column(db.String(), nullable=)
content = db.Column(db.Text, nullable=)
author_id = db.Column(db.String(), db.ForeignKey(), nullable=)
is_published = db.Column(db.Boolean, default=)
():
{
: .,
: .title,
: .content,
: .author_id,
: .is_published,
: .created_at.isoformat(),
: .updated_at.isoformat()
}
:
() -> :
pattern =
re.(pattern, email)
() -> [, ]:
errors = []
is_update data:
name = data.get(, ).strip()
name:
errors.append()
(name) < :
errors.append()
(name) > :
errors.append()
is_update data:
email = data.get(, ).strip()
email:
errors.append()
RequestValidator.validate_email(email):
errors.append()
errors:
ValidationError(.join(errors))
data
() -> [, ]:
errors = []
is_update data:
title = data.get(, ).strip()
title:
errors.append()
(title) < :
errors.append()
(title) > :
errors.append()
is_update data:
content = data.get(, ).strip()
content:
errors.append()
(content) < :
errors.append()
errors:
ValidationError(.join(errors))
data
:
() -> [, ]:
page = (, request.args.get(, , =))
limit = (, (, request.args.get(, , =)))
offset = (page - ) * limit
{: page, : limit, : offset}
() -> [, ]:
total_pages = (total + limit - ) // limit
{
: items,
: {
: page,
: limit,
: total,
: total_pages,
: page < total_pages,
: page >
}
}
:
() -> :
response = APIResponse(
success=error ,
data=data,
error=error,
message=message,
meta=meta
)
jsonify(response.__dict__), status_code
() -> :
.create_response(
error=error.message,
status_code=HTTPStatus.BAD_REQUEST.value
)
() -> :
.create_response(
error=,
status_code=HTTPStatus.NOT_FOUND.value
)
() -> :
.create_response(
error=message,
status_code=HTTPStatus.CONFLICT.value
)
() -> :
app.logger.error()
.create_response(
error=,
status_code=HTTPStatus.INTERNAL_SERVER_ERROR.value
)
():
():
.validator = RequestValidator()
():
:
pagination = PaginationHelper.get_pagination_params()
query = User.query
request.args:
search = request.args[]
query = query.(User.name.contains(search) | User.email.contains(search))
sort_by = request.args.get(, )
sort_order = request.args.get(, )
(User, sort_by):
sort_order == :
query = query.order_by((User, sort_by).desc())
:
query = query.order_by((User, sort_by).asc())
total = query.count()
users = query.offset(pagination[]).limit(pagination[]).()
result = PaginationHelper.create_pagination_response(
[user.to_dict() user users],
total,
pagination[],
pagination[]
)
.create_response(data=result)
Exception e:
.handle_server_error(e)
():
:
user = User.query.get(user_id)
user:
.handle_not_found()
.create_response(data=user.to_dict())
Exception e:
.handle_server_error(e)
():
:
data = request.get_json()
data:
.create_response(
error=,
status_code=HTTPStatus.BAD_REQUEST.value
)
validated_data = .validator.validate_user_data(data)
User.query.filter_by(email=validated_data[]).first():
.handle_conflict()
user = User(
name=validated_data[],
email=validated_data[],
password_hash=
)
db.session.add(user)
db.session.commit()
.create_response(
data=user.to_dict(),
message=,
status_code=HTTPStatus.CREATED.value
)
ValidationError e:
.handle_validation_error(e)
Exception e:
db.session.rollback()
.handle_server_error(e)
():
:
user = User.query.get(user_id)
user:
.handle_not_found()
data = request.get_json()
data:
.create_response(
error=,
status_code=HTTPStatus.BAD_REQUEST.value
)
validated_data = .validator.validate_user_data(data, is_update=)
validated_data:
existing_user = User.query.(
User.email == validated_data[],
User. != user_id
).first()
existing_user:
.handle_conflict()
key, value validated_data.items():
(user, key):
(user, key, value)
user.updated_at = datetime.utcnow()
db.session.commit()
.create_response(
data=user.to_dict(),
message=
)
ValidationError e:
.handle_validation_error(e)
Exception e:
db.session.rollback()
.handle_server_error(e)
():
:
user = User.query.get(user_id)
user:
.handle_not_found()
db.session.delete(user)
db.session.commit()
.create_response(
data={: user.to_dict()},
message=,
status_code=HTTPStatus.NO_CONTENT.value
)
Exception e:
db.session.rollback()
.handle_server_error(e)
():
():
.validator = RequestValidator()
():
:
pagination = PaginationHelper.get_pagination_params()
query = Post.query
request.args:
query = query.(Post.author_id == request.args[])
request.args:
query = query.(Post.is_published == request.args[].lower() == )
request.args:
search = request.args[]
query = query.(Post.title.contains(search) | Post.content.contains(search))
sort_by = request.args.get(, )
sort_order = request.args.get(, )
(Post, sort_by):
sort_order == :
query = query.order_by((Post, sort_by).desc())
:
query = query.order_by((Post, sort_by).asc())
total = query.count()
posts = query.offset(pagination[]).limit(pagination[]).()
result = PaginationHelper.create_pagination_response(
[post.to_dict() post posts],
total,
pagination[],
pagination[]
)
.create_response(data=result)
Exception e:
.handle_server_error(e)
():
:
post = Post.query.get(post_id)
post:
.handle_not_found()
.create_response(data=post.to_dict())
Exception e:
.handle_server_error(e)
():
:
data = request.get_json()
data:
.create_response(
error=,
status_code=HTTPStatus.BAD_REQUEST.value
)
validated_data = .validator.validate_post_data(data)
author_id = validated_data.get()
User.query.get(author_id):
.handle_not_found()
post = Post(
title=validated_data[],
content=validated_data[],
author_id=author_id,
is_published=validated_data.get(, )
)
db.session.add(post)
db.session.commit()
.create_response(
data=post.to_dict(),
message=,
status_code=HTTPStatus.CREATED.value
)
ValidationError e:
.handle_validation_error(e)
Exception e:
db.session.rollback()
.handle_server_error(e)
user_controller = UserController()
post_controller = PostController()
():
user_controller.get_users()
():
user_controller.create_user()
():
user_controller.get_user(user_id)
():
user_controller.update_user(user_id)
():
user_controller.delete_user(user_id)
():
post_controller.get_posts()
():
post_controller.create_post()
():
post_controller.get_post(post_id)
():
APIController().create_response(
error=,
status_code=HTTPStatus.NOT_FOUND.value
)
():
APIController().create_response(
error=,
status_code=
)
():
APIController().handle_server_error(error)
():
()
app.app_context():
db.create_all()
()
()
()
()
()
()
()
()
()
()
()
()
()
__name__ == :
main()
app.run(debug=)
from typing import Dict, Any, List, Optional
from dataclasses import dataclass
from enum import Enum
import json
from datetime import datetime
class HTTPMethod(Enum):
"""HTTP方法"""
GET = "GET"
POST = "POST"
PUT = "PUT"
DELETE = "DELETE"
PATCH = "PATCH"
class ParameterType(Enum):
"""参数类型"""
STRING = "string"
INTEGER = "integer"
BOOLEAN = "boolean"
ARRAY = "array"
OBJECT = "object"
@dataclass
class APIParameter:
"""API参数"""
name: str
type: ParameterType
required: bool = False
description: str = ""
default_value: Any = None
example: Any = None
@dataclass
class APIResponse:
"""API响应"""
status_code: int
description: str
schema: [[, ]] =
example: [[, ]] =
:
path:
method: HTTPMethod
summary:
description:
parameters: [APIParameter]
responses: [APIResponse]
tags: []
:
():
.endpoints: [APIEndpoint] = []
.schemas: [, [, ]] = {}
.info = {
: ,
: ,
:
}
():
.endpoints.append(endpoint)
():
.schemas[name] = schema
() -> [, ]:
spec = {
: ,
: .info,
: {},
: {
: .schemas
}
}
paths = {}
endpoint .endpoints:
endpoint.path paths:
paths[endpoint.path] = {}
operation = {
: endpoint.summary,
: endpoint.description,
: endpoint.tags,
: [],
: {}
}
param endpoint.parameters:
param_spec = {
: param.name,
: endpoint.method [HTTPMethod.GET] ,
: param.required,
: {
: param..value
}
}
param.description:
param_spec[] = param.description
param.default_value :
param_spec[][] = param.default_value
param.example :
param_spec[] = param.example
operation[].append(param_spec)
response endpoint.responses:
response_spec = {
: response.description
}
response.schema:
response_spec[] = {
: {
: response.schema
}
}
response.example:
response_spec:
response_spec[] = {: {}}
response_spec[][][] = response.example
operation[][(response.status_code)] = response_spec
paths[endpoint.path][endpoint.method.value.lower()] = operation
spec[] = paths
spec
() -> :
lines = [
,
,
.info[],
,
,
,
]
tags = ()
endpoint .endpoints:
tags.update(endpoint.tags)
tag (tags):
lines.append()
lines.extend([, , ])
tag (tags):
lines.append()
lines.append()
tag_endpoints = [ep ep .endpoints tag ep.tags]
endpoint tag_endpoints:
lines.extend([
,
,
,
])
endpoint.parameters:
lines.append()
param endpoint.parameters:
required_str = param.required
lines.append()
param.description:
lines.append()
param.default_value :
lines.append()
lines.append()
lines.append()
response endpoint.responses:
lines.append()
lines.append()
lines.append()
lines.append()
.join(lines)
():
()
doc_gen = APIDocumentationGenerator()
user_schema = {
: ,
: {
: {: , : },
: {: , : , : },
: {: , : },
: {: },
: {: , : }
},
: [, ]
}
doc_gen.add_schema(, user_schema)
get_users_endpoint = APIEndpoint(
path=,
method=HTTPMethod.GET,
summary=,
description=,
parameters=[
APIParameter(, ParameterType.INTEGER, , , , ),
APIParameter(, ParameterType.INTEGER, , , , ),
APIParameter(, ParameterType.STRING, , ),
APIParameter(, ParameterType.STRING, , , ),
APIParameter(, ParameterType.STRING, , , )
],
responses=[
APIResponse(, , {: {: , : {: }}}),
APIResponse(, ),
APIResponse(, )
],
tags=[]
)
create_user_endpoint = APIEndpoint(
path=,
method=HTTPMethod.POST,
summary=,
description=,
parameters=[
APIParameter(, ParameterType.STRING, , , example=),
APIParameter(, ParameterType.STRING, , , example=),
APIParameter(, ParameterType.STRING, , )
],
responses=[
APIResponse(, , {: }),
APIResponse(, ),
APIResponse(, ),
APIResponse(, )
],
tags=[]
)
doc_gen.add_endpoint(get_users_endpoint)
doc_gen.add_endpoint(create_user_endpoint)
openapi_spec = doc_gen.generate_openapi_spec()
()
(json.dumps(openapi_spec, indent=, ensure_ascii=))
markdown_docs = doc_gen.generate_markdown_docs()
()
(markdown_docs[:] + (markdown_docs) > markdown_docs)
__name__ == :
main()
/api/v1/usersAccept: application/vnd.api+json;version=1?version=1