ktor icon indicating copy to clipboard operation
ktor copied to clipboard

Specify source of parameter for Ktor Location

Open Enigmatrix opened this issue 5 years ago • 5 comments

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.

Enigmatrix avatar Dec 25 '19 14:12 Enigmatrix

This is how it worked in the past. However, we removed it. The reason is that such locations are one-sided only

cy6erGn0m avatar Dec 25 '19 15:12 cy6erGn0m

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.

Enigmatrix avatar Dec 25 '19 16:12 Enigmatrix

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.

cy6erGn0m avatar Dec 25 '19 20:12 cy6erGn0m

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" }
 }
}

Enigmatrix avatar Dec 29 '19 02:12 Enigmatrix

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

oleg-larshin avatar Aug 10 '20 15:08 oleg-larshin