Apitore blog

Apitoreを運営していた元起業家のブログ

(旧名)Swaggerで社内用と社外用のAPIドキュメントを分けて生成する

はじめに

旧名Swagger、新名称OpenAPI Specificationで、社内用と社外用のAPIドキュメントを分けて生成する方法を紹介します。正確に言うと、SpringfoxでSpring-bootのRestControllerからAPIドキュメントを自動生成している場合に使えるテクニックです。 amarec (20160928-213708)

前提条件

  • Spring-bootのRestControllerでWeb APIを提供している
  • APIドキュメントはSpringfoxで自動生成している

最低限使うライブラリは以下です。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <version>1.3.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger2</artifactId>
  <version>2.4.0</version>
</dependency>

ビフォー

Spring-bootでWeb APIを提供する場合、以下のようなクラスを作ると思います。URLに"public"が含まれるAPIを社外用、"private"が含まれるAPIを社内用とします。

@RestController
@RequestMapping(value = "/example")
public class ExampleController {
  //省略
  @RequestMapping(value="/public/hoge", method=RequestMethod.GET)
  public String hoge() {
  }
  @RequestMapping(value="/private/hoge", method=RequestMethod.GET)
  public String privatehoge() {
  }
}

Springfoxを使うと、以下のようなクラスを作ってAPIのドキュメントを自動生成すると思います。

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
  @Bean
  public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
        .select()
        .apis(RequestHandlerSelectors.basePackage("example.controller"))
        .paths(PathSelectors.any())
        .build()
        .apiInfo(new ApiInfoBuilder().title("Example APIs").build());
  }
}

しかし、これだと社内用と社外用のAPIドキュメントが一緒のjson(/v2/api-docs)で出力されてしまいます。社内用は試験APIとか使用回数無制限とかにしているので、公開されるとまずいわけです。

アフター

というわけで、SwaggerConfigurationを以下のように書き換えます。Docketを2つ立ち上げて、それぞれgroupNameを追加して、pathsを特定のURLに指定しただけです。

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
  @Bean
  public Docket publicApi() {
    return new Docket(DocumentationType.SWAGGER_2)
       .groupName("public")
       .select()
        .apis(RequestHandlerSelectors.basePackage("example.controller"))
        .paths(or(regex(.*/public/.*)))
        .build()
        .apiInfo(new ApiInfoBuilder().title("Example Public APIs").build());
  }
  @Bean
  public Docket privateApi() {
    return new Docket(DocumentationType.SWAGGER_2)
        .groupName("private")
        .select()
        .apis(RequestHandlerSelectors.basePackage("example.controller"))
        .paths(or(regex(.*/private/.*)))
        .build()
        .apiInfo(new ApiInfoBuilder().title("Example Private APIs").build());
  }
}

これで"/v2/api-docs?group=public"にアクセスすると社外用のAPIドキュメントのjsonが、"/v2/api-docs?group=private"にアクセスすると社内用のAPIドキュメントのjsonが、それぞれ生成されます。これは何をやっているかというと、APIのグルーピングです。pathsで特定のURLを指定し、groupNameでグループ名をつけています。

おわりに

たったこれだけでAPIドキュメントを分けることが出来ます。当然ながら、今回紹介したテクニックは社内と社外を分けるだけではなく、APIの種類ごとに分けるといった運用もできます。