HTTPS post not working - delphi

I'm doing a HTTPS post with this code to azurewebsites.
http://MYAPP.azurewebsites.net/api/MYFUNC
I'm currently using this code:
procedure TForm1.OriginalTest();
var
lHTTP: TIdHTTP;
HTTPResult: string;
RequestBody: TStream;
URL: String;
Body: string;
IOHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
lHTTP := TIdHTTP.Create;
try
Body := '{}';
RequestBody := TStringStream.Create(Body, TEncoding.UTF8);
lHTTP.Request.Accept := '';
lHTTP.Request.UserAgent := '';
lHTTP.Request.CustomHeaders.Add('x-functions-key:<your api key>');
lHTTP.ConnectTimeout := 24000;
lHTTP.ReadTimeout := 24000;
IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
IOHandler.SSLOptions.Method := sslvTLSv1_2;
lHTTP.IOHandler := IOHandler;
try
URL := 'https://<yourapp>.azurewebsites.net/api/<funcname>';
HTTPResult := lHTTP.Post(url, RequestBody);
Memo1.Lines.Add(HTTPResult);
except
on E:Exception do
begin
Memo1.Lines.Add(Format('Error sending data. Error: %s', [E.Message] ));
end;
end;
finally
lHTTP.Free;
RequestBody.Free;
end;
end;
For whatever reason, this code gives me the following error:
Error sending data. Error: Socket Error # 10054 Connection reset by peer.
I tried making a simple HTTPS Post using .NET with HttpWebRequest , and it works fine. What am I doing wrong here?

I just gave up and used WinApi.WinInet instead.

Related

Using Indy SMTP and HTTPS across DLL

If I send a basic email via TidSMTP (ignore the try/finally blocks, this is just an example):
var
SMTP : TidSMTP;
MSG : TidMessage;
LHandler : TIdSSLIOHandlerSocketOpenSSL;
begin
SMTP := TIdSMTP.Create(nil);
Msg := TIdMessage.Create(nil);
LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
Msg.Body.Text := 'Test Simple Email';
Msg.Subject := 'Test Simple Email Subject';
Msg.From.Address := 'test#domain.com';
MSG.ContentType := 'text/html';
Msg.Priority := mpHighest;
SMTP.Host := 'smtp.server.com';
SMTP.Username := 'test#domain.com';
SMTP.Port := 587;
SMTP.Password := 'testPassword';
SMTP.IOHandler := LHandler;
try
with Msg.Recipients.Add do
begin
Address := 'test#domain.com'
end;
try
SMTP.Connect;
SMTP.Send(Msg);
SMTP.Disconnect;
finally
Screen.Cursor := crDefault;
end;
finally
LHandler.Free;
Msg.Free;
SMTP.Free;
end;
And then call a DLL which makes an HTTPS request via TidHTTP:
var
myHTTP : TIdHTTP;
LHandler: TIdSSLIOHandlerSocketOpenSSL;
FJSON : String;
GetStr : String;
begin
GetStr := URLEncode('6421 E ROAD, GREELEY,CO,80634');
GetStr := 'https://maps.googleapis.com/maps/api/geocode/json?address=' + GetStr + '&key=' + 'someGoogleAPIKey';
myHTTP := TIdHTTP.Create(nil);
try
LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
LHandler.SSLOptions.SSLVersions := [sslvTLSv1_2];
myHTTP.IOHandler := LHandler;
try
FJSON := myHTTP.Get(GetStr);
except
on E: Exception do
begin
raise
end;
end;
showmessage(FJSON);
finally
LHandler.Free;
end;
finally
myHTTP.Free;
end;
And then try the email a second time, I'm receiving the error "Error creating SSL context", specifically "error:140A90F1:SSL routines: SSL_CTX_new: unable to load ssl2 md5 routines"
If I change this slightly by feeding in the TidSMTP component into the TidSSLIOHandlerSocketOpenSSL Create method:
LHandler := TIdSSLIOHandlerSocketOpenSSL.Create(SMTP);
...
//SMTP.IOHandler := lHandler;
Then it works. But I can't use that. This is a completely stripped down version of the problem. In reality I'm using ReportBuilder (digital-metaphors) to send the email, and they don't allow one to send in the TidSMTP during the TidSSLIOHandlerSocketOpenSSL Create method.
This error does not happen when the HTTPS request is made within the same program as the SMTP request. Only when crossing into a DLL. This error does not happen if I do the HTTPS/DLL first and then SMTP. There is something happening during the first SMTP call that sets it up for the error down the road.
Should I take this over to Digital-Metaphors, or is there something going on during the HTTPS/DLL call that I could be doing better?

Login to secured website programmatically

I have setup the help for my Firemonkey app on a password-secured website hosted by site44.com.
Passing the password as part of the URL doesn't work with certain browsers because they consider it insecure. So I tried the following code. This doesn't work either. Function Login returns the login HTML of the website but does not actually log me in. Can you tell me where my code is wrong?
procedure TMyMainForm.OnlineHelp1Execute(Sender: TObject);
function Login: string;
var
IdHTTP: TIdHTTP;
Request: TStringList;
Response: TMemoryStream;
begin
Result := '';
try
Response := TMemoryStream.Create;
try
Request := TStringList.Create;
try
Request.Add('password=mypassword');
IdHTTP := TIdHTTP.Create;
try
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
IdHTTP.AllowCookies := True;
IdHTTP.HandleRedirects := False;
IdHTTP.Post('https://mysite.site44.com/', Request, Response);
Result := IdHTTP.Get('https://mysite.site44.com/');
finally
IdHTTP.Free;
end;
finally
Request.Free;
end;
finally
Response.Free;
end;
except
on E: Exception do
ShowMessage(E.Message);
end;
end;
begin
ShowMessage(Login);
end;

What's wrong with a request to Dropbox?

I have valid access token to Dropbox account (API v2), Delphi 7 and, Indy 10.
When I try to use this token I have exception 'HTTP/1.1 400 Bad Request'.
I look at Dropbox API v2 and can't understand:
what's wrong with the request?
procedure TDropboxSaveFilterForm.TestButtonClick(Sender: TObject);
const
AccessToken = 'Hq7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
var
IdHTTP: TIdHTTP;
Source: TStringList;
Res, URL: WideString;
begin
Source := TStringList.Create;
IdHTTP := TIdHTTP.Create(nil);
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
URL := 'https://api.dropboxapi.com/2/files/list_folder' + '?' +
'Authorization=Bearer ' + AccessToken;
Res := IdHTTP.Post(URL, Source);
Source.Free;
end;
New code with the header, error the same :-(.
According to Indy: Request Specifies the header values to send to the HTTP server.
procedure TDropboxSaveFilterForm.TestHeaderButtonClick(Sender: TObject);
const
AccessToken = 'Hq7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
URL = 'https://api.dropboxapi.com/2/files/list_folder';
var
IdHTTP: TIdHTTP;
Source: TStringList;
Head, Res: WideString;
Stream: TMemoryStream;
begin
Source := TStringList.Create;
IdHTTP := TIdHTTP.Create(nil);
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
Head := 'Authorization: Bearer ' + AccessToken;
Stream := TMemoryStream.Create;
Stream.Write(Head, Length(Head));
Stream.Position := 0;
IdHTTP.Request.Source := Stream;
Res := IdHTTP.Post(URL, Source);
Source.Free;
end;
You are trying to put the authorization data in the request URL and in the request body. You should put it in the request headers instead. Use the TIdHTTP.Request.CustomHeaders property to send a custom Authorization header value, eg:
procedure TDropboxSaveFilterForm.TestHeaderButtonClick(Sender: TObject);
const
AccessToken = 'Hq7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
URL = 'https://api.dropboxapi.com/2/files/list_folder';
var
IdHTTP: TIdHTTP;
Source: TStringStream;
Res: String;
Stream: TMemoryStream;
begin
Source := TStringStream.Create('JsonParamsHere');
try
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + AccessToken;
IdHTTP.Request.BasicAuthentication := False;
IdHTTP.Request.ContentType := 'application/json';
Res := IdHTTP.Post(URL, Source);
finally
IdHTTP.Free;
end;
finally
Source.Free;
end;
end;

Delphi idhttp long URL parameter is splittet automatically

I am using indys idhttp to submit an URL (post)
Procedure submit_post(url_string,EncodedStr:string;amemo:TMemo);
var
aStream: TMemoryStream;
Params: TStringStream;
begin
aStream := TMemoryStream.create;
Params := TStringStream.create('');
try
with Fmain.IdHTTP1 do
begin
Params.WriteString(EncodedStr);
Request.ContentType := 'application/x-www-form-urlencoded';
Request.Charset := 'utf-8';
try
Response.KeepAlive := False;
Post(url_string, params, aStream);
except
on E: Exception do
begin
Screen.Cursor := crDefault;
exit;
end;
end;
end;
aStream.WriteBuffer(#0' ', 1);
aStream.Position := 0;
amemo.Lines.LoadFromStream(aStream);
Screen.Cursor := crDefault;
finally
aStream.Free;
Params.Free;
end;
end;
It works like a charm for me. I am trying to submit a URL (post) with a parameter containing 300 chars, but will be splittet automatically by adding an "&" every 90 chars. So the server only receives 90 chars instead of 300.
How can I submit an URL with a 300 character parameter without this automatic separation ?
function SubmitPost(Params:String): string;
const
URL= 'http://xxxx.com/register.php?';
var
lHTTP: TIdHTTP;
Source,
ResponseContent: TStringStream;
I:Integer;
begin
lHTTP := TIdHTTP.Create(nil);
lHTTP.Request.ContentType := 'text/xml';
lHTTP.Request.Accept := '*/*';
lHTTP.Request.Connection := 'Keep-Alive';
lHTTP.Request.Method := 'POST';
lHTTP.Request.UserAgent := 'OS Test User Agent';
Source := TStringStream.Create(nil);
ResponseContent:= TStringStream.Create;
try
try
lHTTP.Post(URL+Params, Source, ResponseContent);
Result := ResponseContent.DataString;
except
//your exception here
end;
finally
lHTTP.Free;
Source.Free;
ResponseContent.Free;
end;
end;
Usage
mmo1.Text := SubmitPost('Username=xxxx&Password=xxxx');
I found the mistake. My Post function works perfectly, but the URL is built by params coming from a memo line. With "WantReturns = FALSE", I can build a URL with the maximum line length of the memo. I guess 1024 characters per line which is okay for me.

Log in to website from Delphi

I would ask if someone was kind enough to explain to me how to login at webpage from Delphi app. All the examples I've found here have proved useless to me or I'm doing something wrong. I'm tired of the search and the code that does not work.
There is no error message, I even get page code into Memo but seems it's code from login page (not account [dashboard] page) - seems this code can't pass auth at all and I don't know why.
What is wrong in this code :
procedure Login;
var
HTTP: TIdHTTP;
Param: TStringList;
S: String;
begin
HTTP := TIdHTTP.Create(nil);
HTTP.CookieManager := Main_Form.CookieManager;
Param := TStringList.Create;
Param.Clear;
Param.Add('login=example');
Param.Add('password=example');
try
HTTP.Get ('http://www.filestrum.com/login.html');
HTTP.Post('http://www.filestrum.com/login.html', Param);
S := HTTP.Get ('http://www.filestrum.com/?op=my_account');
Main_Form.Memo2.Lines.Add(S);
finally
HTTP.Free;
Param.Free;
end;
end;
or with this version :
procedure Login;
var
HTTP: TIdHTTP;
S: String;
begin
HTTP := TIdHTTP.Create(nil);
HTTP.CookieManager := Main_Form.CookieManager;
HTTP.Request.BasicAuthentication := True;
HTTP.Request.Username := 'example';
HTTP.Request.Password := 'example';
HTTP.AllowCookies := True;
HTTP.HandleRedirects := True;
S := HTTP.Get ('http://www.filestrum.com/?op=my_account');
Main_Form.Memo2.Lines.Add(S);
end;
Used Delphi XE2 and there is no way to make this code running and login. It's same with XE3 demo. As I said, I'm really tired searching some solution, waste days into it and nothing.
Please guys, some help here. Really need it.
Try something like this:
function Login: string;
var
IdHTTP: TIdHTTP;
Request: TStringList;
Response: TMemoryStream;
begin
Result := '';
try
Response := TMemoryStream.Create;
try
Request := TStringList.Create;
try
Request.Add('op=login');
Request.Add('redirect=http://www.filestrum.com');
Request.Add('login=example');
Request.Add('password=example');
IdHTTP := TIdHTTP.Create;
try
IdHTTP.AllowCookies := True;
IdHTTP.HandleRedirects := True;
IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
IdHTTP.Post('http://www.filestrum.com/', Request, Response);
Result := IdHTTP.Get('http://www.filestrum.com/?op=my_account');
finally
IdHTTP.Free;
end;
finally
Request.Free;
end;
finally
Response.Free;
end;
except
on E: Exception do
ShowMessage(E.Message);
end;
end;

Resources