![]() |
Long running Rest API Call mit THTTPClient
Ich benötige für einen Event von einem Rest-Server einen long running HTTP-Request.
Wie macht man das sauber mit Delphi Board mitteln? Meine aktuelle Lösung läuft zwar nach einigem Probieren. Der Stop des Request geht leider nur auf die harte Tour mit einem Thread.Terminate und hinterlässt dann als Folge unschöne Memory Leaks.
Delphi-Quellcode:
Da ich den Request alle paar Stunden repetitiv abbrechen muss um anschliessend mit einem neuen Token zu restarten, suche ich eine bessere Lösung.
type
TMyRestAPI = class private fClient: THTTPClient; fStream: TMemoryStream; fReadPos: Int64; fOnReceiveData: procedure(const data: string) of object; procedure OnRecData(const Sender: TObject; AContentLength: Int64; AReadCount: Int64; var Abort: Boolean); public procedure StartRequest(const URL: string); procedure StopRequest; end; procedure TMyRestAPI.StartRequest(const URL: string); begin fClient := THTTPClient.Create; fClient.HandleRedirects := true; fClient.Accept := 'text/event-stream'; fClient.OnReceiveData := OnRecData; fStream := TMemoryStream.Create; fReadPos := 0; fThread := TThread.CreateAnonymousThread( procedure begin fClient.Get(URL, fStream); end); fThread.Start; end; procedure TMyRestAPI.OnRecData(const Sender: TObject; AContentLength: Int64; AReadCount: Int64; var Abort: Boolean); var ss: TStringStream; resp: string; begin ss := TStringStream.Create; try fStream.Position := readPos; ss.CopyFrom(fStream, AReadCount - fReadPos); fOnReceiveData(ss.DataString); fReadPos := AReadCount; finally ss.Free; end; end; procedure TMyRestAPI.StopRequest; begin fThread.Terminate; fClient.Free; fStream.Free; end; Bei Verwendung der Asynchronen Calls mit BeginExecute/BeginGet lässt sich der laufende Request leider auch nur stoppen, wenn Daten vom Server empfangen werden. Gerade dies ist aber bei einem long running rest API Call über längere Zeit hinweg nicht der Fall und ich fand kein Weg, den asynchrone Request zu einem beliebigen Zeitpunkt zu stoppen.
Delphi-Quellcode:
Meine Lösung sollte unter Firemonkey auf allen Plattformen laufen, dass wäre mindestens dass Ziel!
Async := fClient.BeginGet(URL);
|
AW: Long running Rest API Call mit THTTPClient
Hast du dich bewusst gegen die REST-Komponenten (TRESTRequest, TRESTClient,TRESTResponse) entschieden?
![]() (Was völlig okay wäre, um klein und schlank zu bleiben, aber ich wollte trotzdem fragen.) |
AW: Long running Rest API Call mit THTTPClient
|
AW: Long running Rest API Call mit THTTPClient
Zitat:
|
AW: Long running Rest API Call mit THTTPClient
So etwas bringt mich auch immer wieder aus der Fassung. Das Problem liegt bei mir übrigens immer noch in der Schublade, die Timeouts sind bis heute immer noch drin :roteyes:
|
AW: Long running Rest API Call mit THTTPClient
Aber das liese sich doch mit den Intercepten der Windows-Funktionen doch problemlos umgehen.
|
AW: Long running Rest API Call mit THTTPClient
Die Verwendung von Timeouts ist aus meiner Sicht keine praktikable Lösung für mein Problem. Ich müsste ein kurzes Timeout (1 Sek) wählen, um die Anforderung für eine gute Reaktion beim Beenden einzuhalten.
In der Folge möchte ich aber nicht alle Sekunden den Http-Request wieder neu starten müssen nur weil ich bei Beendigung des Programm nicht länger als eine Sekunde warten darf. Ich brauche ich den long running Calls genau dafür, dass ich über längere Zeit den Stream offen halten kann und auf Ereignisse vom Server reagieren kann. Klar könnte man dies theoretisch auch mit einem Polling machen, bei dem alle Sekunden ein Get-Request an den Server gesandt wird. Nur bedeutet dies enorm viel mehr Traffic, den ich vermeiden will. Daher suche ich an einer Lösung, wie ich ein laufenden HTTP-Request bei Programm-Ende oder auf nach User-Interaktion sauber stoppen kann. Die Delphi Rest-Komponenten setzt ja auch auf der THTTPClient (In TRESTHTTP ist FHTTPClient auch System.Net.HTTPClient.THTTPClient) und ich dachte mir, je näher ich an der Basis-Komponente bin, desto besser kann ich deren Verhalten steuern. Mit der TNetHTTPClient und Client.Asynchronous := true habe ich es bereits probiert. Hier kann ich den Request auch nicht schliessen, wenn keine Daten vom Server empfangen werden. Wie machen denn andere long running rest API Calls? Und mit long running meine ich den Request eine Stunde oder länger offen zu halten und bei Bedarf wieder schliessen zu können. @TiGü: Wie würdest Du das angehen mit Interceptoren vor und nach der WinApi-Funktion? Eigentlich wollte ich den HTTP-Requestnicht selber für alle Plattformen (mindestens Mac OS und Win32/64) implementieren aber vielleicht läuft es am Schluss doch auf eine solche Lösung raus. |
AW: Long running Rest API Call mit THTTPClient
Meine Idee mit den Interceptoren bezog sich ja auf das Timeout-Problem vom Günther.
Das bringt dir so also nichts. Könntest du den lang offenen Request nicht in einen eigenen Prozess packen und den von deinen Hauptprogramm aus starten, steuern und ggf. killen? Es gibt bestimmt noch eine elegantere Variante. |
AW: Long running Rest API Call mit THTTPClient
Mit einem eigenen Prozess wäre zwar das Memory Leak entschärft, dafür müsste eine Interprozesskommunikation (bpsw. mit einer Pipe) alle eintreffenden Meldungen an den startenden Prozess übermitteln. Da erscheint mir der Aufwand zum Ertrag (keine aufsummierenden Memory Leaks mehr) gar etwas hoch. Beide Lösungen (Thread Kill vs. Prozess Kill) sind ein Murks.
Aus meiner Sicht müsste es wenigstens auf Api Level möglich sein, ein gestarter HTTP Request vom aufrufenden Thread in allen Fällen (also auch ohne Empfang von Daten) jederzeit wieder zu stoppen. Ich glaube, ich schaue jetzt mal wie das unter Windows gemacht werden könnte. Danke für die vielen wertvollen Ideen. |
AW: Long running Rest API Call mit THTTPClient
Hast du ein Beispiel für eine öffentliche REST-Schnittstelle mit long running requests?
Meine bisherigen Erfahrungen mit REST habe ich nur mit Schnittstellen gemacht, die innerhalb von einer handvoll Sekunden geantwortet haben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz