Kotlin Ktor can't get post data with location data class

4k views Asked by At

This is my code:

package com.example.ktordemo

import org.jetbrains.ktor.application.Application
import org.jetbrains.ktor.application.install
import org.jetbrains.ktor.application.log
import org.jetbrains.ktor.auth.UserHashedTableAuth
import org.jetbrains.ktor.features.CallLogging
import org.jetbrains.ktor.features.ConditionalHeaders
import org.jetbrains.ktor.features.DefaultHeaders
import org.jetbrains.ktor.features.PartialContentSupport
import org.jetbrains.ktor.locations.*
import org.jetbrains.ktor.response.*
import org.jetbrains.ktor.routing.*
import org.jetbrains.ktor.util.decodeBase64
import org.slf4j.Logger

@location("/login")
data class Login(val userId: String = "", val password: String = "", val error: String = "")

@location("/userTable") class SimpleUserTable

val hashedUserTable = UserHashedTableAuth(table = mapOf(
        "test" to decodeBase64("VltM4nfheqcJSyH887H+4NEOm2tDuKCl83p5axYXlF0=")
))


fun Application.basicAuth() {
    install(DefaultHeaders)
    install(CallLogging)
    install(ConditionalHeaders)
    install(PartialContentSupport)
    install(Locations)
    install(Routing) {
        manual(log)
    }
}

fun Route.manual(log: Logger) {
    post<Login> {
        log.info(it.toString())
        call.respond(it.userId) // get nothing
    }
    get { login: Login ->
        call.respond("login page")
    }
}

i use insomnia test the request, this is result:

> POST /login HTTP/1.1
> Host: localhost:8080
> User-Agent: insomnia/5.6.3
> Accept: */*
> Accept-Encoding: deflate, gzip
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 33
| userId=username&password=password


< HTTP/1.1 200 OK
< Date: Sun, 27 Aug 2017 16:52:20 GMT
< Server: ktor-core/0.4.0 ktor-core/0.4.0
< Content-Type: text/plain; charset=UTF-8
< Content-Length: 0

Anyone can help me?

2

There are 2 answers

0
Ilya Ryzhenkov On BEST ANSWER

That was an unfortunate consequence of treating all parameters (query and post) in the same way. This was fixed and post parameters should now be received explicitly. It makes sense, because location is a round trip entity, like you can handle it and you can generate an URL from it, which should hit the same handler. With POST parameters it is impossible.

For now you need to call.receive<ValuesMap>() and get post parameters manually from the map. Typed bindings are in the works.

You can track progress here: https://github.com/Kotlin/ktor/issues/190

0
Master Developer On

fun Route.manual(log: Logger) {

location<Login> { //must work
    method(HttpMethod.Post) {
        handle {
            log.info(it.toString())
            call.respond(it.userId)
        }
    }
}
get { login: Login ->
    call.respond("login page")
}