Ktor Netty Server sending an empty response - kotlin

I'm using ktor 0.9.5. I'm trying a simple example. But when a try to connect to the server i get ERR_EMPTY_RESPONSE. This is my code.
fun main(args: Array<String>) {
embeddedServer(Netty, port = 8080, host = "localhost") {
install(DefaultHeaders)
install(CallLogging)
routing {
get(path = "/") {
call.respondText("Hello World!!")
}
}
}.start()
}
Doing some research I found that changing the project to Maven fix the problem, but because of rules of my organization I can't do it. Any other solution... Thanks before hand.
I have added a println("sometext") before call.respondText("Hello World!!") and it's never executed.

With ERR_EMPTY_RESPONSE error, I guess you are requesting the server from a Google Chrome browser. Right ?
Are you trying to connect to the server from another computer? If so it won't work because you have set the server to only respond for requests coming from localhost.
embeddedServer(Netty, port = 8080, host = "localhost")
Even if you add a println() it won't execute.
Try to remove host = "localhost" from embeddedServer() parameters an re-test.

Related

change host name to 0.0.0.0 in ktor

I want to change host in ktor in a EngineMain project. by default ktor uses 127.0.0.1 host in HOCON file but I want to change it to 0.0.0.0. the problem is when I add host attribute in deployment tag in HOCON file and change it to 0.0.0.0, it's still using the default host (127.0.0.1). I tried other hosts and ktor use them correctly but when I change it to 0.0.0.0 it uses the default host.
how can I fix it?
HOCON file (image)
UPDATE
I realized that my code has no problem I tested my code on another computer and it hosted on 0.0.0.0 but I still have trouble with it I don't know what is hosting me on 127.0.0.1.
i found a solution will it work for you give it a try
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
install(ContentNegotiation) {
gson {
setPrettyPrinting()
}
}
routing {
get("/") {
call.respondText("Hello, World!", contentType = ContentType.Text.Plain)
}
}
}.start(wait = true)

heroku deploy issue says ktor env

i got the same problem every time i try to deploy to heruko
https://prnt.sc/IeH3wooTqqAj
a screenshot from the terminal
1- https://prnt.sc/fqpj3f2lQTz8
2- https://prnt.sc/-710l_bznc2B
this is my application.kt
fun main() {
embeddedServer(Netty, port = 8087, host = "0.0.0.0") {
module {
module()
}
}.start(wait = true)
}
Suppress("unused")
fun Application.module() {
configureKoin()
configureAuth()
configureRouting()
configureSerialization()
configureMonitoring()
configureSession()
}
Prockfile
web: build/install/com.example.googleauth/bin/com.example.googleauth
worker: python scheduler.py
every thing is uptodate and i also add the Config Vars on heroku setting
i also tryed the embedded way and also the engin way same issue

Unable to perform get request in ktor framework

I am new to ktor and trying to create api in it.As I have downloaded project from ktor.io and opened it inside IntelliJ idea community edition then run button is showing disabled and when I am running it on right clicking on application.kt file and clicking on run application option.Its showing:
ktor.application - Responding at http://0.0.0.0:8080
When I am going to this link on webpage it is showing:
The web page at http://0.0.0.0:8080/ might be temporarily down or it may have moved permanently to a new web address.
Even if I have get route defined below is my code:
Application.kt
fun main() {
embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
configureRouting()
}.start(wait = true)
}
Routing.kt
fun Application.configureRouting() {
// Starting point for a Ktor app:
routing {
get("/") {
call.respondText("Hello World!")
}
}
}
Someone let me know What is an issue and how can I resolve it.

How to send pings on Ktor websockets

I tried to search in api docs as well as examples, but there weren't any example demonstrating how to send pings and receive pings. The only example was of how to connect to websocket and to send a text here.
I also saw chat sample here of server side and i carefully followed that as well (i.e. set ping interval in server side configuration of WebSocket installation).
I start listening both side for pongs but none of the side was receiving any ping messages.
And there is no option to configure the client side for pings as you can see here.
I'm so much confused about how to send pings.
This is my server side:
embeddedServer(
CIO,
80
) {
install(io.ktor.websocket.WebSockets) {
pingPeriod = Duration.ofSeconds(20)
}
routing {
webSocket("/ws") {
for (frame in incoming) {
when (frame) {
is Frame.Pong -> {
println("ping's response recieved")
}
is Frame.Ping -> {
// just temporary block
println("ping recieved")
}
is Frame.Text -> {
println(frame.readText())
}
}
}
}
}
}.apply { start() }
This is my client side:
val client = HttpClient(CIO) {
install(WebSockets)
}
client.ws(
method = HttpMethod.Get,
host = "127.0.0.1",
port = 80,
path = "/ws"
) {
send(Frame.Text("Hello World!"))
for (frame in incoming) {
when (frame) {
is Frame.Pong -> {
println("ping's response received")
}
is Frame.Ping -> {
// just temporary block
println("ping recieved from server")
}
is Frame.Text -> {
println(frame.readText())
}
}
}
}
Result:
Hello World!
i.e websocket is connected, text are able to transferred, but unfortunately can't use ping/pong feature.
I also found some functions for this here pinger and ponger but now it says its part of api and gets automatically start with initiation of WebsocketSession and i also tried to put pinger in client side but that didn't send ping to server whatsoever.
Result of above code is simply Hello world gets printed in server console as sent from client side but no ping received messages.
I was having trouble getting OkHttp to use ping/pong so I filed this issue https://github.com/ktorio/ktor/issues/1803 and one of the developers replied "well the only thing I can recommend you is to try CIO out. Is does support manual Ping/Pong processing using RawWebSockets."
Haven't tried it myself but you should check out https://github.com/ktorio/ktor/blob/master/ktor-features/ktor-websockets/jvm/test/io/ktor/tests/websocket/RawWebSocketTest.kt

In Vertx I need to redirect all HTTP requests to the same URL but for HTTPS

I have written a Vertx-web handler in Koltin that redirects any request I receive that is HTTP to HTTPS, and I'm using context.request().isSSL to determine if the request is not SSL, and this worked fine until I put my code behind a load balancer. If the load balancer talks to my Vertx-web server on HTTPS then it thinks all user requests are HTTPS even if they are not. And if I change the load balancer to talk to Vertx-web on HTTP then every request is redirected endlessly even if already the user is using HTTPS.
Then I also see another problem, that the redirect using context.request().absoluteURI() goes to the private address instead of the publically available address that the user is actually talking to.
Is there a handler in Vertx-web that I'm missing that does this, or some idiomatic way to solve this? Should I just do this from JavaScript since it sees the real user address instead of trying a server-side redirect?
I'm coding in Kotlin, so any examples for that language are great!
Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that solutions for interesting problems are shared in SO.
First, it is best if your proxy or load balancer can do this check and redirect for you since it has knowledge of the public URL and is a simpler process at that first contact with the user. But, you can also do it server-side with a little more complexity.
The flag you are checking, context.request().isSSL is only valid for the incoming connection to Vertx-web and does not consider the end-user's connect to your proxy or load balancer. You need to use the X-Forwarded-Proto header (and sometimes X-Forwarded-Scheme) and check the actual protocol of the user. And only if that header is not present you can use context.request().isSSL
You also need to externalize your own URL to be able to redirect on the server side to something that the browser can use to find you, your public URL.
First, there is a Kotlin function in this Stack Overflow answer for RoutingContext.externalizeUrl(), you will need it here:
I have a Vertx request and I need to calculate an externally visible (public) URL
Then knowing your public URL you can use the following handler which has default values for the intended public HTTPS port (default 443 will vanish from URL), which form of redirect (i.e. 302), and on any exceptions if the route should be failed or continued:
fun Route.redirectToHttpsHandler(publicHttpsPort: Int = 443, redirectCode: Int = 302, failOnUrlBuilding: Boolean = true) {
handler { context ->
val proto = context.request().getHeader("X-Forwarded-Proto")
?: context.request().getHeader("X-Forwarded-Scheme")
if (proto == "https") {
context.next()
} else if (proto.isNullOrBlank() && context.request().isSSL) {
context.next()
} else {
try {
val myPublicUri = URI(context.externalizeUrl())
val myHttpsPublicUri = URI("https",
myPublicUri.userInfo,
myPublicUri.host,
publicHttpsPort,
myPublicUri.rawPath,
myPublicUri.rawQuery,
myPublicUri.rawFragment)
context.response().putHeader("location", myHttpsPublicUri.toString()).setStatusCode(redirectCode).end()
} catch (ex: Throwable) {
if (failOnUrlBuilding) context.fail(ex)
else context.next()
}
}
}
}
A simpler version might be to just trust the context.externalizeUrl class and see if it has the correct protocol and port and redirect if not:
fun Route.simplifiedRedirectToHttpsHandler(publicHttpsPort: Int = 443, redirectCode: Int = 302, failOnUrlBuilding: Boolean = true) {
handler { context ->
try {
val myPublicUri = URI(context.externalizeUrl())
if (myPublicUri.scheme == "http") {
val myHttpsPublicUri = URI("https",
myPublicUri.userInfo,
myPublicUri.host,
publicHttpsPort,
myPublicUri.rawPath,
myPublicUri.rawQuery,
myPublicUri.rawFragment)
context.response().putHeader("location", myHttpsPublicUri.toString()).setStatusCode(redirectCode).end()
}
else {
context.next()
}
} catch (ex: Throwable) {
if (failOnUrlBuilding) context.fail(ex)
else context.next()
}
}
}