連携させるのにハマったので備忘録です。
使用するライブラリ
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-http" % "10.1.7",
"com.github.swagger-akka-http" %% "swagger-akka-http" % "2.0.3",
"javax.ws.rs" % "javax.ws.rs-api" % "2.0.1",
"ch.megard" %% "akka-http-cors" % "0.4.1"
)
APIエンドポイントの定義
/itemsでレスポンスを返すAPIを作成します
ItemContoller
package json_server.http.controller
import akka.http.scaladsl.model.{ ContentType, HttpEntity, HttpResponse, MediaTypes, StatusCodes }
import akka.http.scaladsl.server.{ Directives, Route }
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{ Content, Schema }
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import javax.ws.rs._
@Path("/items")
@Consumes(Array("application/json"))
@Produces(Array("application/json"))
class ItemController extends Directives {
def route: Route = create
@GET
@Operation(
summary = "Get Items",
description = "",
requestBody = new RequestBody(content = Array(new Content(schema = new Schema()))),
responses = Array(
new ApiResponse(responseCode = "200",
description = "Create response",
content = Array(new Content(schema = new Schema()))),
new ApiResponse(responseCode = "500", description = "Internal server error")
)
)
def create: Route = path("items") {
get {
complete(
HttpResponse(entity = HttpEntity(ContentType(MediaTypes.`application/json`), """
{"items":"pen"}
"""))
)
}
}
}
SwaggerDocServiceの定義
SwaggerDocService.scala
package json_server.http
import com.github.swagger.akka.SwaggerHttpService
import com.typesafe.config.ConfigFactory
class SwaggerDocService(val apis: Set[Class[_]]) extends SwaggerHttpService {
val conf = ConfigFactory.load
val address = conf.getString(MY_HOST) // 0.0.0.0
val port = conf.getInt(MY_PORT) // 5000
override val apiClasses = apis
override val host = s"$address:$port"
override val apiDocsPath = "api-docs" // このパスでyaml/jsonを生成する
override val schemes = List("https") // httpsを使いたい場合はhttpsを指定
}
Routeの定義
Routes.scala
package json_server.http
import akka.actor.ActorSystem
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ ExceptionHandler, Route }
import akka.util.Timeout
import ch.megard.akka.http.cors.scaladsl.CorsDirectives._
import json_server.http.controller.ItemControlle
import scala.util.control.NonFatal
class Routes()(implicit system: ActorSystem, timeout: Timeout) extends SprayJsonSupport {
/***
* Custom Error Handler
*/
implicit def customExceptionHandler: ExceptionHandler = ExceptionHandler {
case NonFatal(ex) =>
extractLog { implicit log =>
extractUri { uri =>
val errorMessage = s"ERROR!! URI: $uri, REASON: ${ex.getMessage}"
log.error(errorMessage)
complete(StatusCodes.InternalServerError -> errorMessage)
}
}
}
/***
* Routing
*/
val routes: Route = (cors() | handleExceptions(customExceptionHandler)) { // Route作成時にcors()を呼ばないとSwaggerでExecuteした時にレスポンスの内容が画面に表示されない
extractLog { implicit log =>
extractUri { uri =>
extractMethod { method =>
log.info(s"call api. method: ${method.value}, uri: $uri")
path("swagger") {
getFromResource("swagger/index.html")
} ~
// swaggerディレクトリ下のファイルにアクセス可能にする
getFromResourceDirectory("swagger") ~
// APIエンドポイントとなるクラスをSwaggerHttpService.apiClassesに渡す
new SwaggerDocService(Set(classOf[ItemController])).routes ~
// エンドポイントのルーティングを追加
new ItemController().route
}
}
}
}
}
swagger.yamlを生成する
ブラウザで以下のURLにアクセスする。
https://localhost:5000/api-docs/swagger.yaml
すると、以下のyaml形式のテキストがブラウザに表示される。
openapi: 3.0.1
info:
title: ""
description: ""
termsOfService: ""
version: ""
servers:
- url: https://0.0.0.0:5000
security: []
paths:
/items:
get:
summary: Get Items
operationId: create
requestBody:
content:
application/json: {}
responses:
200:
description: Create response
content:
application/json: {}
500:
description: Internal server error
components:
schemas:
Function1RequestContextFutureRouteResult:
type: object
resources
下にswagger.yaml
を作成し、この内容をコピペする。
Swaggerの実行
ブラウザで以下のURLにアクセスすると、Swagger UIが起動する。
https://localhost:5000/swagger
画面上部のテキストボックスに、ペットストア用のSwaggerリソースhttps://petstore.swagger.io/v2/swagger.json
が指定されているので、先程作成したswagger.yaml
を指定する。
実行するとSwaggerでエンドポイントにアクセスすることができるようになる。
毎回swagger.yaml
を指定するのが面倒なので、以下のURLで画面を表示すればswagger.yaml
を読み込んだ状態でスタートできる。
https://localhost:5000/swagger?https://localhost:5000/swagger.yaml