extract-openapi-from-code

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

extract-openapi-from-code

从代码中提取OpenAPI规范

Extract an OpenAPI specification from an existing API codebase. Covers eight major frameworks across Python, Java, JavaScript/TypeScript, Ruby, and PHP.
从现有API代码库中提取OpenAPI规范。涵盖Python、Java、JavaScript/TypeScript、Ruby和PHP这几种语言下的8个主流框架。

Content Guides

内容指南

FrameworkLanguageGuide
FastAPIPythoncontent/frameworks/fastapi.md
FlaskPythoncontent/frameworks/flask.md
Django REST FrameworkPythoncontent/frameworks/django.md
Spring BootJavacontent/frameworks/spring-boot.md
NestJSTypeScriptcontent/frameworks/nestjs.md
HonoTypeScriptcontent/frameworks/hono.md
RailsRubycontent/frameworks/rails.md
LaravelPHPcontent/frameworks/laravel.md
Each guide provides detailed setup, schema definition, Speakeasy extensions, authentication, and troubleshooting for that framework.
框架语言指南
FastAPIPythoncontent/frameworks/fastapi.md
FlaskPythoncontent/frameworks/flask.md
Django REST FrameworkPythoncontent/frameworks/django.md
Spring BootJavacontent/frameworks/spring-boot.md
NestJSTypeScriptcontent/frameworks/nestjs.md
HonoTypeScriptcontent/frameworks/hono.md
RailsRubycontent/frameworks/rails.md
LaravelPHPcontent/frameworks/laravel.md
每个指南都提供了对应框架的详细设置、Schema定义、Speakeasy扩展、认证配置以及故障排查内容。

When to Use

适用场景

  • User has an existing API and wants to generate an OpenAPI spec from it
  • User wants to create an SDK from code that has no OpenAPI spec yet
  • User mentions a specific framework (FastAPI, Flask, Django, Spring Boot, NestJS, Hono, Rails, Laravel)
  • User says: "extract OpenAPI", "code first", "generate spec from code", "existing API code"
  • 用户已有一个API,希望从中生成OpenAPI规范
  • 用户想从没有OpenAPI规范的代码中创建SDK
  • 用户提到了特定框架(FastAPI、Flask、Django、Spring Boot、NestJS、Hono、Rails、Laravel)
  • 用户表述为:"extract OpenAPI"、"code first"、"从代码生成规范"、"现有API代码"

Inputs

输入参数

InputRequiredDescription
FrameworkYesThe API framework in use (see Decision Framework)
Project pathYesRoot directory of the API project
Output pathNoWhere to write the spec (default:
openapi.json
or
openapi.yaml
)
Target languageNoSDK target language, if generating an SDK after extraction
输入项是否必填描述
Framework是当前使用的API框架(参考决策框架)
Project path是API项目的根目录
Output path否规范文件的输出路径(默认:
openapi.json
或
openapi.yaml
)
Target language否提取后生成SDK的目标语言

Outputs

输出结果

OutputDescription
OpenAPI specA JSON or YAML file describing the API
Validation reportLint results from
speakeasy lint
输出项描述
OpenAPI spec描述API的JSON或YAML文件
Validation report来自
speakeasy lint
的检查结果

Prerequisites

前置条件

  • The API project must be buildable and its dependencies installed
  • For runtime extraction (FastAPI, Spring Boot, NestJS, Hono), the app must be importable or startable
  • speakeasy
    CLI installed for post-extraction validation and SDK generation
  • API项目必须可构建,且已安装所有依赖
  • 对于运行时提取(FastAPI、Spring Boot、NestJS、Hono),应用必须可导入或可启动
  • 已安装
    speakeasy
    CLI,用于提取后的验证和SDK生成

Decision Framework

决策框架

Use this tree to determine the extraction method:
FrameworkLanguageMethodRequires Running Server?
FastAPIPythonBuilt-in exportNo
Flask (flask-smorest)PythonCLI commandNo
Django REST FrameworkPythondrf-spectacular CLINo
Spring Boot (springdoc)JavaHTTP endpointYes
NestJSTypeScriptHTTP endpoint or scriptYes
Hono (zod-openapi)TypeScriptProgrammatic exportNo
Rails (rswag)RubyRake taskNo
Laravel (l5-swagger)PHPArtisan commandNo
使用以下树形结构确定提取方法:
框架语言方法是否需要运行服务器?
FastAPIPython内置导出否
Flask (flask-smorest)PythonCLI命令否
Django REST FrameworkPythondrf-spectacular CLI否
Spring Boot (springdoc)JavaHTTP端点是
NestJSTypeScriptHTTP端点或脚本是
Hono (zod-openapi)TypeScript程序化导出否
Rails (rswag)RubyRake任务否
Laravel (l5-swagger)PHPArtisan命令否

Command

命令示例

Choose the command matching your framework below. After extraction, always validate with
speakeasy lint
.
选择与你的框架匹配的命令。提取完成后,务必使用
speakeasy lint
进行验证。

Python: FastAPI

Python: FastAPI

FastAPI generates an OpenAPI schema at runtime. Export it without starting the server:
bash
python -c "import json; from myapp import app; print(json.dumps(app.openapi()))" > openapi.json
Replace
myapp
with the module containing your FastAPI
app
instance. If the app uses a factory pattern:
bash
python -c "import json; from myapp import create_app; app = create_app(); print(json.dumps(app.openapi()))" > openapi.json
You can also start the server and fetch from
http://localhost:8000/openapi.json
.
FastAPI会在运行时生成OpenAPI Schema。无需启动服务器即可导出:
bash
python -c "import json; from myapp import app; print(json.dumps(app.openapi()))" > openapi.json
将
myapp
替换为包含FastAPI
app
实例的模块。如果应用使用工厂模式:
bash
python -c "import json; from myapp import create_app; app = create_app(); print(json.dumps(app.openapi()))" > openapi.json
你也可以启动服务器,从
http://localhost:8000/openapi.json
获取。

Python: Flask (flask-smorest)

Python: Flask (flask-smorest)

Requires flask-smorest or apispec:
bash
flask openapi write openapi.json
If using apispec directly, export programmatically:
python
import json
from myapp import create_app, spec
app = create_app()
with app.app_context():
    print(json.dumps(spec.to_dict()))
需要依赖flask-smorest或apispec:
bash
flask openapi write openapi.json
如果直接使用apispec,可通过程序化方式导出:
python
import json
from myapp import create_app, spec
app = create_app()
with app.app_context():
    print(json.dumps(spec.to_dict()))

Python: Django REST Framework

Python: Django REST Framework

Requires drf-spectacular:
bash
python manage.py spectacular --file openapi.yaml
For JSON output:
bash
python manage.py spectacular --format openapi-json --file openapi.json
需要依赖drf-spectacular:
bash
python manage.py spectacular --file openapi.yaml
如需JSON格式输出:
bash
python manage.py spectacular --format openapi-json --file openapi.json

Java: Spring Boot

Java: Spring Boot

Requires springdoc-openapi. Start the application, then fetch the spec:
bash
undefined
需要依赖springdoc-openapi。启动应用后,获取规范:
bash
undefined

Start the app (background)

启动应用(后台运行)

./mvnw spring-boot:run &
./mvnw spring-boot:run &

Wait for startup

等待启动完成

sleep 15
sleep 15

Fetch the spec

获取规范

For YAML format

如需YAML格式

Stop the app

停止应用

kill %1

If the server runs on a different port or context path, adjust the URL accordingly.
kill %1

如果服务器运行在不同端口或上下文路径,请相应调整URL。

TypeScript: NestJS

TypeScript: NestJS

Requires @nestjs/swagger. Start the application, then fetch:
bash
undefined
需要依赖@nestjs/swagger。启动应用后,获取规范:
bash
undefined

Start the app (background)

启动应用(后台运行)

npm run start & sleep 10
npm run start & sleep 10

Fetch the spec (default path with SwaggerModule)

获取规范(SwaggerModule默认路径)

curl http://localhost:3000/api-json -o openapi.json
curl http://localhost:3000/api-json -o openapi.json

Stop the app

停止应用

kill %1

Alternatively, create a script to export without running the server:

```typescript
// scripts/export-openapi.ts
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from '../src/app.module';
import * as fs from 'fs';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { logger: false });
  const config = new DocumentBuilder().setTitle('API').build();
  const doc = SwaggerModule.createDocument(app, config);
  fs.writeFileSync('openapi.json', JSON.stringify(doc, null, 2));
  await app.close();
}
bootstrap();
kill %1

或者,创建脚本无需启动服务器即可导出:

```typescript
// scripts/export-openapi.ts
import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from '../src/app.module';
import * as fs from 'fs';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { logger: false });
  const config = new DocumentBuilder().setTitle('API').build();
  const doc = SwaggerModule.createDocument(app, config);
  fs.writeFileSync('openapi.json', JSON.stringify(doc, null, 2));
  await app.close();
}
bootstrap();

TypeScript: Hono (zod-openapi)

TypeScript: Hono (zod-openapi)

Requires @hono/zod-openapi. Export the schema programmatically:
typescript
// scripts/export-openapi.ts
import { app } from '../src/app';
import * as fs from 'fs';

const doc = app.doc('/doc', {
  openapi: '3.1.0',
  info: { title: 'API', version: '1.0.0' },
});
fs.writeFileSync('openapi.json', JSON.stringify(doc, null, 2));
Run with:
bash
npx tsx scripts/export-openapi.ts
需要依赖@hono/zod-openapi。通过程序化方式导出Schema:
typescript
// scripts/export-openapi.ts
import { app } from '../src/app';
import * as fs from 'fs';

const doc = app.doc('/doc', {
  openapi: '3.1.0',
  info: { title: 'API', version: '1.0.0' },
});
fs.writeFileSync('openapi.json', JSON.stringify(doc, null, 2));
运行脚本:
bash
npx tsx scripts/export-openapi.ts

Ruby: Rails (rswag)

Ruby: Rails (rswag)

Requires rswag:
bash
rails rswag:specs:swaggerize
The spec is written to
swagger/v1/swagger.yaml
by default (configurable in
config/initializers/rswag_api.rb
).
需要依赖rswag:
bash
rails rswag:specs:swaggerize
规范默认写入
swagger/v1/swagger.yaml
(可在
config/initializers/rswag_api.rb
中配置)。

PHP: Laravel (l5-swagger)

PHP: Laravel (l5-swagger)

Requires l5-swagger:
bash
php artisan l5-swagger:generate
The spec is written to
storage/api-docs/api-docs.json
by default.
需要依赖l5-swagger:
bash
php artisan l5-swagger:generate
规范默认写入
storage/api-docs/api-docs.json
。

Post-Extraction Steps

提取后步骤

After extracting the spec, always run these steps:
提取规范后,务必执行以下步骤:

1. Validate the spec

1. 验证规范

bash
speakeasy lint openapi --non-interactive -s openapi.json
bash
speakeasy lint openapi --non-interactive -s openapi.json

2. Fix issues with overlays (if needed)

2. 使用Overlay修复问题(如有需要)

If validation reveals issues, use an overlay rather than modifying the extracted spec directly:
bash
speakeasy overlay apply -s openapi.json -o fixes.yaml
To fix validation errors, create an OpenAPI overlay file and apply it with
speakeasy overlay apply -s <spec> -o <overlay>
.
如果验证发现问题,请使用Overlay而非直接修改提取的规范:
bash
speakeasy overlay apply -s openapi.json -o fixes.yaml
如需修复验证错误,创建一个OpenAPI Overlay文件,然后使用
speakeasy overlay apply -s <spec> -o <overlay>
命令应用。

3. Generate an SDK

3. 生成SDK

bash
speakeasy quickstart --skip-interactive --output console \
  -s openapi.json \
  -t <target> \
  -n <name> \
  -p <package>
Run
speakeasy quickstart -s <spec> -t <language>
to initialize a new SDK project.
bash
speakeasy quickstart --skip-interactive --output console \
  -s openapi.json \
  -t <target> \
  -n <name> \
  -p <package>
运行
speakeasy quickstart -s <spec> -t <language>
初始化新的SDK项目。

Example

示例

Full workflow for a FastAPI project:
bash
undefined
FastAPI项目的完整工作流:
bash
undefined

1. Extract the OpenAPI spec

1. 提取OpenAPI规范

cd /path/to/my-fastapi-project python -c "import json; from main import app; print(json.dumps(app.openapi()))" > openapi.json
cd /path/to/my-fastapi-project python -c "import json; from main import app; print(json.dumps(app.openapi()))" > openapi.json

2. Validate

2. 验证

speakeasy lint openapi --non-interactive -s openapi.json
speakeasy lint openapi --non-interactive -s openapi.json

3. Generate a TypeScript SDK

3. 生成TypeScript SDK

speakeasy quickstart --skip-interactive --output console
-s openapi.json
-t typescript
-n "MyApiSDK"
-p "my-api-sdk"
undefined
speakeasy quickstart --skip-interactive --output console
-s openapi.json
-t typescript
-n "MyApiSDK"
-p "my-api-sdk"
undefined

Adding Speakeasy Extensions

添加Speakeasy扩展

After extracting a spec, add Speakeasy-specific extensions for better SDK output. These can be added in framework config or via overlay.
提取规范后,添加Speakeasy特定扩展以优化SDK输出。这些扩展可在框架配置中添加,或通过Overlay应用。

FastAPI: Add Extensions via
openapi_extra

FastAPI: 通过
openapi_extra
添加扩展

python
@app.get(
    "/items",
    openapi_extra={
        "x-speakeasy-retries": {
            "strategy": "backoff",
            "backoff": {"initialInterval": 500, "maxInterval": 60000, "exponent": 1.5},
            "statusCodes": ["5XX", "429"]
        },
        "x-speakeasy-group": "items",
        "x-speakeasy-name-override": "list"
    }
)
def list_items(): ...
python
@app.get(
    "/items",
    openapi_extra={
        "x-speakeasy-retries": {
            "strategy": "backoff",
            "backoff": {"initialInterval": 500, "maxInterval": 60000, "exponent": 1.5},
            "statusCodes": ["5XX", "429"]
        },
        "x-speakeasy-group": "items",
        "x-speakeasy-name-override": "list"
    }
)
def list_items(): ...

Django: Add Extensions via
SPECTACULAR_SETTINGS

Django: 通过
SPECTACULAR_SETTINGS
添加扩展

python
undefined
python
undefined

settings.py

settings.py

SPECTACULAR_SETTINGS = { # ... other settings 'EXTENSIONS_TO_SCHEMA_FUNCTION': lambda generator, request, public: { 'x-speakeasy-retries': { 'strategy': 'backoff', 'backoff': {'initialInterval': 500, 'maxInterval': 60000, 'exponent': 1.5}, 'statusCodes': ['5XX'] } } }
undefined
SPECTACULAR_SETTINGS = { # ... 其他设置 'EXTENSIONS_TO_SCHEMA_FUNCTION': lambda generator, request, public: { 'x-speakeasy-retries': { 'strategy': 'backoff', 'backoff': {'initialInterval': 500, 'maxInterval': 60000, 'exponent': 1.5}, 'statusCodes': ['5XX'] } } }
undefined

Spring Boot: Add Extensions via Custom
OperationCustomizer

Spring Boot: 通过自定义
OperationCustomizer
添加扩展

java
@Bean
public OperationCustomizer operationCustomizer() {
    return (operation, handlerMethod) -> {
        operation.addExtension("x-speakeasy-group",
            handlerMethod.getBeanType().getSimpleName().replace("Controller", "").toLowerCase());
        return operation;
    };
}
java
@Bean
public OperationCustomizer operationCustomizer() {
    return (operation, handlerMethod) -> {
        operation.addExtension("x-speakeasy-group",
            handlerMethod.getBeanType().getSimpleName().replace("Controller", "").toLowerCase());
        return operation;
    };
}

NestJS: Add Extensions via Decorator Options

NestJS: 通过装饰器选项添加扩展

typescript
@Get()
@ApiOperation({
  summary: 'List items',
  operationId: 'listItems'
})
@ApiExtension('x-speakeasy-group', 'items')
@ApiExtension('x-speakeasy-name-override', 'list')
listItems() { ... }
typescript
@Get()
@ApiOperation({
  summary: 'List items',
  operationId: 'listItems'
})
@ApiExtension('x-speakeasy-group', 'items')
@ApiExtension('x-speakeasy-name-override', 'list')
listItems() { ... }

Via Overlay (Any Framework)

通过Overlay添加(任意框架)

If you cannot modify framework code, use an overlay:
yaml
overlay: 1.0.0
info:
  title: Speakeasy Extensions
  version: 1.0.0
actions:
  - target: $.paths['/items'].get
    update:
      x-speakeasy-group: items
      x-speakeasy-name-override: list
如果无法修改框架代码,可使用Overlay:
yaml
overlay: 1.0.0
info:
  title: Speakeasy Extensions
  version: 1.0.0
actions:
  - target: $.paths['/items'].get
    update:
      x-speakeasy-group: items
      x-speakeasy-name-override: list

Common Issues After Extraction

提取后常见问题

IssueSymptomFix
Missing operationIdsLint warning; SDK methods get generic namesAdd operationIds via overlay or use
speakeasy suggest operation-ids -s openapi.json
Missing descriptionsLint hints; SDK has no documentationAdd descriptions to endpoints and schemas in source code or via overlay
Overly permissive schemasSchemas use
additionalProperties: true
or lack type constraints
Tighten schemas in source code; use stricter validation decorators
No response schemasLint errors; SDK return types are
any
/
object
Add explicit response models to your framework endpoints
Duplicate operationIdsLint errors; generation failsEnsure each endpoint has a unique operationId
Missing authenticationNo security schemes in specAdd security metadata to your framework config or via overlay
问题症状修复方案
缺少operationIds检查警告;SDK方法使用通用名称通过Overlay添加operationIds,或使用
speakeasy suggest operation-ids -s openapi.json
命令
缺少描述检查提示;SDK无文档在源代码或Overlay中为端点和Schema添加描述
Schema过于宽松Schema使用
additionalProperties: true
或缺少类型约束
在源代码中收紧Schema;使用更严格的验证装饰器
无响应Schema检查错误;SDK返回类型为
any
/
object
为框架端点添加明确的响应模型
重复的operationIds检查错误;生成失败确保每个端点有唯一的operationId
缺少认证信息规范中无安全方案在框架配置或Overlay中添加安全元数据

What NOT to Do

禁忌事项

  • Do NOT hand-write an OpenAPI spec when the framework can generate one -- always extract first
  • Do NOT edit the extracted spec directly -- use overlays for fixes so re-extraction does not lose changes
  • Do NOT skip validation -- extracted specs often have issues that block SDK generation
  • Do NOT assume the extracted spec is complete -- frameworks may omit auth, error responses, or headers
  • Do NOT start the server in production mode for extraction -- use development or test configuration
  • 请勿在框架可自动生成时手动编写OpenAPI规范——务必优先提取
  • 请勿直接编辑提取的规范——使用Overlay进行修复,避免重新提取时丢失修改
  • 请勿跳过验证步骤——提取的规范通常存在问题,会阻碍SDK生成
  • 请勿假设提取的规范是完整的——框架可能会遗漏认证、错误响应或头信息
  • 请勿在生产模式下启动服务器进行提取——使用开发或测试配置

Troubleshooting

故障排查

ErrorCauseSolution
ModuleNotFoundError
(Python)
App dependencies not installedRun
pip install -r requirements.txt
or
pip install -e .
Connection refused (Spring Boot, NestJS)Server not fully startedIncrease sleep time or poll for readiness
Empty or minimal specRoutes not registered at import timeEnsure all route modules are imported; check lazy loading
YAML parse errorExtracted file has invalid syntaxRe-extract; check for print statements polluting stdout
Cannot find module
(Node.js)
Dependencies not installedRun
npm install
or
yarn install
No
/v3/api-docs
endpoint (Spring Boot)
springdoc not configuredAdd
springdoc-openapi-starter-webmvc-ui
to dependencies
No
/api-json
endpoint (NestJS)
Swagger module not set upConfigure
SwaggerModule.setup(app, ...)
in
main.ts
错误原因解决方案
ModuleNotFoundError
(Python)
应用依赖未安装运行
pip install -r requirements.txt
或
pip install -e .
连接被拒绝(Spring Boot、NestJS)服务器未完全启动增加等待时间或轮询就绪状态
规范为空或内容极少路由未在导入时注册确保所有路由模块已导入;检查懒加载设置
YAML解析错误提取的文件语法无效重新提取;检查是否有打印语句污染标准输出
Cannot find module
(Node.js)
依赖未安装运行
npm install
或
yarn install
无
/v3/api-docs
端点(Spring Boot)
springdoc未配置添加
springdoc-openapi-starter-webmvc-ui
到依赖中
无
/api-json
端点(NestJS)
Swagger模块未设置在
main.ts
中配置
SwaggerModule.setup(app, ...)

Related Skills

相关技能

  • manage-openapi-overlays
    - Add x-speakeasy-* extensions via overlay
  • start-new-sdk-project
    - Generate SDK after extraction
  • manage-openapi-overlays
    - 通过Overlay添加x-speakeasy-*扩展
  • start-new-sdk-project
    - 提取后生成SDK