Sample code for 30+ languages & platforms
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

Go
    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()