Hi, is it possible to get the server response head...
# ktor
p
Hi, is it possible to get the server response header when using ktor websocket client?
I tried this:
Copy code
val ws = client.webSocketSession(url, block)
val respHeaders = ws?.call?.response?.headers?.toMap()
but it doesn't work, also logging content doesn't show any response header:
Copy code
REQUEST: <ws://localhost:3000/engine.io/?EIO=4&transport=websocket|ws://localhost:3000/engine.io/?EIO=4&transport=websocket>
METHOD: HttpMethod(value=GET)
COMMON HEADERS
-> Accept: */*
-> Accept-Charset: UTF-8
-> X-EngineIO: foo
CONTENT HEADERS
-> Connection: Upgrade
-> Sec-WebSocket-Key: YjdhZTdjZGY5YTU4NTgxYQ==
-> Sec-WebSocket-Version: 13
-> Upgrade: websocket
BODY Content-Type: null
BODY START

BODY END
RESPONSE: 101 Switching Protocols
METHOD: HttpMethod(value=GET)
FROM: <ws://localhost:3000/engine.io/?EIO=4&transport=websocket|ws://localhost:3000/engine.io/?EIO=4&transport=websocket>
COMMON HEADERS
BODY Content-Type: null
BODY START

BODY END
When I connect to the same server with OkHttp, logging content has reponse headers:
Copy code
--> GET <http://localhost:3000/engine.io/?EIO=4&transport=websocket|http://localhost:3000/engine.io/?EIO=4&transport=websocket>
X-EngineIO: foo
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: UV+coRrb16k2qEi6sZmHkg==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate
--> END GET
<-- 101 Switching Protocols <http://localhost:3000/engine.io/?EIO=4&transport=websocket|http://localhost:3000/engine.io/?EIO=4&transport=websocket> (40ms)
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: F1Sn+7cE5k/hytlQpaMjYHSgfAQ=
X-EngineIO: hi
X-EngineIO: foo
<-- END HTTP
a
You can obtain the headers by using the following code:
Copy code
client.webSocket("<wss://ws.postman-echo.com/raw>") {
    val response = call.response
    response.headers.forEach { key, values ->  println("$key: $values")}
}
p
@Aleksei Tirman [JB] thank you for the reply, but as I described above, it doesn't work.
a
For me it prints:
Copy code
Date: [Thu, 02 Jan 2025 13:50:27 GMT]
Connection: [upgrade]
Server: [nginx]
Upgrade: [websocket]
Sec-WebSocket-Accept: [XT3tzZpG0F8BagPlHIrV1pr6AhI=]
p
interesting, which server are you connecting to?
a
p
okay I'll try it later, thank you.
@Aleksei Tirman [JB] Thank you! By calling this override:
Copy code
public suspend fun HttpClient.webSocket(
    urlString: String,
    request: HttpRequestBuilder.() -> Unit = {},
    block: suspend DefaultClientWebSocketSession.() -> Unit
)
and get the response header inside block, it works. Sorry I was wrong, it doesn't work.
Hi @Aleksei Tirman [JB], sorry I was wrong, it doesn't work. My full code:
Copy code
val httpClient = httpClient {
        install(Logging) {
            logger = object : io.ktor.client.plugins.logging.Logger {
                override fun log(message: String) {
                    println(message)
                }
            }
            level = LogLevel.ALL
        }
        install(WebSockets) {
            pingIntervalMillis = 20_000
        }
    }

    val scope = CoroutineScope(Dispatchers.Default)
    scope.launch {
        httpClient.webSocket("<wss://ws.postman-echo.com/raw>") {
            println("XXPXX block start")
            val response = call.response
            println("XXPXX block got response")
            response.headers.forEach { key, values ->  println("$key: $values")}
            println("XXPXX block end")
        }
    }
and output is:
Copy code
REQUEST: <wss://ws.postman-echo.com/raw>
METHOD: HttpMethod(value=GET)
COMMON HEADERS
-> Accept: */*
-> Accept-Charset: UTF-8
CONTENT HEADERS
-> Connection: Upgrade
-> Sec-WebSocket-Key: ZTM0YmJlNDZhNDRiMmExYQ==
-> Sec-WebSocket-Version: 13
-> Upgrade: websocket
BODY Content-Type: null
BODY START

BODY END
RESPONSE: 101 Switching Protocols
METHOD: HttpMethod(value=GET)
FROM: <wss://ws.postman-echo.com/raw>
COMMON HEADERS
BODY Content-Type: null
BODY START

BODY END
XXPXX block start
XXPXX block got response
XXPXX block end
a
Which client engine do you use?
p
Java
a
Can you try using another engine like CIO or OkHttp?
p
okay
Great, OkHttp engine works fine:
Copy code
REQUEST: <wss://ws.postman-echo.com/raw>
METHOD: HttpMethod(value=GET)
COMMON HEADERS
-> Accept: */*
-> Accept-Charset: UTF-8
CONTENT HEADERS
-> Connection: Upgrade
-> Sec-WebSocket-Key: NWFjOTgyZTY2M2I5MjEyMg==
-> Sec-WebSocket-Version: 13
-> Upgrade: websocket
BODY Content-Type: null
BODY START

BODY END
RESPONSE: 101 Switching Protocols
METHOD: HttpMethod(value=GET)
FROM: <wss://ws.postman-echo.com/raw>
COMMON HEADERS
-> connection: upgrade
-> date: Thu, 02 Jan 2025 14:40:20 GMT
-> sec-websocket-accept: ZbNvfGNHXt1pYISCF3Ci2l2kH6U=
-> server: nginx
-> upgrade: websocket
BODY Content-Type: null
BODY START

BODY END
XXPXX block start
XXPXX block got response
connection: [upgrade]
date: [Thu, 02 Jan 2025 14:40:20 GMT]
sec-websocket-accept: [ZbNvfGNHXt1pYISCF3Ci2l2kH6U=]
server: [nginx]
upgrade: [websocket]
XXPXX block end
Okay, as you can see, when I use OkHttp engine, I can get headers, but the header keys and values are all lower case, and when I use CIO engine, the header keys and values are the original ones. @Aleksei Tirman [JB]
a
So, do the headers get printed when using the CIO engine?
p
@Aleksei Tirman [JB] Yes, CIO engine works perfectly. Do you have any plan to fix issues of Java engine and OkHttp engine?
a
I've created an issue to address the problem.
👍 1