VaporToOpenAPI 是一个 Swift 库,可以从 Vapor 代码生成兼容 OpenAPI 3.0.1 版本的输出。您可以将生成的文件与 Swagger UI 或 Stoplight 一起使用。该库基于 SwiftOpenAPI。
添加一个路由,使用 app.routes.openAPI
方法返回一个 OpenAPIObject
。此方法从您的 Vapor 路由生成完整的 OpenAPI 规范。它接受诸如 API 的标题、描述、可用路径、操作和安全要求等参数。
// generate OpenAPI documentation
routes.get("Swagger", "swagger.json") { req in
req.application.routes.openAPI(
info: InfoObject(
title: "Example API",
description: "Example API description",
version: "0.1.0",
)
)
}
.excludeFromOpenAPI()
stoplightDocumentation(openAPI:)
辅助方法生成一个 Stoplight 页面。此方法也可以返回一个 OpenAPIObject
。在路由上使用 .openAPI
修饰符来指定诸如操作摘要、描述、请求/响应正文、查询参数和标头之类的参数。 以下是如何使用它来记录 POST
请求的示例
routes.post("users") { req -> EventLoopFuture<User> in
let user = try req.content.decode(User.self)
return user.save(on: req.db).map { user }
}
.openAPI(
summary: "Create User",
description: "Create a new user with the provided data",
body: .type(User.self),
response: .type(User.self)
)
重要提示
您模型中的所有枚举必须实现 CaseIterable
。
VaporToOpenAPI 提供了几个高级功能,用于自定义您的 OpenAPI 文档
response
:此方法用于为 Vapor 路由指定额外的响应正文。 它接受各种参数,例如状态代码、描述和响应正文类型。groupedOpenAPI
:这些方法用于根据 OpenAPI 元数据(例如标签或安全要求)将 Vapor 路由分组在一起。let routes = app.routes.groupedOpenAPI(auth: .apiKey())
groupedOpenAPIResponse
:这些方法用于基于公共响应将 Vapor 路由分组在一起。
groupedOpenAPI(server:)
:这些方法用于基于公共服务器将 Vapor 路由分组在一起。
excludeFromOpenAPI
:此方法用于从生成的 OpenAPI 规范中排除一个 Vapor 路由或路由组。
openAPINoAuth
:此方法用于指定操作不需要任何身份验证。
openAPI(custom:)
:这些方法用于自定义 Vapor 路由的 OpenAPI 元数据的特定方面,例如特定的安全方案或回调。
stoplightDocumentation(openAPI:)
:这些方法用于从您的 Vapor 路由生成 Stoplight 文档。
operationID
和 operationRef
:这些属性用于为 OpenAPI 操作生成唯一标识符,并在规范的其他部分中创建对它们的引用。
您可以通过实现 OpenAPIDescriptable
和 OpenAPIType
协议来自定义 OpenAPI 模式和参数结果。
OpenAPIDescriptable
协议允许您为类型及其属性提供自定义描述。 @OpenAPIDescriptable
宏使用您的注释实现此协议。import SwiftOpenAPI
@OpenAPIDescriptable
/// Login request body.
struct LoginBody: Codable {
/// Username string.
let username: String
/// Password string. Encoded.
let password: String
}
手动
struct LoginBody: Codable, OpenAPIDescriptable {
let username: String
let password: String
static var openAPIDescription: OpenAPIDescriptionType? {
OpenAPIDescription<CodingKeys>("Login request body.")
.add(for: .username, "Username string.")
.add(for: .password, "Password string. Encoded.")
}
}
OpenAPIType
协议允许您为类型提供自定义模式。import SwiftOpenAPI
struct Color: Codable, OpenAPIType {
static var openAPISchema: SchemaObject {
.string(format: "hex", description: "Color in hex format")
}
}
链接是 OpenAPI 3.0 的新功能之一。使用链接,您可以描述一个操作返回的各种值如何用作其他操作的输入。要创建一个链接
LinkKey
类型,用于标识一些可重用的参数。enum PetID: LinkKey {
}
route.get("pet", use: getPet).openAPI(
links: [
Link("id", in: .response): PetID.self
]
)
route.post("pet", ":petID", use: renamePer).openAPI(
links: [
Link("petID", in: .path): PetID.self
]
)
通过下载 dist
文件夹并将其内容放在 Public/Swagger
目录中,在您的 Vapor 项目中设置一个 SwaggerUI 页面。
按照 Vapor 文档中的描述,描述您的所有路由并注册所有控制器。 使用 route.openAPI
方法将 OpenAPI 详细信息添加到每个路由。
添加一个路由以返回 SwaggerUI index.html。或者配置您的中间件以使用 'index.html' 作为默认页面。
通过 app.routes.openAPI
方法添加一个路由以返回一个 OpenAPIObject
实例。 确保此路由的路径与 SwaggerUI 页面方法中的 swagger.json
URL 匹配。
更改 swagger-initializer.js
中的 url
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
var jsonURL = document.location.origin + "/Swagger/swagger.json";
window.ui = SwaggerUIBundle({
url: jsonURL,
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
//</editor-fold>
};
routes = routes
.groupedOpenAPI(auth: .basic)
.groupedOpenAPIResponse(
statusCode: 400,
body: .type(of: ErrorResponse())
)
routes.post("login") { req in
try await loginService.makeLoginRequest(
query: req.query.decode(LoginQuery.self),
content: req.content.decode(LoginRequestBody.self)
)
}
.openAPI(
summary: "Login",
description: "Login request",
query: .type(LoginQuery.self),
headers: ["X-SOME_VALUE": .string],
body: .type(LoginRequestBody.self),
response: .type(LoginResponse.self),
auth: .apiKey()
)
FileMiddleware(publicDirectory: app.directory.publicDirectory, defaultFile: "index.html")
// generate OpenAPI documentation
routes.get("Swagger", "swagger.json") { req in
req.application.routes.openAPI(
info: InfoObject(
title: "Example API",
description: "Example API description",
version: "0.1.0",
)
)
}
.excludeFromOpenAPI()
创建一个 Package.swift
文件。
// swift-tools-version:5.9
import PackageDescription
let package = Package(
name: "SomeProject",
dependencies: [
.package(url: "https://github.com/dankinsoid/VaporToOpenAPI.git", from: "4.7.1")
],
targets: [
.target(name: "SomeProject", dependencies: ["VaporToOpenAPI"])
]
)
$ swift build
欢迎对 VaporToOpenAPI 做出贡献!如果您发现错误或有功能要求,请提出问题或提交
dankinsoid, voidilov@gmail.com
VaporToOpenAPI 在 MIT 许可下可用。 有关更多信息,请参见 LICENSE 文件。