Go
Go
Firebase Receive Server-Sent Events (text/event-stream)
See more Firebase Examples
Demonstrates how to start receiving server-sent events and update your JSON database with each event.Chilkat Go Downloads
success := false
// Demonstrates how to begin receiving server-sent events, and to update
// your JSON database for each event.
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// This example assumes a JWT authentication token, if required, has been previously obtained.
// See Get Firebase Access Token from JSON Service Account Private Key for sample code.
// Load the previously obtained Firebase access token into a string.
fac := chilkat.NewFileAccess()
accessToken := fac.ReadEntireTextFile("qa_data/tokens/firebaseToken.txt","utf-8")
if fac.LastMethodSuccess() == false {
fmt.Println(fac.LastErrorText())
fac.DisposeFileAccess()
return
}
rest := chilkat.NewRest()
// Make the initial connection (without sending a request yet).
// Once connected, any number of requests may be sent. It is not necessary to explicitly
// call Connect before each request.
success = rest.Connect("chilkat.firebaseio.com",443,true,true)
if success == false {
fmt.Println(rest.LastErrorText())
fac.DisposeFileAccess()
rest.DisposeRest()
return
}
authGoogle := chilkat.NewAuthGoogle()
authGoogle.SetAccessToken(*accessToken)
rest.SetAuthGoogle(authGoogle)
rest.AddHeader("Accept","text/event-stream")
rest.AddHeader("Cache-Control","no-cache")
responseBody := rest.FullRequestNoBody("GET","/.json")
// A 307 redirect response is expected.
if rest.ResponseStatusCode() != 307 {
fmt.Println("Unexpected response code: ", rest.ResponseStatusCode())
fmt.Println(*responseBody)
fmt.Println("Failed.")
fac.DisposeFileAccess()
rest.DisposeRest()
authGoogle.DisposeAuthGoogle()
return
}
// Get the redirect URL
urlStr := rest.LastRedirectUrl()
url := chilkat.NewUrl()
url.ParseUrl(urlStr)
fmt.Println("redirect URL domain: ", url.Host())
fmt.Println("redirect URL path: ", url.Path())
fmt.Println("redirect URL query params: ", url.Query())
fmt.Println("redirect URL path with query params: ", url.PathWithQueryParams())
// Our text/event-stream will be obtained from the redirect URL...
rest2 := chilkat.NewRest()
success = rest2.Connect(url.Host(),443,true,true)
if success != true {
fmt.Println(rest2.LastErrorText())
fac.DisposeFileAccess()
rest.DisposeRest()
authGoogle.DisposeAuthGoogle()
url.DisposeUrl()
rest2.DisposeRest()
return
}
rest2.AddHeader("Accept","text/event-stream")
rest2.AddHeader("Cache-Control","no-cache")
// Add the redirect query params to the request
rest2.AddQueryParams(url.Query())
// In our case, we don't actually need the auth query param,
// so remove it.
rest2.RemoveQueryParam("auth")
// Send the request. (We are only sending the request here.
// We are not yet getting the response because the response
// will be a text/event-stream.)
success = rest2.SendReqNoBody("GET",url.Path())
if success != true {
fmt.Println(rest2.LastErrorText())
fac.DisposeFileAccess()
rest.DisposeRest()
authGoogle.DisposeAuthGoogle()
url.DisposeUrl()
rest2.DisposeRest()
return
}
// Read the response header.
// We want to first get the response header to see if it's a successful
// response status code. If not, then the response will not be a text/event-stream
// and we should read the response body normally.
responseStatusCode := rest2.ReadResponseHeader()
if responseStatusCode < 0 {
fmt.Println(rest2.LastErrorText())
fac.DisposeFileAccess()
rest.DisposeRest()
authGoogle.DisposeAuthGoogle()
url.DisposeUrl()
rest2.DisposeRest()
return
}
// If successful, a 200 response code is expected.
// If the reponse code is not 200, then read the response body and fail..
if responseStatusCode != 200 {
fmt.Println("Response Code: ", responseStatusCode)
fmt.Println("Response Status Text: ", rest2.ResponseStatusText())
fmt.Println("Response Header: ", rest2.ResponseHeader())
responseBody = rest2.ReadRespBodyString()
if rest2.LastMethodSuccess() == true {
fmt.Println("Error Response Body: ", *responseBody)
}
fmt.Println("Failed.")
fac.DisposeFileAccess()
rest.DisposeRest()
authGoogle.DisposeAuthGoogle()
url.DisposeUrl()
rest2.DisposeRest()
return
}
// For this example, our JSON database will be empty at the beginning.
// The incoming events (put and patch) will be applied to this database.
jsonDb := chilkat.NewJsonObject()
// Make sure to set the JSON path delimiter to "/". The default is "." and this
// is not compatible with Firebase paths.
jsonDb.SetDelimiterChar("/")
// At this point, we've received the response header. Now it's time to begin
// receiving the event stream. We'll start a background thread to read the
// stream. (Our main application (foreground) thread can cancel it at any time.)
// While receiving in the background thread, our foreground thread can read the stream
// as it desires..
eventStream := chilkat.NewStream()
// This sse object will be used as a helper to parse the server-sent event stream.
sse := chilkat.NewServerSentEvent()
c := make(chan *chilkat.Task)
go rest2.ReadRespBodyStreamAsync(eventStream,true,c)
task := <-c
// For this example, we'll just read a few events, and then cancel the
// async task.
count := 0
for (count < 3) && (task.Finished() == false) {
// Get the next event, which is a series of text lines ending with
// a blank line.
// Note: This method blocks the calling thread until a message arrives.
// a program might instead periodically check the availability of
// data via the stream's DataAvailable property, and then do the read.
// An alternative to writing a while loop to read the event stream
// would be to setup some sort of timer event in your program (using whatever timer functionality
// is provided in a programming language/environment), to periodically check the eventStream's
// DataAvailable property and consume the incoming event.
eventStr := eventStream.ReadUntilMatch("\r\n\r\n")
if eventStream.LastMethodSuccess() != true {
fmt.Println(eventStream.LastErrorText())
// Force the loop to exit by setting the count to a high number.
count = 99999
} else {
fmt.Println("Event: [", *eventStr, "]")
// We have an event. Let's update our local copy of the JSON database.
success = sse.LoadEvent(*eventStr)
if success != true {
fmt.Println("Failed to load sse event: ", *eventStr)
} else {
// Now we can easily access the event name and data, and apply it to our JSON database:
success = jsonDb.FirebaseApplyEvent(sse.EventName(),sse.Data())
if success != true {
fmt.Println("Failed to apply event: ", sse.EventName(), ": ", sse.Data())
} else {
fmt.Println("Successfully applied event: ", sse.EventName(), ": ", sse.Data())
}
}
}
count = count + 1
}
// Make sure the background task is cancelled if still running.
task.Cancel()
task.DisposeTask()
// Examine the JSON database after applying events..
jsonDb.SetEmitCompact(false)
fmt.Println("----")
fmt.Println(*jsonDb.Emit())
fac.DisposeFileAccess()
rest.DisposeRest()
authGoogle.DisposeAuthGoogle()
url.DisposeUrl()
rest2.DisposeRest()
jsonDb.DisposeJsonObject()
eventStream.DisposeStream()
sse.DisposeServerSentEvent()
task.DisposeTask()