ribesg
05/10/2022, 11:42 AMAleksei Tirman [JB]
05/10/2022, 12:46 PM@Test
fun test() = testApplication {
application {
routing {
get("/redirect") {
call.respondRedirect("/")
}
get("/") {
call.respondText { "hello" }
}
}
}
assertEquals("hello", client.get("/redirect").bodyAsText())
}
ribesg
05/11/2022, 2:58 PMpost<V1.OldTimeSlots> {
call.respondRedirect(application.href(V1.EventTimeSlots()))
}
post<V1.EventTimeSlots> {
…
val response = EventTimeSlotsResponse(…)
call.respond(HttpStatusCode.OK, response)
}
@Test
fun `EventTimeSlots endpoint should return event timeslots`() = testApplication {
val client = createClient {
install(ContentNegotiation) { json() }
install(Resources)
}
val expectedResponse = EventTimeSlotsResponse(…)
val response = <http://client.post|client.post>(V1.EventTimeSlots()) {
contentType(ContentType.Application.Json)
setBody(…)
}.body<EventTimeSlotsResponse>()
assertEquals(expectedResponse, response)
}
@Test
fun `OldTimeslots endpoint should still work`() = testApplication {
val client = createClient {
install(ContentNegotiation) { json() }
install(Resources)
}
val expectedResponse = EventTimeSlotsResponse(…)
val response = <http://client.post|client.post>(V1.OldTimeSlots()) {
contentType(ContentType.Application.Json)
setBody(…)
}.body<EventTimeSlotsResponse>()
assertEquals(expectedResponse, response)
}
io.ktor.client.call.NoTransformationFoundException: No transformation found: class io.ktor.utils.io.ByteBufferChannel -> class blabla.route.EventTimeSlotsResponse
with response from <http://localhost/v1/timeslots>:
status: 302 Found
response headers:
Location: /v1/event-timeslots
, Date: Wed, 11 May 2022 15:01:33 GMT
, Server: Ktor/2.0.1
, Content-Length: 0
Aleksei Tirman [JB]
05/11/2022, 3:40 PMribesg
05/11/2022, 3:43 PM@Resource("/a")
@Serializable
class A {
@Resource("b")
@Serializable
data class B(val parent: A = A())
@Resource("c")
@Serializable
data class C(val parent: B = B())
}
@Serializable
data class RequestBody(val value: Int)
@Serializable
data class ResponseBody(val value: Int)
@Test
fun `Should follow redirects`() = testApplication {
val value = 1337
environment {
config = MapApplicationConfig()
module {
install(CallLogging)
install(DefaultHeaders)
install(AutoHeadResponse)
install(ServerContentNegotiation) { json() }
install(ServerResources)
routing {
post<A.B> {
call.respondRedirect(application.href(A.C()))
}
post<A.C> {
val requestBody = call.receive<RequestBody>()
call.respond(HttpStatusCode.OK, ResponseBody(requestBody.value))
}
}
}
}
val client = createClient {
install(ClientContentNegotiation) { json() }
install(ClientResources)
}
val result = <http://client.post|client.post>(A.B()) {
contentType(ContentType.Application.Json)
setBody(RequestBody(value))
}.body<ResponseBody>()
assertEquals(value, result.value)
}
Aleksei Tirman [JB]
05/12/2022, 10:32 AMHttpRedirect
plugin redirects requests only with GET
and HEAD
methods by default. You can disable checking HTTP method to make it work:
val client = createClient {
followRedirects = false
install(HttpRedirect) {
checkHttpMethod = false
}
install(ClientContentNegotiation) { json() }
install(ClientResources)
}
ribesg
05/12/2022, 10:34 AMAleksei Tirman [JB]
05/12/2022, 10:35 AMif (plugin.checkHttpMethod && origin.request.method !in ALLOWED_FOR_REDIRECT) {
return@intercept origin
}
ALLOWED_FOR_REDIRECT
is setOf(HttpMethod.Get, HttpMethod.Head)
ribesg
05/12/2022, 10:36 AMfollowRedirects
to false because it installs the HttpRedirect
plugin with default config? It’s also weird to have to do that to modify the configAleksei Tirman [JB]
05/12/2022, 10:37 AMribesg
05/12/2022, 10:46 AMAleksei Tirman [JB]
05/12/2022, 10:47 AMribesg
05/12/2022, 10:50 AMcheckHttpMethod
should apply only to old 301 and 302 codes and not 307 and 308. I’m also gonna use 308 in my case.