Skip to content

Commit 7cbb356

Browse files
committed
improve response status writer (#339)
1 parent cc74993 commit 7cbb356

File tree

5 files changed

+126
-13
lines changed

5 files changed

+126
-13
lines changed

src/main/kotlin/io/openapiprocessor/spring/processor/SpringFrameworkAnnotations.kt

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,16 @@ class SpringFrameworkAnnotations: FrameworkAnnotations {
4646
}
4747

4848
override fun getAnnotation(status: EndpointResponseStatus): Annotation {
49-
return RESPONSE_STATUS_ANNOTATION
49+
val statusCode = HTTP_STATUS[status.statusCode]
50+
if (statusCode == null) {
51+
log.error("unknown http status code: ${status.statusCode}")
52+
return UNKNOWN_ANNOTATION
53+
}
54+
55+
return Annotation(
56+
getAnnotationName("ResponseStatus"),
57+
linkedMapOf(
58+
"code" to SimpleParameterValue(statusCode, HTTP_STATUS_ENUM)))
5059
}
5160

5261
private fun getAnnotation(key: String): Annotation {
@@ -95,12 +104,6 @@ private val PARAMETER_ANNOTATIONS = hashMapOf(
95104
"body" to Annotation (getAnnotationName("RequestBody"))
96105
)
97106

98-
private val RESPONSE_STATUS_ANNOTATION = Annotation (
99-
getAnnotationName("ResponseStatus"),
100-
linkedMapOf("code" to SimpleParameterValue(
101-
"HttpStatus", "org.springframework.http.HttpStatus"
102-
)))
103-
104107
private val UNKNOWN_ANNOTATION = Annotation("Unknown")
105108

106109
private const val ANNOTATION_PKG = "org.springframework.web.bind.annotation"
@@ -113,3 +116,81 @@ private fun getMappingAnnotationName(mappingName: String): String {
113116
private fun getAnnotationName(name: String): String {
114117
return "${ANNOTATION_PKG}.${name}"
115118
}
119+
120+
private val HTTP_STATUS = hashMapOf(
121+
"100" to getEnum("CONTINUE"),
122+
"101" to getEnum("SWITCHING_PROTOCOLS"),
123+
"102" to getEnum("PROCESSING"), // WebDAV
124+
"103" to getEnum("CHECKPOINT"),
125+
126+
"200" to getEnum("OK"),
127+
"201" to getEnum("CREATED"),
128+
"202" to getEnum("ACCEPTED"),
129+
"203" to getEnum("NON_AUTHORITATIVE_INFORMATION"),
130+
"204" to getEnum("NO_CONTENT"),
131+
"205" to getEnum("RESET_CONTENT"),
132+
"206" to getEnum("PARTIAL_CONTENT"),
133+
"207" to getEnum("MULTI_STATUS"), // WebDAV
134+
"208" to getEnum("ALREADY_REPORTED"), // WebDAV
135+
"226" to getEnum("IM_USED"),
136+
137+
"300" to getEnum("MULTIPLE_CHOICES"),
138+
"301" to getEnum("MOVED_PERMANENTLY"),
139+
"302" to getEnum("FOUND"), // replaces MOVED_TEMPORARILY
140+
"303" to getEnum("SEE_OTHER"),
141+
"304" to getEnum("NOT_MODIFIED"),
142+
"305" to getEnum("USE_PROXY"),
143+
"307" to getEnum("TEMPORARY_REDIRECT"),
144+
"308" to getEnum("PERMANENT_REDIRECT"),
145+
146+
"400" to getEnum("BAD_REQUEST"),
147+
"401" to getEnum("UNAUTHORIZED"),
148+
"402" to getEnum("PAYMENT_REQUIRED"),
149+
"403" to getEnum("FORBIDDEN"),
150+
"404" to getEnum("NOT_FOUND"),
151+
"405" to getEnum("METHOD_NOT_ALLOWED"),
152+
"406" to getEnum("NOT_ACCEPTABLE"),
153+
"407" to getEnum("PROXY_AUTHENTICATION_REQUIRED"),
154+
"408" to getEnum("REQUEST_TIMEOUT"),
155+
"409" to getEnum("CONFLICT"),
156+
"410" to getEnum("GONE"),
157+
"411" to getEnum("LENGTH_REQUIRED"),
158+
"412" to getEnum("PRECONDITION_FAILED"),
159+
"413" to getEnum("PAYLOAD_TOO_LARGE"), // replaces REQUEST_ENTITY_TOO_LARGE
160+
"414" to getEnum("URI_TOO_LONG"), // replaces REQUEST_URI_TOO_LONG
161+
"415" to getEnum("UNSUPPORTED_MEDIA_TYPE"),
162+
"416" to getEnum("REQUESTED_RANGE_NOT_SATISFIABLE"),
163+
"417" to getEnum("EXPECTATION_FAILED"),
164+
"418" to getEnum("I_AM_A_TEAPOT"),
165+
"419" to getEnum("INSUFFICIENT_SPACE_ON_RESOURCE"), // WebDAV
166+
"420" to getEnum("METHOD_FAILURE"), // WebDAV
167+
"421" to getEnum("DESTINATION_LOCKED"), // WebDAV
168+
"422" to getEnum("UNPROCESSABLE_ENTITY"), // WebDAV
169+
"423" to getEnum("LOCKED"), // WebDAV
170+
"424" to getEnum("FAILED_DEPENDENCY"), // WebDAV
171+
"425" to getEnum("TOO_EARLY"),
172+
"426" to getEnum("UPGRADE_REQUIRED"),
173+
"428" to getEnum("PRECONDITION_REQUIRED"),
174+
"429" to getEnum("TOO_MANY_REQUESTS"),
175+
"431" to getEnum("REQUEST_HEADER_FIELDS_TOO_LARGE"),
176+
"451" to getEnum("UNAVAILABLE_FOR_LEGAL_REASONS"),
177+
178+
"500" to getEnum("INTERNAL_SERVER_ERROR"),
179+
"501" to getEnum("NOT_IMPLEMENTED"),
180+
"502" to getEnum("BAD_GATEWAY"),
181+
"503" to getEnum("SERVICE_UNAVAILABLE"),
182+
"504" to getEnum("GATEWAY_TIMEOUT"),
183+
"505" to getEnum("HTTP_VERSION_NOT_SUPPORTED"),
184+
"506" to getEnum("VARIANT_ALSO_NEGOTIATES"),
185+
"507" to getEnum("INSUFFICIENT_STORAGE"), // WebDAV
186+
"508" to getEnum("LOOP_DETECTED"), // WebDAV
187+
"509" to getEnum("BANDWIDTH_LIMIT_EXCEEDED"),
188+
"510" to getEnum("NOT_EXTENDED"),
189+
"511" to getEnum("NETWORK_AUTHENTICATION_REQUIRED")
190+
)
191+
192+
private const val HTTP_STATUS_ENUM = "org.springframework.http.HttpStatus"
193+
194+
private fun getEnum(name: String): String {
195+
return "HttpStatus.${name}"
196+
}

src/main/kotlin/io/openapiprocessor/spring/writer/java/StatusAnnotationWriter.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ class StatusAnnotationWriter(private val annotations: FrameworkAnnotations): Cor
2424

2525
private fun createStatusAnnotation(status: EndpointResponseStatus): String {
2626
val data = annotations.getAnnotation(status)
27-
val statusCode = status.statusCode.toInt()
27+
val status = data.parameters["code"]
2828

2929
var annotation = data.annotationName
30-
annotation += "("
31-
annotation += "HttpStatus.valueOf($statusCode)"
32-
annotation += ")"
30+
annotation += "(${status!!.value})"
3331
return annotation
3432
}
3533
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2025 https://github.com/openapi-processor/openapi-processor-spring
3+
* PDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.openapiprocessor.spring.processor
7+
8+
import io.kotest.core.spec.style.StringSpec
9+
import io.kotest.matchers.collections.shouldContainExactly
10+
import io.kotest.matchers.shouldBe
11+
import io.openapiprocessor.core.model.EndpointResponseStatus
12+
import io.openapiprocessor.core.model.HttpStatus
13+
14+
15+
class SpringFrameworkAnnotationsSpec : StringSpec({
16+
17+
class Status(override val statusCode: HttpStatus) : EndpointResponseStatus
18+
19+
"provides known HttpStatus annotation with specific status code import" {
20+
val framework = SpringFrameworkAnnotations()
21+
22+
val annotation200 = framework.getAnnotation(Status("200"))
23+
annotation200.referencedImports shouldContainExactly setOf("org.springframework.http.HttpStatus")
24+
annotation200.parameters["code"]!!.value shouldBe "HttpStatus.OK"
25+
26+
val annotation400 = framework.getAnnotation(Status("400"))
27+
annotation400.referencedImports shouldContainExactly setOf("org.springframework.http.HttpStatus")
28+
annotation400.parameters["code"]!!.value shouldBe "HttpStatus.BAD_REQUEST"
29+
30+
val annotation500 = framework.getAnnotation(Status("500"))
31+
annotation500.referencedImports shouldContainExactly setOf("org.springframework.http.HttpStatus")
32+
annotation500.parameters["code"]!!.value shouldBe "HttpStatus.INTERNAL_SERVER_ERROR"
33+
}
34+
})

src/test/kotlin/io/openapiprocessor/spring/writer/java/StatusAnnotationWriterSpec.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ class StatusAnnotationWriterSpec: StringSpec({
3232

3333
writer.write(target, ep, ep.endpointResponses.first())
3434

35-
target.toString() shouldBeEqual """@ResponseStatus(HttpStatus.valueOf(204))"""
35+
target.toString() shouldBeEqual """@ResponseStatus(HttpStatus.NO_CONTENT)"""
3636
}
3737
})

src/testInt/resources/tests/response-status/outputs/api/Api.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
@Generated(value = "openapi-processor-spring", version = "test")
99
public interface Api {
1010

11-
@ResponseStatus(HttpStatus.valueOf(204))
11+
@ResponseStatus(HttpStatus.NO_CONTENT)
1212
@GetMapping(path = "/foo")
1313
void getFoo();
1414

0 commit comments

Comments
 (0)