plugins {
kotlin("jvm") version "1.9.25"
kotlin("plugin.spring") version "1.9.25"
id("org.springframework.boot") version "3.4.5"
id("io.spring.dependency-management") version "1.1.7"
id("org.asciidoctor.jvm.convert") version "3.3.2"
id("com.epages.restdocs-api-spec") version "0.19.4"
id("org.hidetake.swagger.generator") version "2.19.2"
kotlin("plugin.jpa") version "1.9.25"
}
extra["snippetsDir"] = file("build/generated-snippets")
openapi3 {
val local = closureOf<Server> {
url("http://localhost:8080")
description("Local Development Server")
} as Closure<Server>
val dev = closureOf<Server> {
url("https://dev-api.freeapp.me")
description("dev Development Server")
} as Closure<Server>
setServers(listOf(local, dev))
title = "API 문서"
description = "RestDocsWithSwagger Docs"
version = "0.0.1"
format = "yaml"
//outputDirectory = "build/resources/main/static/docs"
}
swaggerSources {
create("api") {
setInputFile(layout.buildDirectory.file("api-spec/openapi3.yaml").get().asFile)
}
}
dependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
testImplementation("org.springframework.security:spring-security-test")
testImplementation("com.epages:restdocs-api-spec-mockmvc:0.19.4")
testImplementation("org.instancio:instancio-junit:5.4.1")
// Swagger UI
swaggerUI("org.webjars:swagger-ui:5.21.0")
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.test {
outputs.dir(project.extra["snippetsDir"]!!)
}
tasks.asciidoctor {
inputs.dir(project.extra["snippetsDir"]!!)
dependsOn(tasks.test)
}
tasks.bootJar {
dependsOn(tasks.getByName("generateSwaggerUIApi"))
from("${tasks.getByName<GenerateSwaggerUI>("generateSwaggerUIApi").outputDir}") {
into("static/docs/")
}
}
tasks.withType<GenerateSwaggerUI> {
dependsOn("openapi3")
inputFile = layout.buildDirectory.file("api-spec/openapi3.yaml").get().asFile
options.set("docExpansion", "none")
}
multipart-form-data-support-issue
multipart-form-data는 아직 지원을 안 한다. 따라서, 임시로 description 편의 생성 함수를 만듬
fun formatMultipartFormDescription(
title: String = "## Multipart Form Data 필드",
fields: List<Triple<String, String, Boolean>> // 필드명, 설명, 필수 여부
): String {
val sb = StringBuilder()
sb.appendLine(title)
sb.appendLine()
// 테이블 헤더
sb.appendLine("| 필드명 | 설명 | 필수 여부 |")
sb.appendLine("|--------|------|----------|")
// 필드 정보
fields.forEach { (name, description, required) ->
val requiredText = if (required) "필수" else "선택"
sb.appendLine("| `$name` | $description | $requiredText |")
}
sb.appendLine()
sb.appendLine("> ⚠️ Swagger UI에서는 multipart form data 전송이 제대로 되지 않으므로 여기에 표시")
return sb.toString()
}
OpenAPI 3.0 스펙에서 null은 유효한 타입이 아님
Spring Rest Docs 와 Swagger-UI 연동
[Spring] restdocs + swagger 같이 사용하기
Swagger와 Spring rest docs, 두마리 토끼 잡기!
Spring boot | Restdocs-api-spec with Swagger, Docker 완전 정복 하기
Spring Rest Docs로 행복해지는 간단한 방법
Spring RestDocs 개선기(2) - 리플렉션을 이용한 Enum 문서 작성 자동화