Reputation: 84550
I've got an Indy server, and having it send a file when the URL requests a file is trivial and always seems to work right.
But I'm also trying to set up a second case that looks like this:
http://example.com/getFile.html?filename=myImage.png
(This works with dynamically generated content, so asking for a static file wouldn't work.) I'm using a custom Indy client and calling TIdHTTP.Get
to retrieve all these files, and in the second use case, it seems to be following this algorithm:
Roll 1D4. If you rolled 2 or higher, download correctly.
Otherwise, roll 1D6 against this table of Indy exceptions and
raise one of them.
If a random exception is raised, it MUST NOT be caught inside
of Indy code.
So far the common ones seem to be EIdHTTPProtocolException
, EIdClosedSocket
, and EIdNotConnected
, but I've seen a few others as well. Setting up an exception handler to catch these and retry the download works sometimes, and other times it just raises more exceptions, again seemingly at random with no deterministic principle behind it.
The fact that this never happens using the static download use case tells me that there's probably something strange going on under the hood in the second use case that my code isn't accounting for properly.
The code is really quite simple. On the client side:
procedure TdmConnection.GetFile(const URL: string; stream: TStream);
procedure Retry;
begin
sleep(100);
stream.Size := 0; //clear any aborted partial download
http.Get(URL, stream);
end;
begin
try
http.Get(URL, stream);
except
on EIdClosedSocket do
Retry;
on EIdNotConnected do
Retry;
on EIdHTTPProtocolException do
Retry;
end;
end;
And on the server side, the request runs a script that produces the file (correctly; I've verified that part) and tells the Indy server to return it as the HTTP response. I've tried simply opening a TFileStream
and assigning it to Response.ContentStream
, and I've tried calling the ServeFile
method on the Response
object, and I still end up getting the same errors on the client side. The relevant part of the server code looks like this:
if lServeFile <> '' then begin //variable set by the script
if lServeFile = '***' then
response.ResponseNo := 404
else begin
response.ResponseNo := 200;
response.ServeFile(AContext, lServeFile);
end;
end;
Any experienced Indy users out there know what I'm doing wrong? Using stock Indy 10 that came with Delphi XE.
Upvotes: 2
Views: 1054
Reputation: 84550
Nevermind, the problem wasn't in Indy. Upon further debugging I eventually figured out that there were two threads both using the IdHTTP component, and sometimes they were using it at the same time. Guaranteeing that each thread would have its own IdHTTP fixed the problem.
Upvotes: 1