从 scala 源代码 (http4s) 生成 Swagger / OpenAPI 规范
Generate Swagger / OpenAPI specification from scala source code (http4s)
所以我不是 swagger 专家,但所有使用 swagger 的系统都要求您在 JSON 或 YAML 中定义 swagger 规范,定义 API 的所有端点(等等)。
我的问题是:是否有已知的方法可以根据实际源代码生成这些规范文件?
我在问,因为当您开始添加属性或返回略有不同的结果时,似乎很难使端点代码和文档保持同步。
所以当我有这段代码时(使用 http4s 和 RhoService):
object HelloWorld {
val service = new RhoService {
GET / "hello" / 'name |>> { name: String =>
Ok(Json.obj("message" -> Json.fromString(s"Hello, ${name}")))
}
}
}
如果能产生(以某种方式)就太好了
/hello/{name}:
get:
tags:
- "HelloWorld"
summary: ""
description: ""
operationId: "getHellobyName"
produces:
- "application/json"
parameters:
- name: "name"
in: "path"
description: ""
required: true
type: "string"
responses:
200:
description: "successful operation"
schema:
$ref: "#/definitions/Hello"
security:
- api_key: []
它没有很好地记录,但显然 http4s 的 RhoService
添加了中间件以根据您的路由生成 swagger.json
:
通过调用“http://localhost:8080/swagger.json”获取它
免责声明:我是 tapir.
的作者
rho 是一种可能性。另一种方法是将 API 端点的描述与业务逻辑完全分开。
有一个端点的描述,这是一个常规的 Scala 值,然后它可以 解释 作为服务器(给定 "business logic" 函数),或者文档。
免责声明:我是 endpoints4s.
的作者
类似于 tapir(在另一个答案中提到)endpoints4s 是一个可以为 HTTP 端点生成 http4s 服务器和 OpenAPI 文档的库。
您可以像下面这样编写您的示例:
// --- This is the description of your HTTP service
import endpoints4s.algebra
case class Hello(message: String)
trait HelloWorldEndpoints
extends algebra.Endpoints
with algebra.JsonEntitiesFromSchemas {
implicit val helloJsonSchema: JsonSchema[Hello] =
field[String]("message")
.xmap(message => Hello(message))(hello => hello.message)
val hello: Endpoint[String, Hello] =
endpoint(
get(path / "hello" / segment[String]("name")),
ok(jsonResponse[Hello])
)
}
// --- This is an OpenApi documentation of the endpoints defined
// --- in HelloWorldEndpoints
import endpoints4s.openapi
import endpoints4s.openapi.model.{ Info, OpenApi }
object HelloWorldDocumentation
extends HelloWorldEndpoints
with openapi.Endpoints
with openapi.JsonEntitiesFromSchemas {
val api: OpenApi =
openApi(Info(title = "Hello API", version = "1.0"))(
hello
)
}
// --- This is an http4s server that implements the endpoints defined
// --- in HelloWorldEndpoints
import endpoints4s.http4s
import cats.effect.IO
import org.http4s.HttpRoutes
object HelloWorld
extends http4s.server.Endpoints[IO]
with http4s.server.JsonEntitiesFromSchemas
with HelloWorldEndpoints {
val service: HttpRoutes[IO] = HttpRoutes.of(
routesFromEndpoints(
hello.implementedBy(name => Hello(s"Hello, ${name}"))
)
)
}
// --- And this is an http4s service that publishes the OpenApi documentation
object OpenApiServer
extends http4s.server.Endpoints[IO]
with http4s.server.JsonEntitiesFromEncodersAndDecoders {
val openApiService: HttpRoutes[IO] = HttpRoutes.of(
routesFromEndpoints(
endpoint(
get(path / "open-api.json"),
ok(jsonResponse[OpenApi])
).implementedBy(_ => HelloWorldDocumentation.api)
)
)
}
所以我不是 swagger 专家,但所有使用 swagger 的系统都要求您在 JSON 或 YAML 中定义 swagger 规范,定义 API 的所有端点(等等)。
我的问题是:是否有已知的方法可以根据实际源代码生成这些规范文件? 我在问,因为当您开始添加属性或返回略有不同的结果时,似乎很难使端点代码和文档保持同步。
所以当我有这段代码时(使用 http4s 和 RhoService):
object HelloWorld {
val service = new RhoService {
GET / "hello" / 'name |>> { name: String =>
Ok(Json.obj("message" -> Json.fromString(s"Hello, ${name}")))
}
}
}
如果能产生(以某种方式)就太好了
/hello/{name}:
get:
tags:
- "HelloWorld"
summary: ""
description: ""
operationId: "getHellobyName"
produces:
- "application/json"
parameters:
- name: "name"
in: "path"
description: ""
required: true
type: "string"
responses:
200:
description: "successful operation"
schema:
$ref: "#/definitions/Hello"
security:
- api_key: []
它没有很好地记录,但显然 http4s 的 RhoService
添加了中间件以根据您的路由生成 swagger.json
:
通过调用“http://localhost:8080/swagger.json”获取它
免责声明:我是 tapir.
的作者rho 是一种可能性。另一种方法是将 API 端点的描述与业务逻辑完全分开。
有一个端点的描述,这是一个常规的 Scala 值,然后它可以 解释 作为服务器(给定 "business logic" 函数),或者文档。
免责声明:我是 endpoints4s.
的作者类似于 tapir(在另一个答案中提到)endpoints4s 是一个可以为 HTTP 端点生成 http4s 服务器和 OpenAPI 文档的库。
您可以像下面这样编写您的示例:
// --- This is the description of your HTTP service
import endpoints4s.algebra
case class Hello(message: String)
trait HelloWorldEndpoints
extends algebra.Endpoints
with algebra.JsonEntitiesFromSchemas {
implicit val helloJsonSchema: JsonSchema[Hello] =
field[String]("message")
.xmap(message => Hello(message))(hello => hello.message)
val hello: Endpoint[String, Hello] =
endpoint(
get(path / "hello" / segment[String]("name")),
ok(jsonResponse[Hello])
)
}
// --- This is an OpenApi documentation of the endpoints defined
// --- in HelloWorldEndpoints
import endpoints4s.openapi
import endpoints4s.openapi.model.{ Info, OpenApi }
object HelloWorldDocumentation
extends HelloWorldEndpoints
with openapi.Endpoints
with openapi.JsonEntitiesFromSchemas {
val api: OpenApi =
openApi(Info(title = "Hello API", version = "1.0"))(
hello
)
}
// --- This is an http4s server that implements the endpoints defined
// --- in HelloWorldEndpoints
import endpoints4s.http4s
import cats.effect.IO
import org.http4s.HttpRoutes
object HelloWorld
extends http4s.server.Endpoints[IO]
with http4s.server.JsonEntitiesFromSchemas
with HelloWorldEndpoints {
val service: HttpRoutes[IO] = HttpRoutes.of(
routesFromEndpoints(
hello.implementedBy(name => Hello(s"Hello, ${name}"))
)
)
}
// --- And this is an http4s service that publishes the OpenApi documentation
object OpenApiServer
extends http4s.server.Endpoints[IO]
with http4s.server.JsonEntitiesFromEncodersAndDecoders {
val openApiService: HttpRoutes[IO] = HttpRoutes.of(
routesFromEndpoints(
endpoint(
get(path / "open-api.json"),
ok(jsonResponse[OpenApi])
).implementedBy(_ => HelloWorldDocumentation.api)
)
)
}