mcp-swagger-server/docs/swagger2openapi-integration...

13 KiB
Raw Blame History

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)

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)

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)

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 新增配置接口

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 默认配置

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 新增错误类型

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 错误码扩展

export const ERROR_CODES = {
  ...existingErrorCodes,
  CONVERSION_ERROR: 'CONVERSION_ERROR',
  UNSUPPORTED_VERSION: 'UNSUPPORTED_VERSION',
  VERSION_DETECTION_FAILED: 'VERSION_DETECTION_FAILED'
};

3.5 类型定义增强

3.5.1 元数据扩展

export interface EnhancedParseMetadata extends ParseMetadata {
  conversionPerformed?: boolean;
  originalVersion?: 'swagger2' | 'openapi3';
  targetVersion?: string;
  conversionDuration?: number;
  patchesApplied?: number;
}

3.5.2 解析结果扩展

export interface EnhancedParseResult extends ParseResult {
  metadata: EnhancedParseMetadata;
  conversionWarnings?: string[];
}

4. 实现步骤

4.1 Phase 1: 基础集成 (Week 1)

  1. 安装依赖

    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 基本使用

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 高级配置

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 错误处理

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. 总结

通过集成 swagger2openapimcp-swagger-parser 将能够:

  1. 无缝支持 Swagger 2.0 和 OpenAPI 3.0+ 规范
  2. 自动转换 旧版规范到新版格式
  3. 提升用户体验 通过统一的 API 接口
  4. 增强错误处理 和调试能力
  5. 保持向后兼容 现有功能

这个集成方案既能满足现有用户需求,又能扩展对传统 API 的支持,是一个平衡的技术决策。