-
Notifications
You must be signed in to change notification settings - Fork 454
Alternative Ktor Raise DSL #3581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
At the moment, this PR is only addressing one "con" of the existing API, which is the reliance on Raising
|
…row-ktor-api # Conflicts: # arrow-libs/integrations/arrow-raise-ktor-server/build.gradle.kts
I've now replaced the existing You could now achieve the above example with something like: routing {
getOrRaise("/users/{userId?}") {
val userId = call.pathParameters["userId"] ?: raiseBadRequest("userId not specified")
withError(::handleError) {
userService.lookupUser(userId) ?: raise(HttpStatusCode.NotFound)
}
}
} |
I'm wary `Response` is potentially too non-specific, however `RoutingResponse` clashes with `io.ktor.server.routing.RoutingResponse`
using the right one relies on ensuring the right import is in, or qualifying the parameter
includes a delegate based access for query/path parameters allowing for: `val id: Int by pathRaising` `val userId: Int by queryRaising("user-id")"` `val nameUpper: String by pathRaising { it.uppercase() }` `validate { ... }` block using RaiseAccumulate has `by pathAccumulating` and `by queryAccumulating` forms and a `receiveAccumulating<T>()` helper. This makes for a nice and succinct: ```kotlin putOrRaise("/user/{name}") { val person = validate { val name: String by pathAccumulating val age: Int by queryAccumulating val info: Info by receiveAccumulating() Person(name, age, info) } Created(person) } ``` There's also a Ktor Route-scoped plugin to provide the default error responses: ```kotlin install(RaiseErrorResponse) { errorResponse = { validationError(it.nel()) } errorsResponse = { validationError(it) } } ```
I've included a delegate based access for query/path parameters allowing for: val id: Int by pathRaising
val userId: Int by queryRaising("user-id")"
val nameUpper: String by pathRaising { it.uppercase() }
This makes for a nice and succinct: putOrRaise("/user/{name}") {
val person = validate {
val name: String by pathAccumulating
val age: Int by queryAccumulating
val info: Info by receiveAccumulating()
Person(name, age, info)
}
Created(person)
} There's also a Ktor Route-scoped plugin to provide the default error responses: install(RaiseErrorResponse) {
errorResponse = { validationError(it.nel()) }
errorsResponse = { validationError(it) }
} |
only need one error response type - a single request error can be wrapped in nel
...or-server/src/commonMain/kotlin/arrow/raise/ktor/server/request/ParameterDelegateProvider.kt
Outdated
Show resolved
Hide resolved
import kotlin.properties.ReadOnlyProperty | ||
import kotlin.reflect.KProperty | ||
|
||
public abstract class RaisingParameterProvider internal constructor( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 at the moment this only raises when a delegated property is used.
Do we want to raise as soon as a delegate is acquired?
This could be achieved by the same process as the accumulating delegate provider but returning an already-resolved delegate.
…row-ktor-api # Conflicts: # arrow-libs/integrations/arrow-raise-ktor-server/api/arrow-raise-ktor-server.klib.api
Not complete by any stretch but hopefully enough to start any discussion.