Overview
Server-Sent Events
(SSE) can provide effective and powerful Server Push Notifications when used in conjunction with the HTTP/2
protocol. Over the years, I have successfully and frequently used SSE in production-level scenarios for various business requirements. Recognizing the lack of examples on the internet that cater to each client's specific situations, I decided to write and introduce them myself. (All the example codes provided below have been validated at the production level.)
Using curl Command for SSE Connection and Event Reception
- For testing and debugging purposes, it's possible to create an EventSource connection and receive events using the
curl
command as follows. The connection remains active until termination and receives new events.
curl -N --http2 \
-H "Accept:text/event-stream" \
-H "Authorization:Bearer {token}" \
'{server-url}'
SSE Connection and Event Reception in Browser JavaScript
- In the browser environment, it's possible to create the HTML5 standard EventSource object to receive SSE connection events. However, standard APIs cannot send custom request headers for authentication, etc. Using a third-party library as below makes this possible.
// Using the Yaffle EventSource Polyfill library to enable custom header requests not possible with vanilla EventSource
<script src="https://raw.githubusercontent.com/Yaffle/EventSource/master/src/eventsource.min.js"></script>
<script>
const eventSource = new EventSourcePolyfill('{server-url}', {
headers: {
'Authorization': 'Bearer {token}'
},
lastEventIdQueryParameterName: 'Last-Event-ID',
heartbeatTimeout: 600000
})
eventSource.addEventListener("{channel}", function(event) {
console.log(event.data)
})
</script>
SSE Connection and Event Reception in Android Kotlin
- In Android and JVM environments, implementation can be done using third-party libraries as follows.
- First, add the following to the project's root build.gradle.kts.
dependencies {
implementation("com.launchdarkly:okhttp-eventsource:4.1.1")
}
- Write a listener to handle Message arrival events for a specific Channel.
class SseEventHandler : BackgroundEventHandler {
override fun onOpen() {
}
override fun onClosed() {
}
override fun onMessage(event: String, messageEvent: MessageEvent) {
}
override fun onComment(comment: String) {
}
override fun onError(t: Throwable) {
}
}
- Finally, implement the code to create the EventSource object as follows.
val eventSource: BackgroundEventSource = BackgroundEventSource
.Builder(
SseEventHandler(),
EventSource.Builder(
ConnectStrategy
.http(URL("{server-url}"))
.header(
"Authorization",
"Bearer {token}"
)
.connectTimeout(3, TimeUnit.SECONDS)
.readTimeout(600, TimeUnit.SECONDS)
)
)
.threadPriority(Thread.MAX_PRIORITY)
.build()
eventSource.start()
SSE Connection and Event Reception in iOS Swift
- In the iOS Swift environment, implementation can be done using third-party libraries as follows.
- First, add the library dependencies to the project environment as follows. (The same LaunchDarkly-produced EventSource library as in the Android example is used.)
pod 'LDSwiftEventSource', '~> 3.1'
github "LaunchDarkly/swift-eventsource" ~> 3.1
dependencies: [
.package(url: "https://github.com/LaunchDarkly/swift-eventsource.git", .upToNextMajor(from: "3.1.1"))
]
- Write a listener to handle Message arrival events for a specific Channel.
class SseEventHandler: EventHandler {
func onOpened() {
}
func onClosed() {
}
func onMessage(eventType: String, messageEvent: MessageEvent) {
}
func onComment(comment: String) {
}
func onError(error: Error) {
}
}
- Finally, implement the code to create the EventSource object as follows.
var config = EventSource.Config(handler: SseEventHandler(), url: URL(string: "{server-url}")!)
config.headers = ["Authorization": "Bearer {token}"]
config.idelTimeout = 600.0
let eventSource = EventSource(config: config)
eventSource.start()
Reference Links