Sandeep Chandra
04/25/2021, 12:20 AMHelio
04/25/2021, 3:13 AM1.4.10 -> 1.4.32
and Ktor 1.4.2 -> 1.5.3
. I was definitely expecting some of Unit tests to break due to compatibility and I’ve already fixed them. However, there are still 4 of them that I’m struggling to understand what could be wrong.
When one of the unit tests starts, it adds an entity to a Global Variable with type mutableListOf<MyModel>()
. I can confirm that the value was added successfully. ArrayList@XXXX
. However, when one of the routes of my Ktor server attempt to read the value from that Global Variable, it is empty and the id of the object is now ArrayList@YYYY
. It looks like when embeddedServer(…).start()
is executed, it creates a new instance of the Global Object, hence it is empty.
I’ve already tried many things, SynchronizeListOf, add the global variable into an object, but no matter what I do the reference of the GlobalObject into Ktor is always different.
Would anyone be able to shed some light, please?
Thanks heaps.Tim Malseed
04/25/2021, 4:31 AMSatyam Agarwal
04/26/2021, 8:14 AMvio
04/26/2021, 1:58 PMClosedWatchServiceException
, when running multiple tests all together. I'm using ktor: 1.5.2
, and having a jetty
server. The issue is thrown when the server is restarted in following tests.
here's a code snippet to exemplify the error:
class StartStopServerTest : FreeSpec({
"server" - {
val server = embeddedServer(
factory = Jetty,
port = 8080,
module = {}
)
"start" {
server.start()
}
"stop" {
server.stop(1000, 1000)
}
"restart" {
server.start() // this fails with the error as shown in the picture
}
"stop again" {
server.stop(1000, 1000)
}
}
})
Did anybody face this as well? Appreciate any suggestions and help, thank you 🙏Guilherme Delgado
04/26/2021, 4:38 PMinstall(Sessions) {
cookie<Session>(SESSION_COOKIE) {
cookie.extensions["SameSite"] = "lax"
transform(SessionTransportTransformerMessageAuthentication(hex(...)))
}
}
install(Authentication) {
session<Session>(SESSION_AUTH) {
challenge { throw AuthenticationException() }
validate { session -> if (session.accessToken.isEmpty()) null else session }
}
oauth(GOOGLE_OAUTH) {
client = httpClient
providerLookup = {
OAuthServerSettings.OAuth2ServerSettings(
name = "google",
authorizeUrl = "<https://accounts.google.com/o/oauth2/auth>",
accessTokenUrl = "<https://www.googleapis.com/oauth2/v3/token>",
requestMethod = <http://HttpMethod.Post|HttpMethod.Post>,
...
)
}
urlProvider = { p -> redirectUrl(Login(p.name), false) }
}
}
webApp/Auth.kt
@KtorExperimentalLocationsAPI
@Location("/login/{provider?}")
class Login(val provider: String = "google")
@KtorExperimentalLocationsAPI
fun Route.login(client: HttpClient) {
authenticate(GOOGLE_OAUTH) {
location<Login> {
param("error") { handle {...} }
handle {
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
if (principal != null) {
val oauth = call.authentication.principal<OAuthAccessTokenResponse.OAuth2>()!!
val response = client.get<UserInfo>("<https://www.googleapis.com/oauth2/v1/userinfo>") {
header(HttpHeaders.Authorization, "Bearer ${oauth.accessToken}")
}
call.sessions.set(Session(response, oauth.accessToken, oauth.refreshToken?: ""))
call.redirect(Home())
} else {
call.respond(status = HttpStatusCode.Unauthorized, "Unauthorized, no token issued")
}
}
}
}
}
webApp/Data.kt
@KtorExperimentalLocationsAPI
@Location("/data")
class Data
@KtorExperimentalLocationsAPI
fun Route.data(client: HttpClient) {
authenticate(SESSION_AUTH) {
get<Data> {
val response = client.get<Info>("<http://localhost:8080>${application.locationToUrl(DataApi())}") {
header(HttpHeaders.Authorization, "Bearer ${call.getSession()?.accessToken}")
...
}
...
}
post<Data> {...}
}
}
api/DataApi.kt
@KtorExperimentalLocationsAPI
@Location("$API_VERSION/data")
class DataApi
@KtorExperimentalLocationsAPI
fun Route.dataApi(client: HttpClient) {
// authenticate(SESSION_AUTH) {
get<DataApi> {
...
val response = client.get<SomeApiData>("<https://www.googleapis.com/>...") {
parameter("key", params.apiKey)
header(HttpHeaders.Authorization, call.request.headers[HttpHeaders.Authorization])
}
...
}
post<DataApi> {...}
// }
}
Guilherme Delgado
04/26/2021, 4:38 PMDominaezzz
04/27/2021, 5:57 PMinterface Animal
@Serializable
class Dog : Animal
@Serializable
class Cat : Animal
// subclasses are explicitly registered in serializerModule.
client.get<...>("...") {
contentType(Json)
body = Dog()
}
How do I get ktor to do polymorphic serialisation correctly?
body
ends up being {}
instead of { "type": "Dog" }
.Dominick
04/28/2021, 5:44 AM@Suppress("unused") // Referenced in application.conf
@kotlin.jvm.JvmOverloads
fun Application.module(testing: Boolean = false) {
// <https://ktor.io/servers/features/https-redirect.html#testing>
if (!testing) {
install(HttpsRedirect) {
// The port to redirect to. By default 443, the default HTTPS port.
sslPort = 1818
// 301 Moved Permanently, or 302 Found redirect.
permanentRedirect = true
}
}
install(ContentNegotiation) {
gson {}
}
routing {
userRoutes()
/*
fileRoutes()
miscRoutes()
deliveryRoutes()
*/
static("/") {
files("public")
default("public/index.html")
}
}
val dataSource = HikariDataSource().apply {
maximumPoolSize = 20
driverClassName = "com.mysql.cj.jdbc.Driver"
jdbcUrl = "[removed]"
addDataSourceProperty("user", "mediauser")
addDataSourceProperty("password", "[removed]")
isAutoCommit = false
}
Database.Companion.connect(dataSource)
transaction {
addLogger(StdOutSqlLogger)
SchemaUtils.create(MediaPropertiesTable, MediaContentTable, UserAPIKeysTable, UserTable)
}
Thread(ConsoleRunnable).run()
}
christophsturm
04/28/2021, 1:49 PMhhariri
04/28/2021, 2:03 PMrsktash
04/29/2021, 9:46 AMTim Malseed
04/29/2021, 11:11 AMException in thread “main” io.ktor.application.DuplicateApplicationFeatureException: Conflicting application feature is already installed with the same key asCall Logging
embeddedServer(
factory = Netty,
port = 8080,
host = "0.0.0.0",
watchPaths = listOf("classes"),
module = {
install(CallLogging)
install(CachingHeaders)
artworkRouting()
}
I can’t figure out why this has suddenly started occurring.. Any ideas?Guilherme Delgado
04/29/2021, 12:15 PMturansky
04/30/2021, 12:01 AM1.5.0
?
Ktor update required for:
1. Coroutines 1.5.0-RC
2. Serialization 1.2.0
3. Kotlin Wrappers update
Bulk update required, because JS module name of serialization library was changed 😞Tim Malseed
04/30/2021, 4:13 AMDuplicateApplicationFeatureException
, I believe it's due to a bug in Ktor (sort of tracked here: https://youtrack.jetbrains.com/issue/KTOR-2586)Tim Malseed
04/30/2021, 12:29 PMinstallDist
as per the documentation. Running on openjdk 11
JVM args are :
applicationDefaultJvmArgs = listOf(
"-Dio.ktor.development=true",
"-Dagentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:8081"
)
I’ve exposed the port 8081.Michael
04/30/2021, 5:06 PMandylamax
04/30/2021, 6:19 PMrouting {
get("/") {
// this works as expected
}
static("/") {
// I have this as well
}
//and
get("/config/{file}") {
// overridden by static("/")
}
}
Question is, how do I implement both static("/")
overriding my get("/config/{file}")
. With both of them existing, ,aking a get request to /config/user1
returns not fount. I am assuming it is looking to the files served as static resources. Help?Patrick Ramsey
05/01/2021, 12:11 AMval xmlBody: String = [prepare body]
<http://client.post|client.post>([uri]) {
contentType(ContentType.Text.Xml)
body = xmlBody
}
However, I’m getting,
io.ktor.http.UnsafeHeaderException: Header(s) [Content-Type] are controlled by the engine and cannot be set explicitly
What’s the correct way to specify the Content-Type header, if not by explicitly calling contentType()?Matvei Vdovitsyn
05/01/2021, 7:11 PMRyan Simon
05/01/2021, 7:36 PMCLOVIS
05/03/2021, 10:54 AMspierce7
05/03/2021, 4:19 PMMBegemot
05/03/2021, 5:11 PMDominick
05/04/2021, 2:52 PMval buffer = (part as PartData.FileItem).streamProvider().buffered()
Those 5gb will never load into memory correct? Is there a way I can get the size of the uploaded file without loading it all into memory as well?Guilherme Delgado
05/05/2021, 10:32 AMCREATE TABLE IF NOT EXISTS
so I assume the file is being deleted. How can I avoid that? Also, where’s the file located?
I don’t have this problem in KMM projects (for android/ios), the BD is never deleted (only if I clean cache of course).
Thanks!Nikky
05/05/2021, 8:04 PMCurl
engine on desktop
i am running into C:\Users\nikky\.konan\dependencies\msys2-mingw-w64-x86_64-clang-llvm-lld-compiler_rt-8.0.1\bin\ld: cannot find -lcurl
i am trying to figure out where i need to install curl.. or what magic env var i have to set
i am guessing i need to install pacman -S mingw-w64-x86_64-curl
in MSYS2, but apparently it is not picked up
maybe because my msys2 is not in the default location?
i also installed curl
via scoop, not sure what else i can doNorbert Sziráczki
05/06/2021, 1:38 PMcsieflyman
05/06/2021, 4:48 PMcsieflyman
05/06/2021, 4:48 PMturansky
05/06/2021, 4:54 PM1.5.0
😞
https://kotlinlang.slack.com/archives/C0A974TJ9/p1619881885019300?thread_ts=1619740875.494900&cid=C0A974TJ9csieflyman
05/06/2021, 5:16 PM