Hey Y'all,
Ok, here's my situation, and it's quite particular to my setup, since it only occurs when I'm tethering to my phone:
ANY HTTPS download using
FPHHTPClient will prematurely end at around 74%
Using Ikel's
cli-fp I've done this to try and find out what's happening:
unit CMD.FPHTTPCli;
{$mode ObjFPC}{$H+}{$J-}
interface
uses
Classes
, SysUtils
, Common.Utils // Utilities for formatting
, CLI.Interfaces // Core interfaces
, CLI.Progress // Optional: Progress indicators
, CLI.Command // Base command implementation
, CLI.Console // Optional: Colored console output
;
type
{ TCmdFHTTPCli }
TCmdFHTTPCli = class(TBaseCommand)
private
FSpinner: IProgressIndicator;
FStream: TMemoryStream;
FSize: Int64;
procedure OnDataReceived(Sender: TObject; Const ContentLength, CurrentPos: Int64);
protected
public
{ Main execution method that orchestrates the greeting display
@return 0 for success, 1 for errors }
function Execute: Integer; override;
published
end;
var
CmdFHTTPCli: TCmdFHTTPCli;
implementation
uses
fphttpclient // Free Pascal HTTP Client
, opensslsockets
;
const
codes: array of Integer = (
200,
400,
401,
403,
404,
405,
500,
501,
502,
503,
504
);
{ TCmdFHTTPCli }
procedure TCmdFHTTPCli.OnDataReceived(Sender: TObject; const ContentLength,
CurrentPos: Int64);
begin
FSpinner.Update(0);
TConsole.Write(Format(' Data Received: %9s of %9s (%6.2f%%); Stream: %9s',[
FormatBytes(CurrentPos),
FormatBytes(FSize),
Percent(FSize, CurrentPos),
FormatBytes(FStream.Position)
]));
end;
function TCmdFHTTPCli.Execute: Integer;
var
http: TFPHTTPClient;
url: String;
index: Integer;
begin
Result:= 0;
if GetParameterValue('--url', url) then
begin
http:= TFPHTTPClient.Create(nil);
try
FStream:= TMemoryStream.Create;
try
try
FSpinner := CreateSpinner(ssDots);
FSpinner.Start;
http.AllowRedirect:= True;
http.KeepConnection:= False;
FSpinner.Update(0);
TConsole.Write(' Calling HEAD');
http.HTTPMethod('HEAD', url, nil, []);
FSize := 0;
for index := 0 to Pred(http.ResponseHeaders.Count) do
begin
if LowerCase(http.ResponseHeaders.Names[index]) = 'content-length' then
begin
FSize:= StrToInt64(http.ResponseHeaders.ValueFromIndex[index]);
FSpinner.Update(0);
TConsole.Write(Format(' Got Size: %d; Status(%d): %s', [
FSize,
http.ResponseStatusCode,
http.ResponseStatusText
]));
break;
end;
end;
Sleep(2000);
FSpinner.Update(0);
TConsole.Write(' Calling GET ');
http.OnDataReceived:=@OnDataReceived;
http.HTTPMethod(
'GET',
url,
FStream,
codes
);
FSpinner.Stop;
TConsole.WriteLn(Format('Status(%d): %s', [http.ResponseStatusCode, http.ResponseStatusText]));
except
on E:Exception do
begin
Result:= 1;
TConsole.WriteLn('ERROR: ' + E.Message, ccRed);
end;
end;
finally
FStream.Free;
end;
finally
http.free;
end;
end
else
begin
Result:= 1;
TConsole.WriteLn('ERROR: No URL to download', ccRed);
end;
end;
end.
As you can see I have:
- Created a codes variable with a ton of HTTP Status codes.
- Put a call to HEAD because the first 4 or 5 calls to OnDataReceived come with the total at zero
- A try..except around the entire transfer code
While testing it, no matter the speed that my provider's allowing me, I get consistent download drop at around 74%, I know this is a clue, just not figured what it means yet.
This only happens in
HTTPS not
HTTP. I've tested both and the
HTTP completes every time, no issue.
The call to
HTTPMethod never triggers any exception and always returns
200 OK.
It only happens on files above 10MB. I've tested with files of ~1MB and it downloads it fine, but with files of 11MB, 16MB and 17MB it drops.
I've tested with
aria2c,
wget and
cURL. They download the file without any issue.
One of the things that bothers me is the fact that
FPHHTPClient swallows any/all exception. I don't think that we get anything going bad if it happens at the
SSL level. Which is where my suspicions are at the moment. I don't think it's chunking, but I'm not sure.
My suspicions, at the moment are: It's either an
SSL issue, or a chunking issue.
Since I don't want to post an issue on GitLab to something that can only be
reproduced with my own phone's tethering, I need some help to debug. I'm quite unfamiliar with the code and the hierarchy of the Classes that it's just a black box at the moment.
Why all this? Welp, I did a
GUI downloader that is now used on
fpcupdeluxe, and it
fails miserably 
. I need to get to the bottom of this in order to not disappoint it's author!!
Can someone give me some pointers to where I should dig in?
Many thanks in advance!!
Cheers,
Gus