Stream files from server to server

Hi,
I'm trying to write 2 Sparkle servers, one is a 'Gateway' server which in turn calls the other 'Host' server when a request is received.  All works fine, but I'm now trying to work it so that if a file is requested, the file is streamed from the 'Host' server back to the 'Gateway' server and client app bit by bit in one process, rather than the entire file being first transferred to the 'Gateway' server and then onto the client app.  By doing this I should be able to show an accurate download progress bar at the client app.

Client App --> Gateway Server --> Host Server  (Request)
           <--                <--              (Response)

Here is the abbreviated code :

Gateway Server Method Code
const
  BufSize = 65536;
var
  httpClient: THttpClient;
  httpRequest: THttpRequest;
  httpResponse: THttpResponse;
  Buf: array[0..BufSize - 1] of Byte;
begin
  // Call method on the host server
  httpClient := THttpClient.Create;
  httpRequest := httpClient.CreateRequest;
  httpRequest.Uri := 'https://hostserver/api/downloadfile';
  httpRequest.Method := 'POST';
  httpRequest.SetContent(C.Request.Content);  // Pass request content from calling app
  httpResponse := nil;
  try
    httpResponse := httpClient.Send(httpRequest);
  finally
    if (httpResponse <> nil) then
    begin
      C.Response.StatusCode := httpResponse.StatusCode;
      C.Response.ContentLength := httpResponse.ContentLength;
      C.Response.ContentType := httpResponse.ContentType;
      repeat
        intBytesRead := httpResponse.ContentAsStream.Read(Buf, BufSize);
        C.Response.Content.Write(Buf, intBytesRead);
      until (intBytesRead < BufSize);
      C.Response.Close;
      httpResponse.Free;
    end;
  end;
  httpRequest.Free;
  httpClient.Free;
end;

Host Server Method Code
const
  BufSize = 65536;
var
  strFileStream: TFileStream;
  intBytesRead: Integer;
  Buf: array[0..BufSize - 1] of Byte;
begin
  // Respond with PDF file from disk location
  if (FileExists('C:\MyPDFFile.pdf') = True) then
  begin
    C.Response.StatusCode := 200;
    C.Response.ContentType := 'application/pdf';
    strFileStream := TFileStream.Create('C:\MyPDFFile.pdf', fmShareDenyNone);
    C.Response.ContentLength := strFileStream.Size;
    repeat
      intBytesRead := strFileStream.Read(Buf, BufSize);
      C.Response.Content.Write(Buf, intBytesRead);
    until (intBytesRead < BufSize);
    C.Response.Close;
    strFileStream.Free;
  end;
end;

If I call the host server method directly, the file downloads fine.  However if I call the gateway server method, the file is read from/written to the streams for so long but then just freezes (no errors, just hangs).

Is there some kind of read/write conflict causing it to freeze?  Is is possible to do what I want?

Thanks,
Jonathan

One first tip: do not call ContentAsStream twice. Read it just once and put the reference in a Stream variable and then use it from that.



ResponseStream := httpResponse.ContentAsStream;
...

       intBytesRead := ResponseStream.Read(Buf, BufSize);
        C.Response.Content.Write(Buf, intBytesRead);

Hi Wagner,


Thank you for your prompt reply.  That simple change appears to have resolved the problem!

Many thanks,
Jonathan