Connection to MongoDB Atlas with Delphi - mongodb

I'm using Delphi Seattle with Firedac and I need to connect to my base which is on MongoDB Atlas.
On Firedac I only have the option to put the server's ip, but Atlas only provides a connection string.
How to connect to MongoDB Atlas with Firedac + Delphi?
PS: I tried to get the part of the connection string that references the server address, "mongodb+srv://address.address.mongodb.net/myFirstDatabase", but delphi cannot resolve this address

I was unable to get to work as well, Instead, I used the REST API instead. eg
RESTClient1.BaseURL := 'https://data.mongodb-api.com';
RESTRequest1.Client := RESTClient1;
RESTRequest1.Resource := '/app/data-cemfo/endpoint/data/v1/action/findOne';
RESTRequest1.Method := rmPOST;
RESTRequest1.AddAuthParameter('api-key', 'FHZ....your API key',
pkHTTPHEADER, [poDoNotEncode]);
RESTRequest1.AddParameter('Content-Type', 'application/json', pkHTTPHEADER);
RESTRequest1.AddParameter('Access-Control-Request-Headers', '*',
pkHTTPHEADER);
body := TJSONObject.Create;
body.AddPair ('collection', 'mycollection');
body.AddPair ('database', 'mydbs');
body.AddPair ('dataSource', mydsrc');
subObj := TJSONObject.Create;
subObj.AddPair ('numInventory', 10);
body.AddPair ('filter', subObj);
RESTRequest1.AddBody(body);
RESTRequest1.Execute;
jsonStr := RESTResponse1.JSONValue.ToString;

Related

Sending an Email in Delphi using Indy... SSL Negotiation Failed [duplicate]

I try to send eMail with the code below (taken from http://delphiprogrammingdiary.blogspot.com/2014/12/how-to-send-email-in-delphi.html) without success.
Constantly I receive the error ("socket error 10054 connection reset by peer" twice and finally "SSL negotiation failed") at the statement "Send(IdMessage1)" although client is successfully connected with server.
procedure SendEmailClick(Sender: TObject);
var
IdMessage1: TIdMessage;
Attachmentfile: TIdAttachmentFile;
begin
// IO HANDLER SETTINGS //
With TIdSSLIOHandlerSocketOpenSSL.Create(nil) do
begin
Destination := 'mySrver.com:587';
Host := 'mySrver.com';
MaxLineAction := maException;
Port := 587;
SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
SSLOptions.Mode := sslmUnassigned;
SSLOptions.VerifyMode := [];
SSLOptions.VerifyDepth := 0;
end;
//SETTING SMTP COMPONENT DATA //
with TIdSMTP.Create(nil) do begin
Host := 'mySrver.com';
Port := 587;
Username := myMailAddress; // please change to your gmail address //
Password := myPassword;
IOHandler := TIdSSLIOHandlerSocketOpenSSL.create;
AuthType := satDefault;
UseTLS := utUseExplicitTLS;
// SETTING email MESSAGE DATA //
IdMessage1:= TIdMessage.Create(nil);
IdMessage1.Clear;
// add recipient list //
with IdMessage1.Recipients.Add do
begin
Name := 'Recipient 1';
Address := recipient1Address; // please change email address as required //
end;
//add Attachment to mail //
Attachmentfile := TIdAttachmentFile.Create(IdMessage1.MessageParts,'Τιμολόγιο 659.PDF');
IdMessage1:= TIdMessage.Create(nil);
IdMessage1.From.Address := myMailAddress; // please change to your gmail address //;
IdMessage1.Subject := 'Test Email Subject';
IdMessage1.Body.Add('Test Email Body');
IdMessage1.Priority := mpHigh;
TRY
Connect(); // no problem here. it connects always
Send(IdMessage1); // raises the error SSL negotiation failed
ShowMessage('Email sent');
Disconnect();
except on e:Exception do
begin
ShowMessage(e.Message);
Disconnect();
end;
END;
IdMessage1.Free;
IOHandler.Free;
end;
AttachmentFile.Free;
end;
Can you help me please ?
PS1. The same problem raises with any MAPI server (myServer, GMail, Yahoo etc)
PS2. The SSL DLLs are present and they are used by the same application to connect for other purpose without this problem.
You are creating a TIdSSLIOHandlerSocketOpenSSL object and configuring it, but then you discard and leak it and then create and use another TIdSSLIOHandlerSocketOpenSSL object with default settings. Get rid of the second object, use the first object instead.
You are also creating 2 TIdMessage objects, as well. Get rid of the second one.
Also, you don't need to set the Host, Port, and Destination properties on the SSLIOHandler. Connect() will handle that for you.
Try this:
procedure SendEmailClick(Sender: TObject);
var
IdSMTP: TIdSMTP;
IdMessage1: TIdMessage;
Attachmentfile: TIdAttachmentFile;
IdSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
//SETTING SMTP COMPONENT DATA //
IdSMTP := TIdSMTP.Create(nil);
try
IdSMTP.Host := 'mySrver.com';
IdSMTP.Port := 587;
IdSMTP.Username := myMailAddress; // please change to your gmail address
// Password := myPassword;
IdSMTP.AuthType := satDefault;
IdSMTP.UseTLS := utUseExplicitTLS;
// IO HANDLER Settings //
IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTP);
IdSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
IdSSL.SSLOptions.Mode := sslmUnassigned;
IdSSL.SSLOptions.VerifyMode := [];
IdSSL.SSLOptions.VerifyDepth := 0;
IdSMTP.IOHandler := IdSSL;
// SETTING email MESSAGE DATA //
IdMessage1 := TIdMessage.Create(nil);
try
// add recipient list //
with IdMessage1.Recipients.Add do
begin
Name := 'Recipient 1';
Address := recipient1Address; // please change email address as required //
end;
//add Attachment to mail //
Attachmentfile := TIdAttachmentFile.Create(IdMessage1.MessageParts, 'Τιμολόγιο 659.PDF');
IdMessage1.From.Address := myMailAddress; // please change to your gmail address //;
IdMessage1.Subject := 'Test Email Subject';
IdMessage1.Body.Add('Test Email Body');
IdMessage1.Priority := mpHigh;
try
IdSMTP.Connect();
try
IdSMTP.Send(IdMessage1);
ShowMessage('Email sent');
finally
IdSMTP.Disconnect();
end;
except
on e: Exception do
begin
ShowMessage(e.Message);
end;
end;
finally
IdMessage1.Free;
end;
finally
IdSMTP.Free;
end;
end;

SSL3_GET_RECORD Error Using Delphi XE5 RestClient

First time trying to connect to a server's HTTP API Interface using RESTClient/1.0 library installed with Delphi XE5. RestRequest.Execute raises an EIdOSSLUnderlyingCryptoError Exception:
error:1408F10B:SSL routines: SSL3_GET_RECORD:wrong version number.
Only components used are RestClient, RestRequest, and RestResponse.
from the .dfm file:
object RESTClient1: TRESTClient
Accept = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
BaseURL = 'https://intakeq.com/api/v1'
ContentType = 'ctAPPLICATION_JSON'
Params = <>
HandleRedirects = True
Left = 117
Top = 256
end
object RESTRequest: TRESTRequest
Client = RESTClient1
Params = <>
Response = RESTResponse1
Left = 185
Top = 258
end
from the .pas file
RestRequest.Params.Clear;
RestClient1.BaseURL := sBaseUrl + 'practitioners';
RestRequest.Method := TRESTRequestMethod.rmGET;
RestRequest.Params.AddItem;
RestRequest.Params[0].Kind := TRESTRequestParameterKind.pkHTTPHEADER;
RestRequest.Params[0].name := 'X-Auth-Key';
RestRequest.Params[0].Value := 'xxxxxyyyyyzzzzz';
When I put the same information into the Embarcadero REST Debugger it connected without an error.
Is there an updated REST Client Library that would work with XE5, and if so, where would I find it?
I don't see anything in the TRestClient or TRestResponse components that indicates what the SSL or TLS version is. Is that something that I need to install separately?

How to post data with a ContentType of 'multipart/form-data' in Delphi REST?

I am trying to send a request to a REST API using multipart/form-data as the content type.
I always get "HTTP/1.1 500 Internal Error" as a response.
I tried sending requests to methods that require application/x-www-form-urlencoded and had success, though.
How can I achieve getting a success response from my API using multipart/form-data?
Here is my code:
procedure TForm10.Button1Click(Sender: TObject);
var
RESTClient1: TRESTClient;
RESTRequest1: TRESTRequest;
strImageJSON : string;
Input: TIdMultipartFormDataStream;
begin
Input := TIdMultipartFormDataStream.Create;
Input.Clear;
Input.AddFormField('Email', 'tugba.xx#allianz.com.tr');
Input.AddFormField('Password', 'xxxx');
RESTClient1 := TRESTClient.Create('http://192.168.1.172:81/');
RESTRequest1 := TRESTRequest.Create(nil);
RESTRequest1.Method := TRESTRequestMethod.rmPOST;
RESTRequest1.Resource := 'api/Mobile/MobileLoginControl';
RESTRequest1.AddBody(Input,TRESTContentType.ctMULTIPART_FORM_DATA);
RESTRequest1.Client := RESTClient1;
RESTRequest1.Execute;
strImageJSON := RESTRequest1.Response.Content;
end;
Embarcadero's REST component has its own built in multipart/form-data capabilities via the TRESTRequest.AddParameter() method:
procedure TForm10.Button1Click(Sender: TObject);
var
RESTClient1: TRESTClient;
RESTRequest1: TRESTRequest;
strImageJSON : string;
begin
RESTClient1 := TRESTClient.Create('http://192.168.1.172:81/');
try
RESTRequest1 := TRESTRequest.Create(nil);
try
RESTRequest1.Method := TRESTRequestMethod.rmPOST;
RESTRequest1.Resource := 'api/Mobile/MobileLoginControl';
RESTRequest1.AddParameter('Email', 'tugba.xx#allianz.com.tr', TRESTRequestParameterKind.pkREQUESTBODY);
RESTRequest1.AddParameter('Password', 'xxxx', TRESTRequestParameterKind.pkREQUESTBODY);
RESTRequest1.Client := RESTClient1;
RESTRequest1.Execute;
strImageJSON := RESTRequest1.Response.Content;
finally
RESTRequest1.Free;
end;
finally
RESTClient1.Free;
end;
end;
You don't need to use use Indy's TIdMultiPartFormDataStream, especially when you are not using Indy's TIdHTTP.

How can I get a client's remote (targeted) addr from server side, while server listening on udp:0.0.0.0:port?

What version of Go are you using (go version)?
go version go1.9.2 linux/amd64
What did you do?
Server side, listening on udp ":11110" and print client's src ip and remote ip:
ServerAddr,err := net.ResolveUDPAddr("udp",":11110")
ServerConn, err := net.ListenUDP("udp", ServerAddr)
n,addr,err := ServerConn.ReadFromUDP(buf)
fmt.Println("Received ",string(buf[0:n]), " from ",addr, " to ", ServerConn.LocalAddr())
Client side, two clients send udp to "10.16.83.185:11110" and "127.0.0.1:11110" respectively:
ServerAddr1,err := net.ResolveUDPAddr("udp", "10.16.83.185:11110")
Conn1, err := net.DialUDP("udp", nil, ServerAddr1)
_,err := Conn1.Write(buf)
ServerAddr2,err := net.ResolveUDPAddr("udp", "127.0.0.1:11110")
Conn2, err := net.DialUDP("udp", nil, ServerAddr2)
_,err := Conn2.Write(buf)
What did you expect to see?
Received 1 from 10.16.83.185:51386 to 10.16.83.185:11110
Received 1 from 127.0.0.1:58306 to 127.0.0.1:11110
What did you see instead?
Received 1 from 10.16.83.185:51386 to 0.0.0.0:11110
Received 1 from 127.0.0.1:58306 to 0.0.0.0:11110
It seems net: UDPConn.LocalAddr() would always return "0.0.0.0:11110" instead of "10.16.83.185:11110" or "127.0.0.1:11110".
So is there any way i can achieve the "expect" result?

Delphi Seattle - Sending Post Request with custom body Responds bad Request 400

I would like to send a Post Request to a Rest Server of external Provider. I Have tried with Curl and everything works perfect. Here is the CURL Code:
curl -X POST -H 'PRODUCT-KEY: SUperL0ngAndSpecialSecretCode' -H 'Content-Type: application/json' -H 'Authorization: Basic CrytedWorksalsowellwithotherget' -i 'http://myserver:8080/rest.svc/v1.0/query' --data '{
"query":"SELECT Name from Address where name like '\''%me%'\''"
}'
In Curl Everything works fine.
I have tried for a bunch of hours to get this Code working in Delphi. At this time my code looks like this:
function GetSomeInformation: string;
var
lrestrequest: TRESTRequest;
lRestClient: TRESTClient;
lRestResponce: TRESTResponse;
begin
result := '';
lRestClient := TRESTClient.Create('http://myserver:8080/rest.svc/v1.0/query');
try
lrestrequest := TRESTRequest.Create(nil);
try
lRestResponce := TRESTResponse.Create(nil);
try
lrestrequest.Client := lRestClient;
lrestrequest.Response := lRestResponce;
lrestrequest.Method := rmPost;
lrestrequest.Params.AddItem('PRODUCT-KEY',
'SUperL0ngAndSpecialSecretCode',
TRESTRequestParameterKind.pkHTTPHEADER);
lrestrequest.Params.AddItem('Content-Type', 'application/json',
TRESTRequestParameterKind.pkHTTPHEADER);
lrestrequest.Params.AddItem('query',
ansitoutf8('SELECT Name from Address where Name like ' +
quotedstr('%me%')), TRESTRequestParameterKind.pkREQUESTBODY);
lrestrequest.Execute;
if not lRestResponce.Status.Success then
showmessage(lRestResponce.StatusText + ' ' +
inttostr(lRestResponce.StatusCode))
else
result := lRestResponce.Content;
finally
lRestResponce.Free;
end;
finally
lrestrequest.Free
end;
finally
lRestClient.Free;
end;
end;
I have no idea what to do next to get the Work done? Any ideas or ways I can Debug the problem better.
--Update
Okay I Used Wireshark to check if there are any differences between the Post commands, it look like Delphi ignores or broke my Header.
In the Wireshark snippet there is a Value Content-Type. It should be
Content-Type: application/json
But with Delphi I get
Content-Type: application%2Fjson, application/x-www-form-urlencoded
And I also miss the Procduct-Key Value.
Any Suggestions?
You have to specify the kind of request in Method property of TRESTRequest
lRESTRequest.Method := TRESTRequestMethod.rmPost
Delphi ships with code samples!
http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/REST.RESTDemo_Sample
after some Research and some Wireshark I got my Work done at least here ist the way I throw the parameters into my Request.
function GetSomeInformation: string;
var
lrestrequest: TRESTRequest;
lRestClient: TRESTClient;
lRestResponce: TRESTResponse;
begin
result := '';
lRestClient := TRESTClient.Create('http://myserver:8080/rest.svc/v1.0/query');
try
lrestrequest := TRESTRequest.Create(nil);
try
lRestResponce := TRESTResponse.Create(nil);
try
lrestrequest.Client := lRestClient;
lrestrequest.Response := lRestResponce;
RESTRequest1.Params.Clear;
RESTRequest1.Method:=rmpost;
RESTResponse1.RootElement := '';
lparam := RESTRequest1.Params.AddItem;
lparam.name := 'PRODUCT-KEY';
lparam.Value := 'SpecialKeyButWithSomeTrickyCharsLike==';
lparam.ContentType := ctNone;
lparam.Kind := pkHTTPHEADER;
//This one is Important otherwise the '==' will get url encoded
lparam.Options := [poDoNotEncode];
lparam := RESTRequest1.Params.AddItem;
lparam.name := 'data';
lparam.Value := '{"query":"' + SelectString + '"}';
lparam.ContentType := ctAPPLICATION_JSON;
lparam.Kind := pkGETorPOST;
lrestrequest.Execute;
if not lRestResponce.Status.Success then
showmessage(lRestResponce.StatusText + ' ' +
inttostr(lRestResponce.StatusCode))
else
result := lRestResponce.Content;
finally
lRestResponce.Free;
end;
finally
lrestrequest.Free
end;
finally
lRestClient.Free;
end;
end;
Thanks for Supporting!
PJM