S.
03/29/2022, 6:48 PMSebastien Leclerc Lavallee
03/29/2022, 10:08 PMfun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
fun Application.module() {
registerRoutes()
}
fun Application.registerRoutes() {
routing {
route("/") {
get {
call.respondText("Hello world!")
}
}
}
}
What would be the best way? Where should I put it?
Thanks!Hexa
03/29/2022, 10:41 PMJames Black
03/30/2022, 1:22 AMtim
03/31/2022, 9:11 AMfunctionaldude
03/31/2022, 3:17 PMJsonFeature
. I have the following class structure:
@Serializable
sealed class Base {
@Serializable
class Child: Base()
}
When I do a post request with Child()
as body, the class discriminator is missing (the body is just {}
). I figured out that `Child`’s serializer is used, if I use `Base`’s serializer then the class discriminator is there:
val payload = Base.Child()
val payloadString1 = kotlinxSerializer.encodeToString(Base.serializer(), payload) // payloadString1 = "{"@class": "com.example.Base.Child"}"
val payloadString2 = kotlinxSerializer.encodeToString(Base.Child.serializer(), payload) // payloadString2 = "{}"
The problem is, I can’t find a way to force the Ktor client to use the sealed class’s serializer. Is this a bug or the intended behaviour? And if this is the intended behaviour then how can I tell the Ktor client to use a different serializer?Pavel Petkevich
04/01/2022, 7:28 AMMichal Klimczak
04/02/2022, 8:05 PMrouting {
val service by KoinJavaComponent.inject<PageService>(PageService::class.java)
...
Exception:
class com.xyz.PageService cannot be cast to class com.xyz.PageService (com.xyz.PageService is in unnamed module of loader 'app'; com.xyz.PageService is in unnamed module of loader io.ktor.server.engine.OverridingClassLoader$ChildURLClassLoader @55a88417)
Also it's injected fine at app startup, but fails with this exception when it's done in the routing
lambda. Works fine when I disable development mode, too. Any ideas?ste
04/03/2022, 7:32 PMbr
(Brotli) support in ktor-client-encoding
? The only thing I could find is https://github.com/ktorio/ktor/issues/408, but this is closed and the YouTrack link is brokenFilip Lastic
04/04/2022, 7:43 AMwithTestApplication {}
in our integration tests, but this causes that server has to start with each test. We started to have some performance issues, where test is executed in milliseconds, but server is starting for long time..
Do you have some experiences with starting server programatically, for example from gradle
before running all tests? I found this solution https://stackoverflow.com/a/61246720 But not sure if it is correct approach.Robert Jaros
04/04/2022, 12:49 PMS.
04/04/2022, 6:19 PMNotFound
or BadRequest
since they throw io.ktor.client.plugins.ClientRequestException
?
so this below doesn't work, only way is to do the checks on the exception's message it seems
val response = client.get("api/v1/words/x")
response shouldHaveStatus HttpStatusCode.BadRequest
response.bodyAsText() shouldBe INVALID_ID
dave08
04/05/2022, 6:34 AMharry248
04/05/2022, 6:39 AMonly-if-cached
cache control header? Ktor always responds with status code 504 even if there is a non-stale result in cache.dodalovic
04/05/2022, 7:50 PMsetBody(
Json.encodeToString(
CreateUpdateCustomer(
name = "name",
street = "street",
houseNumber = "houseNumber",
zip = "zip",
place = "place",
countryCode = "DE",
email = "<mailto:some@email.com|some@email.com>",
invoiceLanguage = "EN",
)
)
)
to be able to do json
Shouldn't it be just
setBody(
CreateUpdateCustomer(
name = "name",
street = "street",
houseNumber = "houseNumber",
zip = "zip",
place = "place",
countryCode = "DE",
email = "<mailto:some@email.com|some@email.com>",
invoiceLanguage = "EN",
)
)
Tobias Gronbach
04/05/2022, 10:35 PMMartin Gaens
04/05/2022, 11:24 PMrouting {
get("/") {
call.respond(
FreeMarkerContent(
"index.ftl",
mapOf(
"apartments" to transaction { Apartment.all().toList() }
)
)
)
}
}
The transaction produces a List
of `Apartment`s. Now, the problem is, that the Apartment
object holds a property called Address
but this property is from a different table. So, in order to access the `Address`' name, we have to call address.name
. This is the FreeMarker code:
<ol>
<#list apartments as apartment>
<li>${apartment.address.name} ${apartment.apartmentNumber} ${apartment.room}</li>
</#list>
</ol>
And this is the error it produces:
freemarker.core._TemplateModelException: An error has occurred when reading existing sub-variable "address"; see cause exception! The type of the containing value was: extended_hash+string (com.gitlab.djsushi.data.table.Apartment wrapped into f.e.b.StringModel)
ribesg
04/06/2022, 11:46 AMJorge Bo
04/06/2022, 4:16 PMjson {
serializersModule = SerializersModule {
contextual(Map::class) { MarketMapSerializer }
}
}
object MarketMapSerializer :
JsonTransformingSerializer<Map<String, Market>>(MapSerializer(String.serializer(), Market.serializer())) {
override fun transformDeserialize(element: JsonElement): JsonElement {
return JsonObject(element.jsonObject.filterNot { (k, _) ->
k == "token"
})
}
}
Todd
04/06/2022, 9:34 PMsendoav
04/07/2022, 8:52 PMJames Black
04/08/2022, 5:15 AMimport io.ktor.server.application.*
import com.blackfox.myoutfitpicker.plugins.configureRouting
import com.blackfox.myoutfitpicker.plugins.configureSerialization
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
fun Application.module() {
configureRouting()
configureSerialization()
}
I have no idea what I am doing wrong.Timur Atakishiev
04/08/2022, 6:39 AMtry{
smth
} catch(Throwable t) {
smth
}
that handles everything or it should be done separately for each case like in the spring security? Thankshhariri
04/08/2022, 8:27 AMDirk
04/08/2022, 12:47 PMval clientTopic = HttpClient {
install(Logging)
install(ContentNegotiation) {
json()
}
install(HttpCookies) {
storage = AcceptAllCookiesStorage() // default
}
defaultRequest {
...
}
}
....
val response = clientTopic.get(href(ResourcesFormat(), ApiTopicMS.Topic.V1.Laden(onlineLinkID = onlineLinkID)))
when (response.status) {
HttpStatusCode.OK -> {
<http://console.info|console.info>("Cookies from server: ${response.setCookie()}")
val setCookieHeader = response.headers["Set-Cookie"]
<http://console.info|console.info>("Cookie from header: $setCookieHeader")
<http://console.info|console.info>(response.headers.names())
response.headers.forEach { s, strings ->
<http://console.info|console.info>("s: $strings")
}
response.body<TopicDTO>()
}
else -> {
console.error("Topic konnte nicht geladen werden. Status: ${response.status}")
null
}
}
brabo-hi
04/08/2022, 2:13 PMCould not find io.ktor:ktor-serialization-kotlinx-json:2.0.0-RC.1
John O'Reilly
04/08/2022, 4:00 PM2.0.0-rc-1
- full stack trace in https://github.com/joreilly/PeopleInSpace/runs/5887877881?check_suite_focus=true
IllegalArgumentException: Sequence has more than one element
Nathan Kleinschmidt
04/09/2022, 7:50 PM@Serializable
sealed class Response(
@Contextual
val statusCode: HttpStatusCode = HttpStatusCode.OK
) {
@Serializable
data class SuccessResponse<T>(
val data : T? = null,
val message : String? = null
) : Response()
@Serializable
data class ErrorResponse<T>(
val exception : T? = null,
val message : String? = null
) : Response()
}
However it fails to serialize and I get runtime errors.
If I attempt to convert the response to Json using call.respond(statusCode, Json.encodeToString(result))
then I get:
kotlinx.serialization.SerializationException: Class 'String' is not registered for polymorphic serialization in the scope of 'Any'.
Mark the base class as 'sealed' or register the serializer explicitly.
If I don’t and just attempt to call call.respond(statusCode, result)
, then I get this error instead:
kotlinx.serialization.SerializationException: Serializer for class 'ErrorResponse' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
Not sure if this is an issue with how I am using serialization, or if this is even the recommended way of dealing with responses?Martin Gaens
04/09/2022, 8:28 PM2022-04-09 23:21:46.270 [eventLoopGroupProxy-4-1] TRACE o.t.s.expression.AdditionExpression - [THYMELEAF][eventLoopGroupProxy-4-1] Evaluating addition expression: "'table-select-' + ${iter.index}"
2022-04-09 23:21:46.270 [eventLoopGroupProxy-4-1] TRACE o.t.s.e.TextLiteralExpression - [THYMELEAF][eventLoopGroupProxy-4-1] Evaluating text literal: "'table-select-'"
2022-04-09 23:21:46.270 [eventLoopGroupProxy-4-1] TRACE o.t.s.expression.VariableExpression - [THYMELEAF][eventLoopGroupProxy-4-1] Evaluating variable expression: "${iter.index}"
2022-04-09 23:21:46.270 [eventLoopGroupProxy-4-1] TRACE o.t.s.e.OGNLVariableExpressionEvaluator - [THYMELEAF][eventLoopGroupProxy-4-1] OGNL expression: evaluating expression "iter.index" on target
2022-04-09 23:21:46.270 [eventLoopGroupProxy-4-1] TRACE o.t.T.cache.EXPRESSION_CACHE - [THYMELEAF][eventLoopGroupProxy-4-1][EXPRESSION_CACHE][CACHE_HIT] Cache hit in cache "EXPRESSION_CACHE" for key "ognlsc|org.thymeleaf.engine.IterationStatusVar|index".
James Black
04/10/2022, 6:41 AMcurl -H "Accept: application/json" -v 0.0.0.0:8080/hello
* Trying 0.0.0.0:8080...
* Connected to 0.0.0.0 (127.0.0.1) port 8080 (#0)
> GET /hello HTTP/1.1
> Host: 0.0.0.0:8080
> User-Agent: curl/7.79.1
> Accept: application/json
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Length: 0
<
* Connection #0 to host 0.0.0.0 left intact
when I start the server and the first line here is the last line, until I make the curl call then it outputs the rest of the lines:
01:34:22.888 [DefaultDispatcher-worker-1] INFO Application - Responding at <http://0.0.0.0:8080>
01:34:30.926 [eventLoopGroupProxy-3-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
01:34:30.929 [eventLoopGroupProxy-3-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
01:34:30.930 [eventLoopGroupProxy-3-1] DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@2383b23
01:34:31.007 [eventLoopGroupProxy-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
01:34:31.007 [eventLoopGroupProxy-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
01:34:31.007 [eventLoopGroupProxy-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.chunkSize: 32
This is my Application set up and with or without serialization same error:
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
fun Application.module() {
configureRouting()
configureStatusPages()
configureCallLogging()
// configureSerialization()
}
Status pages I was hoping would get called but it doesn't, so the 404 I am not certain where it is coming from.
fun Application.configureStatusPages() {
install(StatusPages) {
exception<Throwable> { call, cause ->
if(cause is RuntimeException) {
call.respondText(text = "403: $cause" , status = HttpStatusCode.Forbidden)
} else {
call.respondText(text = "500: $cause" , status = HttpStatusCode.InternalServerError)
}
}
status(HttpStatusCode.NotFound) { call, status ->
call.respondText(text = "404: Page Not Found", status = status)
}
}
}
I was hoping to see the logging requests but this doesn't seem to help:
fun Application.configureCallLogging() {
install(CallLogging) {
level = <http://Level.INFO|Level.INFO>
format { call ->
val status = call.response.status()
val httpMethod = call.request.httpMethod.value
val userAgent = call.request.headers["User-Agent"]
"Status: $status, HTTP method: $httpMethod, User agent: $userAgent"
}
}
}
And at the moment the routing is very simple:
fun Application.configureRouting() {
install(Routing) {
routing {
get("/") {
val uri = call.request.uri
call.respondText("Request uri: $uri")
}
get("/hello") {
call.respondText("Hello")
}
get("/weather") {
call.respondText("current weather")
}
}
}
}
James Black
04/10/2022, 6:41 AMcurl -H "Accept: application/json" -v 0.0.0.0:8080/hello
* Trying 0.0.0.0:8080...
* Connected to 0.0.0.0 (127.0.0.1) port 8080 (#0)
> GET /hello HTTP/1.1
> Host: 0.0.0.0:8080
> User-Agent: curl/7.79.1
> Accept: application/json
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Length: 0
<
* Connection #0 to host 0.0.0.0 left intact
when I start the server and the first line here is the last line, until I make the curl call then it outputs the rest of the lines:
01:34:22.888 [DefaultDispatcher-worker-1] INFO Application - Responding at <http://0.0.0.0:8080>
01:34:30.926 [eventLoopGroupProxy-3-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
01:34:30.929 [eventLoopGroupProxy-3-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkBounds: true
01:34:30.930 [eventLoopGroupProxy-3-1] DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@2383b23
01:34:31.007 [eventLoopGroupProxy-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
01:34:31.007 [eventLoopGroupProxy-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
01:34:31.007 [eventLoopGroupProxy-3-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.chunkSize: 32
This is my Application set up and with or without serialization same error:
fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)
fun Application.module() {
configureRouting()
configureStatusPages()
configureCallLogging()
// configureSerialization()
}
Status pages I was hoping would get called but it doesn't, so the 404 I am not certain where it is coming from.
fun Application.configureStatusPages() {
install(StatusPages) {
exception<Throwable> { call, cause ->
if(cause is RuntimeException) {
call.respondText(text = "403: $cause" , status = HttpStatusCode.Forbidden)
} else {
call.respondText(text = "500: $cause" , status = HttpStatusCode.InternalServerError)
}
}
status(HttpStatusCode.NotFound) { call, status ->
call.respondText(text = "404: Page Not Found", status = status)
}
}
}
I was hoping to see the logging requests but this doesn't seem to help:
fun Application.configureCallLogging() {
install(CallLogging) {
level = <http://Level.INFO|Level.INFO>
format { call ->
val status = call.response.status()
val httpMethod = call.request.httpMethod.value
val userAgent = call.request.headers["User-Agent"]
"Status: $status, HTTP method: $httpMethod, User agent: $userAgent"
}
}
}
And at the moment the routing is very simple:
fun Application.configureRouting() {
install(Routing) {
routing {
get("/") {
val uri = call.request.uri
call.respondText("Request uri: $uri")
}
get("/hello") {
call.respondText("Hello")
}
get("/weather") {
call.respondText("current weather")
}
}
}
}
Aleksei Tirman [JB]
04/10/2022, 10:35 AMJames Black
04/10/2022, 8:22 PMktor {
deployment {
port = 8060
}
application {
modules = [ com.blackfox.myoutfitpicker.ApplicationKt.module ]
}
}
and I had this in the log, but I get the same error.
15:18:30.997 [DefaultDispatcher-worker-1] INFO Application - Responding at <http://0.0.0.0:8060>
15:18:38.588 [eventLoopGroupProxy-3-1] DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.checkAccessible: true
This is the output:
curl -v 0.0.0.0:8060/
* Trying 0.0.0.0:8060...
* Connected to 0.0.0.0 (127.0.0.1) port 8060 (#0)
> GET / HTTP/1.1
> Host: 0.0.0.0:8060
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Length: 0
Aleksei Tirman [JB]
04/11/2022, 12:29 PMe: /Users/Aleksei.Tirman/projects/MyOutfitPicker/server/src/main/kotlin/com/blackfox/myoutfitpicker/plugins/Routing.kt: (4, 36): Unresolved reference: api
e: /Users/Aleksei.Tirman/projects/MyOutfitPicker/server/src/main/kotlin/com/blackfox/myoutfitpicker/plugins/Routing.kt: (36, 19): Unresolved reference: WeatherApi
e: /Users/Aleksei.Tirman/projects/MyOutfitPicker/server/src/main/kotlin/com/blackfox/myoutfitpicker/plugins/Routing.kt: (37, 9): Overload resolution ambiguity:
James Black
04/11/2022, 5:23 PM* Trying 0.0.0.0:8080...
* Connected to 0.0.0.0 (127.0.0.1) port 8080 (#0)
> GET /hello HTTP/1.1
> Host: 0.0.0.0:8080
> User-Agent: curl/7.79.1
> Accept: application/json
>
* Empty reply from server
This is now my router.
routing {
get("/") {
val uri = call.request.uri
call.respondText("Request uri: $uri")
}
get("/hello") {
call.respondText("Hello")
}
get("/weather") {
call.respondText("current weather")
//currentWeather()
}
}
install(Routing) {
get("/") {
val uri = call.request.uri
call.respondText("Request uri: $uri")
}