|
@@ -19,7 +19,7 @@ unit fphttpclient;
|
|
interface
|
|
interface
|
|
|
|
|
|
uses
|
|
uses
|
|
- Classes, SysUtils, ssockets, httpdefs, uriparser, base64, sslsockets;
|
|
|
|
|
|
+ Classes, SysUtils, ssockets, httpdefs, uriparser, base64, sslsockets, DateUtils;
|
|
|
|
|
|
Const
|
|
Const
|
|
// Socket Read buffer size
|
|
// Socket Read buffer size
|
|
@@ -73,6 +73,7 @@ Type
|
|
FKeepConnection: Boolean;
|
|
FKeepConnection: Boolean;
|
|
FMaxChunkSize: SizeUInt;
|
|
FMaxChunkSize: SizeUInt;
|
|
FMaxRedirects: Byte;
|
|
FMaxRedirects: Byte;
|
|
|
|
+ FOnIdle: TNotifyEvent;
|
|
FOnDataReceived: TDataEvent;
|
|
FOnDataReceived: TDataEvent;
|
|
FOnDataSent: TDataEvent;
|
|
FOnDataSent: TDataEvent;
|
|
FOnHeaders: TNotifyEvent;
|
|
FOnHeaders: TNotifyEvent;
|
|
@@ -131,6 +132,10 @@ Type
|
|
Function ProxyActive : Boolean;
|
|
Function ProxyActive : Boolean;
|
|
// Override this if you want to create a custom instance of proxy.
|
|
// Override this if you want to create a custom instance of proxy.
|
|
Function CreateProxyData : TProxyData;
|
|
Function CreateProxyData : TProxyData;
|
|
|
|
+ // Called before data is read.
|
|
|
|
+ Procedure DoBeforeDataRead; virtual;
|
|
|
|
+ // Called when the client is waiting for the server.
|
|
|
|
+ Procedure DoOnIdle; virtual;
|
|
// Called whenever data is read.
|
|
// Called whenever data is read.
|
|
Procedure DoDataRead; virtual;
|
|
Procedure DoDataRead; virtual;
|
|
// Called whenever data is written.
|
|
// Called whenever data is written.
|
|
@@ -345,6 +350,8 @@ Type
|
|
Property OnPassword : TPasswordEvent Read FOnPassword Write FOnPassword;
|
|
Property OnPassword : TPasswordEvent Read FOnPassword Write FOnPassword;
|
|
// Called whenever data is read from the connection.
|
|
// Called whenever data is read from the connection.
|
|
Property OnDataReceived : TDataEvent Read FOnDataReceived Write FOnDataReceived;
|
|
Property OnDataReceived : TDataEvent Read FOnDataReceived Write FOnDataReceived;
|
|
|
|
+ // Called when the client is waiting for the server
|
|
|
|
+ Property OnIdle : TNotifyEvent Read FOnIdle Write FOnIdle;
|
|
// Called whenever data is written to the connection.
|
|
// Called whenever data is written to the connection.
|
|
Property OnDataSent : TDataEvent Read FOnDataSent Write FOnDataSent;
|
|
Property OnDataSent : TDataEvent Read FOnDataSent Write FOnDataSent;
|
|
// Called when headers have been processed.
|
|
// Called when headers have been processed.
|
|
@@ -380,6 +387,7 @@ Type
|
|
Property OnPassword;
|
|
Property OnPassword;
|
|
Property OnDataReceived;
|
|
Property OnDataReceived;
|
|
Property OnDataSent;
|
|
Property OnDataSent;
|
|
|
|
+ Property OnIdle;
|
|
Property OnHeaders;
|
|
Property OnHeaders;
|
|
Property OnGetSocketHandler;
|
|
Property OnGetSocketHandler;
|
|
Property Proxy;
|
|
Property Proxy;
|
|
@@ -689,6 +697,21 @@ begin
|
|
FreeAndNil(FSocket);
|
|
FreeAndNil(FSocket);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TFPCustomHTTPClient.DoBeforeDataRead;
|
|
|
|
+var
|
|
|
|
+ BreakUTC: TDateTime;
|
|
|
|
+begin
|
|
|
|
+ // use CanRead to keep the client responsive in case the server needs a lot of time to respond
|
|
|
|
+ if IOTimeout>0 then
|
|
|
|
+ BreakUTC := IncMilliSecond(NowUTC, IOTimeout);
|
|
|
|
+ while not Terminated and not FSocket.CanRead(10) do
|
|
|
|
+ begin
|
|
|
|
+ DoOnIdle;
|
|
|
|
+ if (IOTimeout>0) and (CompareDateTime(NowUTC, BreakUTC)>0) then // we exceeded the timeout -> read error
|
|
|
|
+ Raise EHTTPClientSocketRead.Create(SErrReadingSocket);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
function TFPCustomHTTPClient.AllowHeader(var AHeader: String): Boolean;
|
|
function TFPCustomHTTPClient.AllowHeader(var AHeader: String): Boolean;
|
|
|
|
|
|
begin
|
|
begin
|
|
@@ -780,6 +803,7 @@ function TFPCustomHTTPClient.ReadString(out S: String): Boolean;
|
|
R : Integer;
|
|
R : Integer;
|
|
|
|
|
|
begin
|
|
begin
|
|
|
|
+ DoBeforeDataRead;
|
|
if Terminated then
|
|
if Terminated then
|
|
Exit(False);
|
|
Exit(False);
|
|
SetLength(FBuffer,ReadBufLen);
|
|
SetLength(FBuffer,ReadBufLen);
|
|
@@ -1121,6 +1145,9 @@ Function TFPCustomHTTPClient.ReadResponse(Stream: TStream;
|
|
Function Transfer(LB : Integer) : Integer;
|
|
Function Transfer(LB : Integer) : Integer;
|
|
|
|
|
|
begin
|
|
begin
|
|
|
|
+ DoBeforeDataRead;
|
|
|
|
+ if Terminated then
|
|
|
|
+ Exit(0);
|
|
Result:=FSocket.Read(FBuffer[1],LB);
|
|
Result:=FSocket.Read(FBuffer[1],LB);
|
|
If Result<0 then
|
|
If Result<0 then
|
|
Raise EHTTPClientSocketRead.Create(SErrReadingSocket);
|
|
Raise EHTTPClientSocketRead.Create(SErrReadingSocket);
|
|
@@ -1152,6 +1179,7 @@ Function TFPCustomHTTPClient.ReadResponse(Stream: TStream;
|
|
|
|
|
|
begin
|
|
begin
|
|
Result:=False;
|
|
Result:=False;
|
|
|
|
+ DoBeforeDataRead;
|
|
If Terminated then
|
|
If Terminated then
|
|
exit;
|
|
exit;
|
|
SetLength(FBuffer,ReadBuflen);
|
|
SetLength(FBuffer,ReadBuflen);
|
|
@@ -1356,6 +1384,12 @@ begin
|
|
End;
|
|
End;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+procedure TFPCustomHTTPClient.DoOnIdle;
|
|
|
|
+begin
|
|
|
|
+ If Assigned(FOnIdle) Then
|
|
|
|
+ FOnIdle(Self);
|
|
|
|
+end;
|
|
|
|
+
|
|
Procedure TFPCustomHTTPClient.DoKeepConnectionRequest(const AURI: TURI;
|
|
Procedure TFPCustomHTTPClient.DoKeepConnectionRequest(const AURI: TURI;
|
|
const AMethod: string; AStream: TStream;
|
|
const AMethod: string; AStream: TStream;
|
|
const AAllowedResponseCodes: array of Integer;
|
|
const AAllowedResponseCodes: array of Integer;
|