Clean BadRequest response
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
package fr.dcproject.application.http
|
||||
|
||||
import fr.dcproject.application.http.HttpErrorBadRequest.InvalidParam
|
||||
import io.konform.validation.ValidationResult
|
||||
import io.ktor.http.HttpStatusCode
|
||||
|
||||
class BadRequestException(val httpError: HttpErrorBadRequest) : Exception()
|
||||
|
||||
class HttpErrorBadRequest(
|
||||
statusCode: HttpStatusCode,
|
||||
val title: String = statusCode.description,
|
||||
val invalidParams: List<InvalidParam>,
|
||||
) {
|
||||
val statusCode: Int = statusCode.value
|
||||
data class InvalidParam(
|
||||
val name: String,
|
||||
val reason: String
|
||||
)
|
||||
}
|
||||
|
||||
fun ValidationResult<*>.toOutput() = HttpErrorBadRequest(
|
||||
HttpStatusCode.BadRequest,
|
||||
invalidParams = this.errors.map {
|
||||
InvalidParam(
|
||||
it.dataPath,
|
||||
it.message
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
fun ValidationResult<*>.badRequestIfNotValid() {
|
||||
if (errors.size > 0) {
|
||||
throw BadRequestException(toOutput())
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,11 @@ import com.github.jasync.sql.db.postgresql.exceptions.GenericDatabaseException
|
||||
import fr.dcproject.common.security.AccessDeniedException
|
||||
import fr.dcproject.component.auth.ForbiddenException
|
||||
import fr.dcproject.component.auth.user
|
||||
import io.konform.validation.ValidationResult
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.features.NotFoundException
|
||||
import io.ktor.features.StatusPages
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.util.pipeline.PipelineContext
|
||||
import java.util.concurrent.CompletionException
|
||||
|
||||
class HttpError(
|
||||
@@ -20,8 +17,6 @@ class HttpError(
|
||||
val type: String? = null,
|
||||
val title: String = cause?.message ?: statusCode.description,
|
||||
val detail: String? = null,
|
||||
val invalidParams: List<InvalidParam>? = null,
|
||||
val stackTrace: String? = cause?.stackTraceToString()
|
||||
) {
|
||||
val statusCode: Int = statusCode.value
|
||||
data class InvalidParam(
|
||||
@@ -30,30 +25,6 @@ class HttpError(
|
||||
)
|
||||
}
|
||||
|
||||
fun ValidationResult<*>.toOutput(): HttpError {
|
||||
return HttpError(
|
||||
HttpStatusCode.BadRequest,
|
||||
invalidParams = this.errors.map {
|
||||
HttpError.InvalidParam(
|
||||
it.dataPath,
|
||||
it.message
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun PipelineContext<*, ApplicationCall>.respondIfNotValid(validationResult: ValidationResult<*>): HttpError? {
|
||||
if (validationResult.errors.size > 0) {
|
||||
val out = validationResult.toOutput()
|
||||
this.call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
out
|
||||
)
|
||||
return out
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun statusPagesInstallation(): StatusPages.Configuration.() -> Unit = {
|
||||
exception<CompletionException> { e ->
|
||||
val parent = e.cause?.cause
|
||||
@@ -106,4 +77,7 @@ fun statusPagesInstallation(): StatusPages.Configuration.() -> Unit = {
|
||||
call.respond(HttpStatusCode.Forbidden, it)
|
||||
}
|
||||
}
|
||||
exception<BadRequestException> { e ->
|
||||
call.respond(HttpStatusCode.BadRequest, e.httpError)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package fr.dcproject.component.article.routes
|
||||
|
||||
import fr.dcproject.application.http.respondIfNotValid
|
||||
import fr.dcproject.application.http.badRequestIfNotValid
|
||||
import fr.dcproject.common.response.toOutput
|
||||
import fr.dcproject.common.security.assert
|
||||
import fr.dcproject.common.validation.isUuid
|
||||
@@ -74,7 +74,7 @@ object FindArticles {
|
||||
|
||||
fun Route.findArticles(repo: ArticleRepository, ac: ArticleAccessControl) {
|
||||
get<ArticlesRequest> {
|
||||
respondIfNotValid(it.validate())?.apply { return@get }
|
||||
it.validate().badRequestIfNotValid()
|
||||
|
||||
repo.findArticles(it)
|
||||
.apply { ac.assert { canView(result, citizenOrNull) } }
|
||||
|
||||
@@ -134,6 +134,12 @@ paths:
|
||||
tags:
|
||||
- article
|
||||
operationId: getArticle
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/page'
|
||||
- $ref: '#/components/parameters/limit'
|
||||
- $ref: '#/components/parameters/sort'
|
||||
- $ref: '#/components/parameters/direction'
|
||||
- $ref: '#/components/parameters/search'
|
||||
responses:
|
||||
200:
|
||||
description: The Article objects
|
||||
@@ -149,6 +155,12 @@ paths:
|
||||
tags:
|
||||
- article
|
||||
operationId: getArticleVersions
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/page'
|
||||
- $ref: '#/components/parameters/limit'
|
||||
- $ref: '#/components/parameters/sort'
|
||||
- $ref: '#/components/parameters/direction'
|
||||
- $ref: '#/components/parameters/search'
|
||||
responses:
|
||||
200:
|
||||
description: The versions of Article
|
||||
@@ -2224,20 +2236,8 @@ components:
|
||||
properties:
|
||||
statusCode:
|
||||
type: integer
|
||||
type:
|
||||
type: string
|
||||
nullable: true
|
||||
title:
|
||||
type: string
|
||||
detail:
|
||||
type: string
|
||||
nullable: true
|
||||
cause:
|
||||
type: string
|
||||
nullable: true
|
||||
stackTrace:
|
||||
type: string
|
||||
nullable: true
|
||||
invalidParams:
|
||||
type: array
|
||||
items:
|
||||
|
||||
Reference in New Issue
Block a user