上手Swagger3.0,踩了两个坑

4,519 阅读4分钟

踩坑前言

Swagger3.0出来一段时间了,虽然简化了基础的配置,但作为一个大版本的升级肯定存在不少问题,不少2.x版本的类都被标记为过时了,大部分类的构造与属性设置依旧都交给了对应的Buidler处理,但不少配置上都引入了函数式接口去处理,对于对函数式编程不太了解的开发者而言可能有一定的配置难度。目前国内较少对3.0版本的配置介绍,所以自己在项目里将Swagger升级到3.0后看了下替代了标记过时(@Deprecated)相应功能的源码进行相应的配置,结果踩了2个坑,所以分享下踩坑记录与3.0的通用配置方式。

踩坑记录

项目中使用了jwt鉴权,但无论对于开发人员还是测试人员来说每次Swagger测接口前都要登录获取token,每次传token都是一件很麻烦的事,所以我便打算按Swagger比较常用的全局参数设置将Authorization设为全局header并设置默认值,于是有了以下3.0(OAS_30指Open API Spefication 3.0)中的配置:

@Bean
public Docket docket() {
    return new Docket(DocumentationType.OAS_30)
            .globalRequestParameters(Lists.newArrayList(
                    new RequestParameterBuilder()
                            .name("debug")
                            .description("ignore authorization")
                            .in(ParameterType.HEADER)
                            // 类内部创建了默认的builder以供属性设置
                            .query(parameterSpecificationBuilder -> parameterSpecificationBuilder.defaultValue("1")
                                    .allowEmptyValue(true))
                            .build(),
                    new RequestParameterBuilder()
                            .name("Authorization")
                            .description("token")
                            .query(parameterSpecificationBuilder -> parameterSpecificationBuilder.defaultValue("1")
                                    .allowEmptyValue(true))
                            .in(ParameterType.HEADER)
                            .build()
            ))
            .select()
            .paths(PathSelectors.regex("^(?!/error).*"))
            .build();
}

以上配置中的query()可以看成是Swagger3.0中配置风格的一个核心:在配置类中创建好相应的属性对象builder,并暴露一个该builder的Conumser函数式接口作为参数的方法,开发者根据需要提供一个Consumer进行对该builder的操作(属性设置),只要了解了该风格相信基本上新版本的配置看看源码也能很快上手。
以上配置代码query()方法中我取了RequestParameterBuilder类中的属性对象simpleParameterBuilder引用进行了属性设置,RequestParameterBuilder部分源码:

public class RequestParameterBuilder {
  ......
  SimpleParameterSpecificationBuilder simpleParameterBuilder;
  
  ...... 
  
  private SimpleParameterSpecificationBuilder queryBuilder() {
    if (simpleParameterBuilder == null) {
      simpleParameterBuilder = new SimpleParameterSpecificationBuilder();
    }
    return simpleParameterBuilder;
  }
  
  public RequestParameterBuilder query(@NonNull Consumer<SimpleParameterSpecificationBuilder> parameter) {
    parameter.accept(queryBuilder());
    return this;
  }
  
  ......

其实个人认为既然集成SpringBoot了以properties类为主导进行属性设置而非Builder与FunctionalInterface对开发者使用而言会更便利,现在先踩坑填坑。按照对2.x的版本配置与了解个人以为以上的配置应该是没有问题的,然而居然出现了2个坑。

坑A:name为Authorization的全局header参数值将无法传到后端

当我添加一个Authorization的全局header的时候测试时发现怎么传都没有传到后端,一开始以为是Swagger的bug,但考虑到这个name的敏感性,我就去翻了下OpenAPI 3.0(Swagger 3.0是按照OpenAPI 3.0的规范去设计实现的,文档的数据格式也是遵循3.0规范),于是翻出了以下内容: parameter-object-doc 当全局header参数中包含命名为AccpetContent-TypeAuthorization的参数时,参数的定义将被忽略。于是我加了一个非忽略header,得到了以下结果:

swagger-authorization-header

可以看到全局header设置中debug是能接收到的,而Authorization是被忽略的,即基本确认非bug,只是我没有看规范而已。既然以该方式定义的Authorization header无法被接收,但Swagger以往的版本还有一种设置全局token的方式-SecurityContextSecurityReference

@Bean
public Docket docket() {
    return new Docket(DocumentationType.OAS_30)
            .securityContexts(Arrays.asList(SecurityContext.builder()
                    .securityReferences(Arrays.asList(SecurityReference.builder()
                            .reference("Authorization")
                            .scopes(new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")})
                            .build()))
                    .build()))
            .securitySchemes(Arrays.asList(new ApiKey("Authorization", "Authorization", "header")))
            .select()
            .paths(PathSelectors.regex("^(?!/error).*"))
            .build();
}

SecurityContextSecurityReference的设置与以往版本变化不大,结果也达到了个人的期望(后端能获取到Authorization header),只是该方式配置的header无法设置默认值而已,效果图如下: Swagger-Security

坑B:全局参数的默认值并没有起效

虽然通过query()方法设置了参数默认值,但实质上Swagger并没有把该默认值设置到页面上,从坑1中的演示图1可以看到全局参数即使设置了初始值1,但页面上还是空的。该坑确认了是3.0的bug,在github里也找到了相应的issue,该bug已加到了3.0.1的里程碑中(即3.0.1版本会修复):

结语

虽然官方框架的使用更具有普遍性,但目前还是觉得自己写的香,如果以上3.0版本出现的问题会影响当前项目的测试使用则不建议先升级,玩玩尚可。 personal-swagger