Skip to content

Commit 58ad09d

Browse files
Handle null bodies better (#38)
if request handler request type is nullable pass null otherwise fail with 400
1 parent 2c86a6e commit 58ad09d

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

router/src/main/kotlin/io/moia/router/RequestHandler.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ abstract class RequestHandler : RequestHandler<APIGatewayProxyRequestEvent, APIG
110110
val requestType = handler.reflect()!!.parameters.first().type.arguments.first().type
111111
return when {
112112
requestType?.classifier as KClass<*> == Unit::class -> Unit
113+
input.body == null && requestType.isMarkedNullable -> null
114+
input.body == null -> throw ApiException("no request body present", "REQUEST_BODY_MISSING", 400)
113115
else -> deserializationHandlerChain.deserialize(input, requestType)
114116
}
115117
}

router/src/test/kotlin/io/moia/router/RequestHandlerTest.kt

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,40 @@ class RequestHandlerTest {
290290
}
291291
}
292292

293+
@Test
294+
fun `should return 400 on missing body when content type stated`() {
295+
296+
val response = testRequestHandler.handleRequest(
297+
POST("/some")
298+
.withHeaders(
299+
mapOf(
300+
"Accept" to "application/json",
301+
"Content-Type" to "application/json"
302+
)
303+
)
304+
.withBody(null), mockk()
305+
)
306+
assert(response.statusCode).isEqualTo(400)
307+
assert(mapper.readValue<ApiError>(response.body).code).isEqualTo("REQUEST_BODY_MISSING")
308+
}
309+
310+
@Test
311+
fun `should handle null body when content type is stated and request handler body type is nullable`() {
312+
313+
val response = testRequestHandler.handleRequest(
314+
POST("/some-nullable")
315+
.withHeaders(
316+
mapOf(
317+
"Accept" to "application/json",
318+
"Content-Type" to "application/json"
319+
)
320+
)
321+
.withBody(null), mockk()
322+
)
323+
assert(response.statusCode).isEqualTo(200)
324+
assert(response.body).isEqualTo("""{"greeting":""}""")
325+
}
326+
293327
@Test
294328
fun `should handle api exception`() {
295329

@@ -542,7 +576,7 @@ class RequestHandlerTest {
542576
}
543577

544578
@Test
545-
fun `Handler should return the content type that is accepted`() {
579+
fun `should return the content type that is accepted`() {
546580
val jsonResponse = AcceptTypeDependingHandler().handleRequest(
547581
GET("/all-objects")
548582
.withHeader("accept", "application/json"),
@@ -664,7 +698,7 @@ class RequestHandlerTest {
664698
)
665699
}
666700

667-
POST("/some") { r: Request<TestRequest> ->
701+
POST("/some") { _: Request<TestRequest> ->
668702
ResponseEntity.ok(
669703
TestResponse(
670704
"v2"
@@ -680,6 +714,14 @@ class RequestHandlerTest {
680714
)
681715
}.producing("application/json", "application/*+json")
682716

717+
POST("/some-nullable") { r: Request<TestRequest?> ->
718+
ResponseEntity.ok(
719+
TestResponse(
720+
r.body?.greeting.orEmpty()
721+
)
722+
)
723+
}.producing("application/json")
724+
683725
POST("/somes") { r: Request<List<TestRequest>> ->
684726
ResponseEntity.ok(r.body.map {
685727
TestResponse(

0 commit comments

Comments
 (0)