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 pathAPI项目的根目录
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-smorestapispec
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