ktor
ktor copied to clipboard
Specify source of parameter for Ktor Location
Subsystem Ktor Locations Feature Is your feature request related to a problem? Please describe. Ktor's Location feature is a pretty big game changer and makes it easy to create and receive requests. However, for POST requests, the source of the parameter is still sourced from the query string, instead of body or form fields. e.g.
@Location("/users/login")
data class UserInfo(val username: String, val password: String)
.
.
.
post<UserInfo> {
// Needs `username` and `password` to be set in the query params!
}
Describe the solution you'd like It would be nice if we could specify the source of the parameters in the declaration of the parameters itself, using annotations:
@Location("/users/login")
data class UserInfo(@Form val username: String, @Form val password: String)
.
.
.
post<UserInfo> {
// yay it.username and it.password can be set via multipart form
}
or
@Location("/users/login")
data class UserInfo(@Body val username: String, @Body val password: String)
.
.
.
post<UserInfo> {
// yay it.username and it.password can be set via body
}
Creating the request to be used by the ktor clients for post requests can also be specified this way.
This is how it worked in the past. However, we removed it. The reason is that such locations are one-sided only
Sorry, could you provide me with an example of such an one-sided location? In any case, I think it's useful for it to be declarable like so, even if it's one-sided, since it simplifies the code you have to write on the server-side.
Sorry for slightly unclear definition. By one-sided I wanted to say "one direction serialization" so I an only deserialize but there is no way to construct a link url. So some locations could be urlified while some of them can't be and it's quite easy to make mistake. This is why we have removed it.
Perhaps we need a way to receive (deserialize) an object from parameters.
To be fair, the only place to use a non-GET link is in the form
element. The other places where href(<Location>)
is used are elements that require the link to be GET anyway (e.g. a
)
For the form
element, it can simply ignore the parameters that have @Form
/@Body
and generate the link for the sake of the form
element, and the form will set the params.
@Location("/users/login")
data class UserInfo(@Form val username: String="", @Form val password: String="")
// new href ignores `username` and `password` params since they are marked with @Form
form(href(UserInfo()), encType = FormEncType.multipartFormData, method = FormMethod.post) {
acceptCharset = "utf-8"
p {
label { +"username: " }
textInput { name = "username" }
}
p {
label { +"password: " }
textInput { name = "password" }
}
p {
submitInput { value = "send" }
}
}
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.