mirror of https://github.com/usbharu/Hideout.git
feat: Null非許容のパラメーターにnullがきたときのエラーメッセージを改善
This commit is contained in:
parent
b33f62b656
commit
5c8d7e8d36
|
@ -141,10 +141,11 @@ class AccountApiTest {
|
|||
mockMvc
|
||||
.post("/api/v1/accounts") {
|
||||
contentType = MediaType.APPLICATION_FORM_URLENCODED
|
||||
param("username", "api-test-user-3")
|
||||
param("password", "api-test-user-3")
|
||||
with(csrf())
|
||||
}
|
||||
.andExpect { status { isBadRequest() } }
|
||||
.andDo { print() }
|
||||
.andExpect { status { isUnprocessableEntity() } }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -156,7 +157,7 @@ class AccountApiTest {
|
|||
param("username", "api-test-user-4")
|
||||
with(csrf())
|
||||
}
|
||||
.andExpect { status { isBadRequest() } }
|
||||
.andExpect { status { isUnprocessableEntity() } }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.slf4j.LoggerFactory
|
|||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.validation.BindException
|
||||
import org.springframework.validation.FieldError
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler
|
||||
|
||||
|
@ -52,23 +53,43 @@ class MastodonApiControllerAdvice {
|
|||
@ExceptionHandler(BindException::class)
|
||||
fun handleException(ex: BindException): ResponseEntity<UnprocessableEntityResponse> {
|
||||
logger.debug("Failed bind entity.", ex)
|
||||
val error = ex.bindingResult.fieldErrors
|
||||
val message = error.map {
|
||||
"${it.field} ${it.defaultMessage}"
|
||||
}.joinToString(prefix = "Validation failed: ")
|
||||
|
||||
val details = error.associate {
|
||||
it.field to UnprocessableEntityResponseDetails(
|
||||
when (it.code) {
|
||||
"Email" -> "ERR_INVALID"
|
||||
"Pattern" -> "ERR_INVALID"
|
||||
else -> "ERR_INVALID"
|
||||
},
|
||||
it.defaultMessage
|
||||
)
|
||||
val details = mutableMapOf<String, MutableList<UnprocessableEntityResponseDetails>>()
|
||||
|
||||
ex.allErrors.forEach {
|
||||
val defaultMessage = it.defaultMessage
|
||||
when {
|
||||
it is FieldError -> {
|
||||
val code = when (it.code) {
|
||||
"Email" -> "ERR_INVALID"
|
||||
"Pattern" -> "ERR_INVALID"
|
||||
else -> "ERR_INVALID"
|
||||
}
|
||||
details.getOrPut(it.field) {
|
||||
mutableListOf()
|
||||
}.add(UnprocessableEntityResponseDetails(code, defaultMessage.orEmpty()))
|
||||
}
|
||||
|
||||
defaultMessage?.startsWith("Parameter specified as non-null is null:") == true -> {
|
||||
val parameter = defaultMessage.substringAfterLast("parameter ")
|
||||
|
||||
details.getOrPut(parameter) {
|
||||
mutableListOf()
|
||||
}.add(UnprocessableEntityResponseDetails("ERR_BLANK", "can't be blank"))
|
||||
}
|
||||
|
||||
else -> {
|
||||
logger.warn("Unknown validation error", ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseEntity.unprocessableEntity().body(UnprocessableEntityResponse(message, details))
|
||||
val message = details.map {
|
||||
it.key + " " + it.value.joinToString { it.description }
|
||||
}.joinToString()
|
||||
|
||||
return ResponseEntity.unprocessableEntity()
|
||||
.body(UnprocessableEntityResponse(message, details))
|
||||
}
|
||||
|
||||
@ExceptionHandler(StatusNotFoundException::class)
|
||||
|
|
|
@ -1455,6 +1455,8 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
username:
|
||||
|
||||
nullable: false
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 300
|
||||
|
@ -2841,9 +2843,11 @@ components:
|
|||
error:
|
||||
type: string
|
||||
details:
|
||||
type: object
|
||||
type: array
|
||||
additionalProperties:
|
||||
$ref: "#/components/schemas/UnprocessableEntityResponseDetails"
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/UnprocessableEntityResponseDetails"
|
||||
|
||||
UnprocessableEntityResponseDetails:
|
||||
type: object
|
||||
|
@ -2852,6 +2856,10 @@ components:
|
|||
type: string
|
||||
description:
|
||||
type: string
|
||||
nullable: false
|
||||
required:
|
||||
- error
|
||||
- description
|
||||
|
||||
UnauthorizedResponse:
|
||||
type: object
|
||||
|
|
|
@ -35,4 +35,5 @@ isLong set
|
|||
Not Integer, not Long => we have a decimal value!
|
||||
}}{{^isInteger}}{{^isLong}}{{#minimum}}
|
||||
@get:DecimalMin("{{.}}"){{/minimum}}{{#maximum}}
|
||||
@get:DecimalMax("{{.}}"){{/maximum}}{{/isLong}}{{/isInteger}}
|
||||
@get:DecimalMax("{{.}}"){{/maximum}}{{/isLong}}{{/isInteger}}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{{#useBeanValidation}}{{>beanValidation}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swagger2AnnotationLibrary}}
|
||||
@Schema({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{.}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{/example}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}
|
||||
@ApiModelProperty({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{.}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{/example}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swagger1AnnotationLibrary}}
|
||||
@ApiModelProperty({{#example}}example = "{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{.}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{/example}}required = true, {{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swagger1AnnotationLibrary}}{{^isNullable}}@get:NotNull{{/isNullable}}
|
||||
@get:JsonProperty("{{{baseName}}}", required = true){{#isInherited}} override{{/isInherited}} {{>modelMutable}} {{{name}}}: {{#isEnum}}{{#isArray}}{{baseType}}<{{/isArray}}{{classname}}.{{{nameInCamelCase}}}{{#isArray}}>{{/isArray}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}
|
||||
|
|
Loading…
Reference in New Issue