405 lines
13 KiB
Markdown
405 lines
13 KiB
Markdown
# Swagger2OpenAPI 集成实现方案
|
||
|
||
## 1. swagger2openapi 包介绍
|
||
|
||
### 1.1 包的作用
|
||
`swagger2openapi` 是一个专门用于将 Swagger 2.0 (OpenAPI 2.0) 规范转换为 OpenAPI 3.0.x 规范的 Node.js 包。它具有以下主要功能:
|
||
|
||
- **自动转换**:将 Swagger 2.0 规范自动转换为 OpenAPI 3.0.x 格式
|
||
- **引用保护**:默认保留几乎所有的 `$ref` JSON 引用,不会解引用所有项目
|
||
- **模式转换**:自动"修复"不兼容的 Swagger 2.0 模式问题
|
||
- **验证功能**:内置 OpenAPI 3.0.x 验证功能
|
||
- **多种输入源**:支持从文件、URL、字符串等多种方式加载规范
|
||
- **规范扩展**:支持有限的现实世界规范扩展
|
||
|
||
### 1.2 核心特性
|
||
- **引用保护**:保持 `$ref` 引用而不是完全解引用
|
||
- **错误修复**:自动修复小错误(patch 模式)
|
||
- **灵活配置**:丰富的配置选项
|
||
- **多格式支持**:支持 JSON 和 YAML 格式
|
||
- **高性能**:经过 74,426 个真实世界 Swagger 2.0 定义的测试
|
||
|
||
## 2. 在 mcp-swagger-parser 中的应用场景
|
||
|
||
### 2.1 当前痛点
|
||
- 许多传统 API 仍然使用 Swagger 2.0 格式
|
||
- 现有的 `@apidevtools/swagger-parser` 主要针对 OpenAPI 3.0+
|
||
- 需要手动处理 Swagger 2.0 到 OpenAPI 3.0 的转换
|
||
|
||
### 2.2 集成收益
|
||
- **自动兼容**:无缝支持 Swagger 2.0 规范
|
||
- **透明转换**:用户无需关心底层版本转换
|
||
- **减少错误**:自动修复常见的 Swagger 2.0 问题
|
||
- **提升体验**:统一的 API 接口处理两种格式
|
||
|
||
## 3. 技术实现方案
|
||
|
||
### 3.1 架构设计
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ OpenAPIParser │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
||
│ │ URL Parser │ │ File Parser │ │ Text Parser │ │
|
||
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ Version Detection & Conversion │ │
|
||
│ │ ┌─────────────────┐ ┌─────────────────────────────┐ │ │
|
||
│ │ │ Swagger 2.0 │ │ OpenAPI 3.0+ │ │ │
|
||
│ │ │ Detection │ │ Direct Parse │ │ │
|
||
│ │ └─────────────────┘ └─────────────────────────────┘ │ │
|
||
│ │ │ │ │ │
|
||
│ │ ▼ │ │ │
|
||
│ │ ┌─────────────────┐ │ │ │
|
||
│ │ │ swagger2openapi │ │ │ │
|
||
│ │ │ Conversion │ │ │ │
|
||
│ │ └─────────────────┘ │ │ │
|
||
│ │ │ │ │ │
|
||
│ │ └──────────────────────────┘ │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
||
│ │ Validator │ │ Normalizer │ │ Transformer │ │
|
||
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 3.2 核心组件实现
|
||
|
||
#### 3.2.1 版本检测器 (VersionDetector)
|
||
```typescript
|
||
export class VersionDetector {
|
||
static detect(spec: any): 'swagger2' | 'openapi3' | 'unknown' {
|
||
if (spec.swagger && spec.swagger.startsWith('2.')) {
|
||
return 'swagger2';
|
||
}
|
||
if (spec.openapi && spec.openapi.startsWith('3.')) {
|
||
return 'openapi3';
|
||
}
|
||
return 'unknown';
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.2.2 Swagger2OpenAPI 转换器 (Swagger2OpenAPIConverter)
|
||
```typescript
|
||
import * as swagger2openapi from 'swagger2openapi';
|
||
|
||
export class Swagger2OpenAPIConverter {
|
||
private options: swagger2openapi.Options;
|
||
|
||
constructor(options: ConversionOptions = {}) {
|
||
this.options = {
|
||
patch: true, // 修复小错误
|
||
warnOnly: false, // 遇到错误时抛出异常
|
||
resolveInternal: false, // 不解析内部引用
|
||
...options
|
||
};
|
||
}
|
||
|
||
async convert(swagger2Spec: any): Promise<OpenAPISpec> {
|
||
try {
|
||
const result = await swagger2openapi.convertObj(swagger2Spec, this.options);
|
||
return result.openapi;
|
||
} catch (error) {
|
||
throw new Swagger2OpenAPIConversionError(
|
||
`Failed to convert Swagger 2.0 to OpenAPI 3.0: ${error.message}`,
|
||
error
|
||
);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.2.3 增强的解析器 (EnhancedParser)
|
||
```typescript
|
||
export class EnhancedParser extends OpenAPIParser {
|
||
private converter: Swagger2OpenAPIConverter;
|
||
|
||
constructor(config: ParserConfig = {}) {
|
||
super(config);
|
||
this.converter = new Swagger2OpenAPIConverter({
|
||
patch: config.autoFix !== false,
|
||
warnOnly: !config.strictMode
|
||
});
|
||
}
|
||
|
||
protected async processSpec(
|
||
spec: any,
|
||
metadata: Partial<ParseResult['metadata']>
|
||
): Promise<ParseResult> {
|
||
// 检测版本
|
||
const version = VersionDetector.detect(spec);
|
||
|
||
// 如果是 Swagger 2.0,先转换为 OpenAPI 3.0
|
||
if (version === 'swagger2') {
|
||
console.log('检测到 Swagger 2.0 规范,正在转换为 OpenAPI 3.0...');
|
||
spec = await this.converter.convert(spec);
|
||
|
||
// 更新元数据
|
||
metadata.conversionPerformed = true;
|
||
metadata.originalVersion = 'swagger2';
|
||
metadata.targetVersion = 'openapi3';
|
||
}
|
||
|
||
// 调用父类处理逻辑
|
||
return super.processSpec(spec, metadata);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.3 配置选项扩展
|
||
|
||
#### 3.3.1 新增配置接口
|
||
```typescript
|
||
export interface EnhancedParserConfig extends ParserConfig {
|
||
// Swagger 2.0 转换选项
|
||
swagger2Options?: {
|
||
patch?: boolean; // 是否修复小错误
|
||
warnOnly?: boolean; // 是否仅警告而不抛出异常
|
||
resolveInternal?: boolean; // 是否解析内部引用
|
||
targetVersion?: string; // 目标 OpenAPI 版本
|
||
preserveRefs?: boolean; // 是否保留引用
|
||
};
|
||
|
||
// 自动检测和转换
|
||
autoConvert?: boolean; // 是否自动转换 Swagger 2.0
|
||
autoFix?: boolean; // 是否自动修复错误
|
||
}
|
||
```
|
||
|
||
#### 3.3.2 默认配置
|
||
```typescript
|
||
export const ENHANCED_DEFAULT_CONFIG: Required<EnhancedParserConfig> = {
|
||
...DEFAULT_PARSER_CONFIG,
|
||
swagger2Options: {
|
||
patch: true,
|
||
warnOnly: false,
|
||
resolveInternal: false,
|
||
targetVersion: '3.0.0',
|
||
preserveRefs: true
|
||
},
|
||
autoConvert: true,
|
||
autoFix: true
|
||
};
|
||
```
|
||
|
||
### 3.4 错误处理增强
|
||
|
||
#### 3.4.1 新增错误类型
|
||
```typescript
|
||
export class Swagger2OpenAPIConversionError extends OpenAPIParseError {
|
||
constructor(
|
||
message: string,
|
||
public originalError?: Error,
|
||
public conversionOptions?: any
|
||
) {
|
||
super(message, ERROR_CODES.CONVERSION_ERROR);
|
||
this.name = 'Swagger2OpenAPIConversionError';
|
||
}
|
||
}
|
||
|
||
export class UnsupportedVersionError extends OpenAPIParseError {
|
||
constructor(version: string) {
|
||
super(
|
||
`Unsupported API specification version: ${version}`,
|
||
ERROR_CODES.UNSUPPORTED_VERSION
|
||
);
|
||
this.name = 'UnsupportedVersionError';
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.4.2 错误码扩展
|
||
```typescript
|
||
export const ERROR_CODES = {
|
||
...existingErrorCodes,
|
||
CONVERSION_ERROR: 'CONVERSION_ERROR',
|
||
UNSUPPORTED_VERSION: 'UNSUPPORTED_VERSION',
|
||
VERSION_DETECTION_FAILED: 'VERSION_DETECTION_FAILED'
|
||
};
|
||
```
|
||
|
||
### 3.5 类型定义增强
|
||
|
||
#### 3.5.1 元数据扩展
|
||
```typescript
|
||
export interface EnhancedParseMetadata extends ParseMetadata {
|
||
conversionPerformed?: boolean;
|
||
originalVersion?: 'swagger2' | 'openapi3';
|
||
targetVersion?: string;
|
||
conversionDuration?: number;
|
||
patchesApplied?: number;
|
||
}
|
||
```
|
||
|
||
#### 3.5.2 解析结果扩展
|
||
```typescript
|
||
export interface EnhancedParseResult extends ParseResult {
|
||
metadata: EnhancedParseMetadata;
|
||
conversionWarnings?: string[];
|
||
}
|
||
```
|
||
|
||
## 4. 实现步骤
|
||
|
||
### 4.1 Phase 1: 基础集成 (Week 1)
|
||
1. **安装依赖**
|
||
```bash
|
||
npm install swagger2openapi @types/swagger2openapi
|
||
```
|
||
|
||
2. **创建版本检测器**
|
||
- 实现 `VersionDetector` 类
|
||
- 添加版本检测逻辑
|
||
- 编写单元测试
|
||
|
||
3. **创建转换器**
|
||
- 实现 `Swagger2OpenAPIConverter` 类
|
||
- 配置转换选项
|
||
- 处理转换错误
|
||
|
||
### 4.2 Phase 2: 解析器增强 (Week 2)
|
||
1. **增强主解析器**
|
||
- 修改 `OpenAPIParser` 类
|
||
- 集成版本检测和转换逻辑
|
||
- 更新配置接口
|
||
|
||
2. **错误处理完善**
|
||
- 添加新的错误类型
|
||
- 完善错误消息和堆栈跟踪
|
||
- 添加错误恢复机制
|
||
|
||
### 4.3 Phase 3: 功能完善 (Week 3)
|
||
1. **配置选项扩展**
|
||
- 扩展配置接口
|
||
- 实现配置验证
|
||
- 添加配置文档
|
||
|
||
2. **元数据和日志增强**
|
||
- 扩展元数据信息
|
||
- 添加转换过程日志
|
||
- 实现性能监控
|
||
|
||
### 4.4 Phase 4: 测试和优化 (Week 4)
|
||
1. **全面测试**
|
||
- 单元测试覆盖
|
||
- 集成测试
|
||
- 性能测试
|
||
|
||
2. **文档和示例**
|
||
- 更新 API 文档
|
||
- 添加使用示例
|
||
- 编写迁移指南
|
||
|
||
## 5. 使用示例
|
||
|
||
### 5.1 基本使用
|
||
```typescript
|
||
import { parseAndTransform } from 'mcp-swagger-parser';
|
||
|
||
// 自动检测和转换 Swagger 2.0
|
||
const tools = await parseAndTransform('swagger2-api.json', {
|
||
parserConfig: {
|
||
autoConvert: true,
|
||
swagger2Options: {
|
||
patch: true,
|
||
warnOnly: false
|
||
}
|
||
}
|
||
});
|
||
```
|
||
|
||
### 5.2 高级配置
|
||
```typescript
|
||
const parser = new OpenAPIParser({
|
||
autoConvert: true,
|
||
swagger2Options: {
|
||
patch: true,
|
||
resolveInternal: false,
|
||
targetVersion: '3.0.3'
|
||
}
|
||
});
|
||
|
||
const result = await parser.parseFromUrl('https://api.example.com/swagger.json');
|
||
|
||
if (result.metadata.conversionPerformed) {
|
||
console.log(`转换完成: ${result.metadata.originalVersion} -> ${result.metadata.targetVersion}`);
|
||
console.log(`转换耗时: ${result.metadata.conversionDuration}ms`);
|
||
}
|
||
```
|
||
|
||
### 5.3 错误处理
|
||
```typescript
|
||
try {
|
||
const result = await parseFromFile('swagger2.yaml');
|
||
} catch (error) {
|
||
if (error instanceof Swagger2OpenAPIConversionError) {
|
||
console.error('Swagger 2.0 转换失败:', error.message);
|
||
console.error('原始错误:', error.originalError);
|
||
} else if (error instanceof UnsupportedVersionError) {
|
||
console.error('不支持的版本:', error.message);
|
||
}
|
||
}
|
||
```
|
||
|
||
## 6. 兼容性考虑
|
||
|
||
### 6.1 向后兼容
|
||
- 现有 API 保持不变
|
||
- 新功能通过配置选项启用
|
||
- 默认行为保持一致
|
||
|
||
### 6.2 性能影响
|
||
- 转换操作仅在检测到 Swagger 2.0 时执行
|
||
- 内存使用增加约 10-20%
|
||
- 解析时间增加约 5-15%
|
||
|
||
### 6.3 依赖管理
|
||
- `swagger2openapi` 作为直接依赖
|
||
- 版本锁定确保稳定性
|
||
- 定期更新和安全扫描
|
||
|
||
## 7. 测试策略
|
||
|
||
### 7.1 测试覆盖
|
||
- 单元测试:> 90%
|
||
- 集成测试:主要使用场景
|
||
- 性能测试:基准测试和回归测试
|
||
|
||
### 7.2 测试数据
|
||
- 真实世界的 Swagger 2.0 规范
|
||
- 边缘情况和错误情况
|
||
- 大型复杂规范的性能测试
|
||
|
||
### 7.3 持续集成
|
||
- 自动化测试流水线
|
||
- 多 Node.js 版本测试
|
||
- 依赖安全扫描
|
||
|
||
## 8. 风险评估
|
||
|
||
### 8.1 技术风险
|
||
- **依赖风险**:swagger2openapi 包维护状态
|
||
- **转换风险**:复杂规范的转换准确性
|
||
- **性能风险**:大型规范的处理性能
|
||
|
||
### 8.2 缓解策略
|
||
- 版本锁定和定期评估
|
||
- 全面的测试覆盖
|
||
- 性能监控和优化
|
||
|
||
## 9. 总结
|
||
|
||
通过集成 `swagger2openapi`,`mcp-swagger-parser` 将能够:
|
||
|
||
1. **无缝支持** Swagger 2.0 和 OpenAPI 3.0+ 规范
|
||
2. **自动转换** 旧版规范到新版格式
|
||
3. **提升用户体验** 通过统一的 API 接口
|
||
4. **增强错误处理** 和调试能力
|
||
5. **保持向后兼容** 现有功能
|
||
|
||
这个集成方案既能满足现有用户需求,又能扩展对传统 API 的支持,是一个平衡的技术决策。
|