Jump to content
adeptusgb

"EIdSocketError" on S3 file upload - Delphi 7

Recommended Posts

Posted (edited)

Hello,

I'm having trouble trying to upload files to my s3 bucket in my Delphi 7 application. I have a python api that generates a presigned url for putting files, and it works perfectly. I am able to send the files to the s3 bucket through Postman, setting the body as binary and the url as the presigned s3 url.

 

Now for the Delphi part, basically what my code does is get the presigned url and send a PUT to it with the TFileStream of a file selected by the user.

var
  SignedURL    ,
  res          ,
  filePath     : string;
  httpClient   : TIdHTTP;
  SSLIOHandler : TIdSSLIOHandlerSocketOpenSSL;
  jsonRes      : ISuperObject;
  fileStream   : TFileStream
begin
  filePath  := 'path/to/file.pdf'; // file selected by user in OpenDialog
  SignedURL := 'signedUrlGeneratedByPythonCode'; // response from calling my python web api

  fileStream := TFileStream.Create(filePath, fmOpenRead or fmShareDenyNone); 
  httpClient := TIdHTTP.Create;
  httpClient.Request.Accept := 'application/json';

  SSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  SSLIOHandler.SSLOptions.Method := sslvTLSv1_2;
  httpClient.IOHandler := SSLIOHandler;
  try
    res := httpClient.Put(url, fileStream);
    jsonRes := SO(res);
  finally
    fileStream.Free;
    httpClient.Free;
    SSLIOHandler.Free;
  end;
end;

With this code I get an access violation at the res := httpClient.Put(url, fileStream); if I run just the Put on runtime, without assigning the response to a variable I get a "Delphi exception EIdSocketError at $2646F905".

Removing the SSLIOHandler, I get a "Socket Error #10054 Connection reset by peer.".

 

I'm still a beginner in coding (and very new with Delphi), so I can't pinpoint what exactly could be the problem. I assume it's either because of AWS using HTTPS (although the python api also uses HTTPS and I don't need to set a SSLIOHandler to make a request to it) and my SSL/TLS not working properly or I'm passing the file binaries in the wrong format and the AWS server is refusing the connection instantly.

Using: Delphi 7, Indy 10

Thanks in advance, any help would be very much appreciated.

 

Edited by adeptusgb

Share this post


Link to post
1 hour ago, adeptusgb said:

res := httpClient.Put(url, fileStream);

url should be SignedURL instead.

1 hour ago, adeptusgb said:

With this code I get an access violation at the res := httpClient.Put(url, fileStream);

Is it an actual EAccessViolation, or some other exception?  I see nothing in the code you have shown that should be causing an EAccessViolation.

1 hour ago, adeptusgb said:

if I run just the Put on runtime, without assigning the response to a variable I get a "Delphi exception EIdSocketError at $2646F905".

What is the complete error message?  There should be more detail about the exact socket error that actually occurred.

1 hour ago, adeptusgb said:

Removing the SSLIOHandler, I get a "Socket Error #10054 Connection reset by peer.".

Sure, since you are disabling use of TLS.  You can't connect to an HTTPS url without TLS.

1 hour ago, adeptusgb said:

I assume it's either because of AWS using HTTPS ... and my SSL/TLS not working properly

Other then the url issue mentioned above, the rest of the code looks fine.  Do you have OpenSSL v1.0.2 DLLs installed alongside your app?

1 hour ago, adeptusgb said:

or I'm passing the file binaries in the wrong format and the AWS server is refusing the connection instantly.

More likely, either you are posting to the wrong URL, or there is a problem with the TLS handshake.  Have you tried using a packet sniffer, like Wireshark, to look at the raw TCP data for any differences between the postman handshake and the TIdHTTP handshake?  If the handshake is working, have you tried comparing Postman's HTTP request to TIdHTTP's HTTP request for differences?

Share this post


Link to post
20 minutes ago, Remy Lebeau said:

url should be SignedURL instead.

My bad, I simplified the code a bit to make it more readable for the post and forgot to change the name of this variable. In the actual code it's the correct URL.

41 minutes ago, Remy Lebeau said:

Is it an actual EAccessViolation, or some other exception?  I see nothing in the code you have shown that should be causing an EAccessViolation.

I think the access violation was actually happening at jsonRes := SO(res); but it doesn't matter anyway because the AWS endpoint doesn't have a response body, so I took this part out of the code.

46 minutes ago, Remy Lebeau said:

Other then the url issue mentioned above, the rest of the code looks fine.  Do you have OpenSSL v1.0.2 DLLs installed alongside your app?

That was the problem. The project only had OpenSSL v0.9.8.33 DLLs, I noticed there were some OpenSSL DLLs but didn't check if the version supported TLS 1.2 :classic_blink:

49 minutes ago, Remy Lebeau said:

Have you tried using a packet sniffer, like Wireshark, to look at the raw TCP data for any differences between the postman handshake and the TIdHTTP handshake?

I actually had no idea about this software, looks very helpful and I'll be surely checking it out!

 

Thank you so much for the help, I'm sending my files to S3 with no problems now! :classic_biggrin:

Share this post


Link to post
1 hour ago, adeptusgb said:

That was the problem. The project only had OpenSSL v0.9.8.33 DLLs, I noticed there were some OpenSSL DLLs but didn't check if the version supported TLS 1.2 :classic_blink:

Then you should have gotten an exception like EIdOSSLCouldNotLoadSSLLibrary from TIdHTTP when it failed to load the necessary TLS functions from the DLLs.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×