Hi! I found a weird behavior with `sse()` routes. ...
# ktor
h
Hi! I found a weird behavior with
sse()
routes. If we want to send a HTTP response instead of emitting events (e.g.,
call.respond(HttpStatusCode.BadRequest)
), that response code is simply ignored and we always get HTTP 200. Is this an expected behavior? I feel it makes error handling for SSE endpoints difficult.
a
The plugin's HTTP handler for the SSE endpoint is executed before the SSE block. So the response is already sent when the call property within the SSE block is accessed. Can you tell me what the expected behavior should be?
h
If my request fails, I want to respond with a regular HTTP 4xx or 5xx code and a body describing the error. Basically we only want to upgrade to a SSE stream if things are going well.
Can we manually upgrade a route to SSE? We would like to use HTTP POST to initiate the stream, and as far as I know, the spec doesn't prevent that
a
What do you mean by things going well? The built-in handler already checks the status code.
h
In our SSE endpoint we read from an external service. If that call fails, we want to respond with HTTP 4xx or 5xx depending on the failure, instead of sending events.
Basically, we shouldn't send the upgrade header until we are sure everything is good from the external service
a
You can respond with an instance of the
SSEServerContent
class to initiate an SSE session. Here is an example:
Copy code
routing {
    get("/sse") {
        try {
            external()

            call.response.header(HttpHeaders.ContentType, ContentType.Text.EventStream.toString())
            call.response.header(HttpHeaders.CacheControl, "no-store")
            call.response.header(HttpHeaders.Connection, "keep-alive")
            call.response.header("X-Accel-Buffering", "no")
            call.respond(SSEServerContent(call) {
                send(ServerSentEvent("Hello client!"))
            })
        } catch (_: RuntimeException) {
            call.respond(HttpStatusCode.InternalServerError)
        }
    }
}
// ...
suspend fun external() {
//    throw RuntimeException("error")
}
👍 1
h
Thanks!