Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(PureBasic) Firebase Receive Server-Sent Events (text/event-stream)Demonstrates how to start receiving server-sent events and update your JSON database with each event.
IncludeFile "CkJsonObject.pb" IncludeFile "CkTask.pb" IncludeFile "CkFileAccess.pb" IncludeFile "CkUrl.pb" IncludeFile "CkStream.pb" IncludeFile "CkAuthGoogle.pb" IncludeFile "CkRest.pb" IncludeFile "CkServerSentEvent.pb" Procedure ChilkatExample() ; 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.i = CkFileAccess::ckCreate() If fac.i = 0 Debug "Failed to create object." ProcedureReturn EndIf accessToken.s = CkFileAccess::ckReadEntireTextFile(fac,"qa_data/tokens/firebaseToken.txt","utf-8") If CkFileAccess::ckLastMethodSuccess(fac) <> 1 Debug CkFileAccess::ckLastErrorText(fac) CkFileAccess::ckDispose(fac) ProcedureReturn EndIf rest.i = CkRest::ckCreate() If rest.i = 0 Debug "Failed to create object." ProcedureReturn EndIf ; 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.i = CkRest::ckConnect(rest,"chilkat.firebaseio.com",443,1,1) If success <> 1 Debug CkRest::ckLastErrorText(rest) CkFileAccess::ckDispose(fac) CkRest::ckDispose(rest) ProcedureReturn EndIf authGoogle.i = CkAuthGoogle::ckCreate() If authGoogle.i = 0 Debug "Failed to create object." ProcedureReturn EndIf CkAuthGoogle::setCkAccessToken(authGoogle, accessToken) CkRest::ckSetAuthGoogle(rest,authGoogle) CkRest::ckAddHeader(rest,"Accept","text/event-stream") CkRest::ckAddHeader(rest,"Cache-Control","no-cache") responseBody.s = CkRest::ckFullRequestNoBody(rest,"GET","/.json") ; A 307 redirect response is expected. If CkRest::ckResponseStatusCode(rest) <> 307 Debug "Unexpected response code: " + Str(CkRest::ckResponseStatusCode(rest)) Debug responseBody Debug "Failed." CkFileAccess::ckDispose(fac) CkRest::ckDispose(rest) CkAuthGoogle::ckDispose(authGoogle) ProcedureReturn EndIf ; Get the redirect URL url.i = CkRest::ckRedirectUrl(rest) If CkRest::ckLastMethodSuccess(rest) <> 1 Debug CkRest::ckLastErrorText(rest) CkFileAccess::ckDispose(fac) CkRest::ckDispose(rest) CkAuthGoogle::ckDispose(authGoogle) ProcedureReturn EndIf Debug "redirect URL domain: " + CkUrl::ckHost(url) Debug "redirect URL path: " + CkUrl::ckPath(url) Debug "redirect URL query params: " + CkUrl::ckQuery(url) Debug "redirect URL path with query params: " + CkUrl::ckPathWithQueryParams(url) ; Our text/event-stream will be obtained from the redirect URL... rest2.i = CkRest::ckCreate() If rest2.i = 0 Debug "Failed to create object." ProcedureReturn EndIf success = CkRest::ckConnect(rest2,CkUrl::ckHost(url),443,1,1) If success <> 1 Debug CkRest::ckLastErrorText(rest2) CkUrl::ckDispose(url) CkFileAccess::ckDispose(fac) CkRest::ckDispose(rest) CkAuthGoogle::ckDispose(authGoogle) CkRest::ckDispose(rest2) ProcedureReturn EndIf CkRest::ckAddHeader(rest2,"Accept","text/event-stream") CkRest::ckAddHeader(rest2,"Cache-Control","no-cache") ; Add the redirect query params to the request CkRest::ckAddQueryParams(rest2,CkUrl::ckQuery(url)) ; In our case, we don't actually need the auth query param, ; so remove it. CkRest::ckRemoveQueryParam(rest2,"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 = CkRest::ckSendReqNoBody(rest2,"GET",CkUrl::ckPath(url)) If success <> 1 Debug CkRest::ckLastErrorText(rest2) CkUrl::ckDispose(url) CkFileAccess::ckDispose(fac) CkRest::ckDispose(rest) CkAuthGoogle::ckDispose(authGoogle) CkRest::ckDispose(rest2) ProcedureReturn EndIf CkUrl::ckDispose(url) ; 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.i = CkRest::ckReadResponseHeader(rest2) If responseStatusCode < 0 Debug CkRest::ckLastErrorText(rest2) CkFileAccess::ckDispose(fac) CkRest::ckDispose(rest) CkAuthGoogle::ckDispose(authGoogle) CkRest::ckDispose(rest2) ProcedureReturn EndIf ; 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 Debug "Response Code: " + Str(responseStatusCode) Debug "Response Status Text: " + CkRest::ckResponseStatusText(rest2) Debug "Response Header: " + CkRest::ckResponseHeader(rest2) responseBody = CkRest::ckReadRespBodyString(rest2) If CkRest::ckLastMethodSuccess(rest2) = 1 Debug "Error Response Body: " + responseBody EndIf Debug "Failed." CkFileAccess::ckDispose(fac) CkRest::ckDispose(rest) CkAuthGoogle::ckDispose(authGoogle) CkRest::ckDispose(rest2) ProcedureReturn EndIf ; 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.i = CkJsonObject::ckCreate() If jsonDb.i = 0 Debug "Failed to create object." ProcedureReturn EndIf ; Make sure to set the JSON path delimiter to "/". The default is "." and this ; is not compatible with Firebase paths. CkJsonObject::setCkDelimiterChar(jsonDb, "/") ; 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.i = CkStream::ckCreate() If eventStream.i = 0 Debug "Failed to create object." ProcedureReturn EndIf ; This sse object will be used as a helper to parse the server-sent event stream. sse.i = CkServerSentEvent::ckCreate() If sse.i = 0 Debug "Failed to create object." ProcedureReturn EndIf task.i = CkRest::ckReadRespBodyStreamAsync(rest2,eventStream,1) CkTask::ckRun(task) ; For this example, we'll just read a few events, and then cancel the ; async task. count.i = 0 While (count < 3) AND (CkTask::ckFinished(task) = 0) ; 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.s = CkStream::ckReadUntilMatch(eventStream,Chr(13) + Chr(10) + Chr(13) + Chr(10)) If CkStream::ckLastMethodSuccess(eventStream) <> 1 Debug CkStream::ckLastErrorText(eventStream) ; Force the loop to exit by setting the count to a high number. count = 99999 Else Debug "Event: [" + eventStr + "]" ; We have an event. Let's update our local copy of the JSON database. success = CkServerSentEvent::ckLoadEvent(sse,eventStr) If success <> 1 Debug "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 = CkJsonObject::ckFirebaseApplyEvent(jsonDb,CkServerSentEvent::ckEventName(sse),CkServerSentEvent::ckData(sse)) If success <> 1 Debug "Failed to apply event: " + CkServerSentEvent::ckEventName(sse) + ": " + CkServerSentEvent::ckData(sse) Else Debug "Successfully applied event: " + CkServerSentEvent::ckEventName(sse) + ": " + CkServerSentEvent::ckData(sse) EndIf EndIf EndIf count = count + 1 Wend ; Make sure the background task is cancelled if still running. CkTask::ckCancel(task) CkTask::ckDispose(task) ; Examine the JSON database after applying events.. CkJsonObject::setCkEmitCompact(jsonDb, 0) Debug "----" Debug CkJsonObject::ckEmit(jsonDb) CkFileAccess::ckDispose(fac) CkRest::ckDispose(rest) CkAuthGoogle::ckDispose(authGoogle) CkRest::ckDispose(rest2) CkJsonObject::ckDispose(jsonDb) CkStream::ckDispose(eventStream) CkServerSentEvent::ckDispose(sse) ProcedureReturn EndProcedure |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.