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
(Delphi ActiveX) Firebase Receive Server-Sent Events (text/event-stream)Demonstrates how to start receiving server-sent events and update your JSON database with each event.
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Chilkat_TLB; ... procedure TForm1.Button1Click(Sender: TObject); var fac: TCkFileAccess; accessToken: WideString; rest: TChilkatRest; success: Integer; authGoogle: TChilkatAuthGoogle; responseBody: WideString; url: IChilkatUrl; rest2: TChilkatRest; responseStatusCode: Integer; jsonDb: TChilkatJsonObject; eventStream: TChilkatStream; sse: TChilkatServerSentEvent; task: IChilkatTask; count: Integer; eventStr: WideString; begin // 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 := TCkFileAccess.Create(Self); accessToken := fac.ReadEntireTextFile('qa_data/tokens/firebaseToken.txt','utf-8'); if (fac.LastMethodSuccess <> 1) then begin Memo1.Lines.Add(fac.LastErrorText); Exit; end; rest := TChilkatRest.Create(Self); // 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,1,1); if (success <> 1) then begin Memo1.Lines.Add(rest.LastErrorText); Exit; end; authGoogle := TChilkatAuthGoogle.Create(Self); authGoogle.AccessToken := accessToken; rest.SetAuthGoogle(authGoogle.ControlInterface); 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) then begin Memo1.Lines.Add('Unexpected response code: ' + IntToStr(rest.ResponseStatusCode)); Memo1.Lines.Add(responseBody); Memo1.Lines.Add('Failed.'); Exit; end; // Get the redirect URL url := rest.RedirectUrl(); if (rest.LastMethodSuccess <> 1) then begin Memo1.Lines.Add(rest.LastErrorText); Exit; end; Memo1.Lines.Add('redirect URL domain: ' + url.Host); Memo1.Lines.Add('redirect URL path: ' + url.Path); Memo1.Lines.Add('redirect URL query params: ' + url.Query); Memo1.Lines.Add('redirect URL path with query params: ' + url.PathWithQueryParams); // Our text/event-stream will be obtained from the redirect URL... rest2 := TChilkatRest.Create(Self); success := rest2.Connect(url.Host,443,1,1); if (success <> 1) then begin Memo1.Lines.Add(rest2.LastErrorText); Exit; end; 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 <> 1) then begin Memo1.Lines.Add(rest2.LastErrorText); Exit; end; // 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) then begin Memo1.Lines.Add(rest2.LastErrorText); Exit; end; // 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) then begin Memo1.Lines.Add('Response Code: ' + IntToStr(responseStatusCode)); Memo1.Lines.Add('Response Status Text: ' + rest2.ResponseStatusText); Memo1.Lines.Add('Response Header: ' + rest2.ResponseHeader); responseBody := rest2.ReadRespBodyString(); if (rest2.LastMethodSuccess = 1) then begin Memo1.Lines.Add('Error Response Body: ' + responseBody); end; Memo1.Lines.Add('Failed.'); Exit; end; // 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 := TChilkatJsonObject.Create(Self); // Make sure to set the JSON path delimiter to "/". The default is "." and this // is not compatible with Firebase paths. jsonDb.DelimiterChar := '/'; // 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 := TChilkatStream.Create(Self); // This sse object will be used as a helper to parse the server-sent event stream. sse := TChilkatServerSentEvent.Create(Self); task := rest2.ReadRespBodyStreamAsync(eventStream.ControlInterface,1); task.Run(); // For this example, we'll just read a few events, and then cancel the // async task. count := 0; while (count < 3) and (task.Finished = 0) do begin // 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(#13#10 + #13#10); if (eventStream.LastMethodSuccess <> 1) then begin Memo1.Lines.Add(eventStream.LastErrorText); // Force the loop to exit by setting the count to a high number. count := 99999; end else begin Memo1.Lines.Add('Event: [' + eventStr + ']'); // We have an event. Let's update our local copy of the JSON database. success := sse.LoadEvent(eventStr); if (success <> 1) then begin Memo1.Lines.Add('Failed to load sse event: ' + eventStr); end else begin // 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 <> 1) then begin Memo1.Lines.Add('Failed to apply event: ' + sse.EventName + ': ' + sse.Data); end else begin Memo1.Lines.Add('Successfully applied event: ' + sse.EventName + ': ' + sse.Data); end; end; end; count := count + 1; end; // Make sure the background task is cancelled if still running. task.Cancel(); // Examine the JSON database after applying events.. jsonDb.EmitCompact := 0; Memo1.Lines.Add('----'); Memo1.Lines.Add(jsonDb.Emit()); end; |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.