What's wrong with a request to Dropbox? - delphi

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;

Related

How to get the request header from TNetHTTPClient

How to get the request header from TNetHTTPClient?
I have the following code:
var
netC: TNetHTTPClient;
strim: TStringStream;
aResponse: IHTTPResponse;
begin
netC := TNetHTTPClient.Create(nil);
try
strim := TStringStream.Create;
try
aResponse := netC.Get('https://google.com', strim);
finally
strim.Free;
end;
finally
netC.Free;
end;
end;

How to consume Google Safe Browsing API v4 from Delphi

I'm having trouble consuming the google safe browsing api v4. I'm sure this should be easy but its already taking me some time. I always get error 400 bad request. here is my code :
var
idHttp : TIdHTTPEx;
url : string;
slTemp : TStringList;
memoryStream : TMemoryStream;
begin
idHttp := TIdHTTPEx.Create(nil); // parent class is TIdHTTP, inherited to be able to execute HTTPS
slTemp := TStringList.Create;
memoryStream := TStringStream.Create;
try
idHttp.Request.ContentType := 'application/json';
url := 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=' + GOOGLE_SAFE_BROWSING_API_KEY + ' HTTP/1.1';
slTemp.Text := '{"client":{"clientId":"iGame","clientVersion":"1.0.0"},"threatInfo":{"threatTypes":"MALWARE","platformTypes":"WINDOWS","threatEntryTypes":"URL","threatEntries":[{"url":"http://www.hyxyg.com/default.php"},{"url":"https://jsonlint.com/"}]}}';
idHttp.Post(url, slTemp, memoryStream);
memo1.Text := memoryStream.ToString;
finally
memoryStream.Free;
slTemp.Free;
idHttp.Free;
end;
end;
I tried checking this but it is using lower version. Where did I go wrong?
EDIT
I tried using this as suggested by one of the comment, but still the same error 400 bad request. the example was OK though.
var
idHttp : TIdHTTPEx; // parent class is TIdHTTP, inherited to be able to execute HTTPS
url : string;
requestBody : TStream;
sTemp : string;
begin
url := 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=' + GOOGLE_SAFE_BROWSING_API_KEY + ' HTTP/1.1';
//url := 'https://httpbin.org/post';
idHttp := TIdHTTPEx.Create(nil);
requestBody := nil;
try
idHttp.Request.Accept := 'application/json';
idHttp.Request.ContentType := 'application/json';
sTemp := '{"client":{"clientId":"iGame","clientVersion":"1.0.0"},"threatInfo":{"threatTypes":"MALWARE","platformTypes":"WINDOWS","threatEntryTypes":"URL","threatEntries":[{"url":"http://www.hyxyg.com/default.php"},{"url":"https://jsonlint.com/"}]}}';
//sTemp := '{"日本語":42}';
requestBody := TStringStream.Create(sTemp, TEncoding.UTF8);
sTemp := idHttp.Post(url, requestBody);
memo1.Text := sTemp + sLineBreak + sLineBreak + idHttp.ResponseText;
finally
requestBody.Free;
idHttp.Free;
end;
end;
The " HTTP/1.1" at the end of the URI must be an error, try without it.

HTTPS post not working

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.

How to send messages to all registered friends

I'm facing a problem to send messages to all of my friends in the list, when I hit the send button only the first person in the list receives (2) notification messages!!!, there are 2 IDs in the list, using GCM service, why the message is not send to all?
this the codes, plz HELP...
const
YOUR_GCM_SENDERID = '123201xxx95';
YOUR_API_ID = 'AIzaSyBzvpTa-e0OnkaxxxxXfH6XroXN8QE';
procedure TForm1.Button5Click(Sender: TObject);
const
sendUrl = 'https://android.googleapis.com/gcm/send';
var
Params: TStringList;
AuthHeader: STring;
idHTTP: TIDHTTP;
SSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;
i : integer;
ItemText: string;
begin
idHTTP := TIDHTTP.Create(nil);
SslIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
idHTTP.IOHandler := SSLIOHandler;
idHTTP.HTTPOptions := [];
Params := TStringList.Create;
for i := 0 to ListView1.Items.Count-1 do
begin
ItemText := ListView1.Items[i].Text;
Params.Add('registration_id='+ ItemText);
Params.Values['data.message'] := Edit1.Text;
idHTTP.Request.Host := sendUrl;
AuthHeader := 'Authorization: key=' + YOUR_API_ID;
idHTTP.Request.CustomHeaders.Add(AuthHeader);
IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded;charset=UTF-8';
idHTTP.Post(sendUrl, Params);
end;
FreeAndNil(idHTTP);
end;
You are not managing your parameters correctly on each loop iteration. In particular, you are not overwriting the registration_id value in Params, or the Authorization value in TIdHTTP.Request.CustomHeaders. You are adding new values and keeping the previous values.
Try something more like this instead:
const
YOUR_GCM_SENDERID = '123201xxx95';
YOUR_API_ID = 'AIzaSyBzvpTa-e0OnkaxxxxXfH6XroXN8QE';
procedure TForm1.Button5Click(Sender: TObject);
const
sendUrl = 'https://android.googleapis.com/gcm/send';
var
Params: TStringList;
idHTTP: TIdHTTP;
SSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;
i : integer;
ItemText: string;
begin
idHTTP := TIDHTTP.Create(nil);
SslIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(idHTTP);
idHTTP.IOHandler := SSLIOHandler;
idHTTP.HTTPOptions := [];
Params := TStringList.Create;
for i := 0 to ListView1.Items.Count-1 do
begin
ItemText := ListView1.Items[i].Text;
Params.Clear;
Params.Add('registration_id='+ ItemText);
Params.Add('data.message=' + Edit1.Text);
idHTTP.Request.CustomHeaders.Values['Authorization'] := 'key=' + YOUR_API_ID;
IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded;charset=UTF-8';
idHTTP.Post(sendUrl, Params);
end;
end;

how to upload file to dropbox via Delphi 7?

I try to upload file into dropbox.
I use dropbox api https://www.dropbox.com/developers/reference/api#files-POST
procedure TDropbox.Upload2;
const
URL = 'https://api-content.dropbox.com/1/files/dropbox/';
var
Response: String;
Params: TIdMultipartFormDataStream;
https: TIdHTTP;
SslIoHandler: TIdSSLIOHandlerSocket;
begin
https := TIdHTTP.Create(nil);
Params := TIdMultipartFormDataStream.Create();
try
SslIoHandler := TIdSSLIOHandlerSocket.Create(https);
SslIoHandler.SSLOptions.Method := sslvTLSv1;
SslIoHandler.SSLOptions.Mode := sslmUnassigned;
https.IOHandler := SslIoHandler;
Params.AddFormField('oauth_signature_method', 'PLAINTEXT');
Params.AddFormField('oauth_consumer_key', FAppKey);
Params.AddFormField('oauth_token', FOAuth.AccessToken);
Params.AddFormField('oauth_signature', FAppSecret + '&' + FOAuth.AccessTokenSecret);
Params.AddFile('file', 'C:\test.txt', 'application/octet-stream');
https.Post(URL + 'test.txt', Params);
finally
FreeAndNil(https);
FreeAndNil(Params);
end;
end;
I got "400 Bad request".
All tokens are correct (other api works well).
How pass parameters for this api?
Try this instead:
procedure TDropbox.Upload(const AFileName: String);
const
API_URL = 'https://api-content.dropbox.com/1/files_put/sandbox/';
var
URL: String;
https: TIdHTTP;
SslIoHandler: TIdSSLIOHandlerSocket;
begin
URL := API_URL+ExtractFileName(AFileName)
+ '?oauth_signature_method=PLAINTEXT&oauth_consumer_key=' + FAppKey
+ '&oauth_token=' + FOAuth.AccessToken
+ '&oauth_signature=' + FAppSecret + '%26' + FOAuth.AccessTokenSecret;
https := TIdHTTP.Create(nil);
try
SslIoHandler := TIdSSLIOHandlerSocket.Create(https);
SslIoHandler.SSLOptions.Method := sslvTLSv1;
SslIoHandler.SSLOptions.Mode := sslmUnassigned;
https.IOHandler := SslIoHandler;
https.Post(URL, AFileName);
finally
FreeAndNil(https);
end;
end;
Use %26 instead & in oauth_signature parameter. There is two values in one parameter concated by & symbol.
Pass file via TMemoryStream.
procedure TDropbox.Upload(const AFileName: String);
const
API_URL = 'https://api-content.dropbox.com/1/files_put/sandbox/';
var
URL: String;
Stream: TMemoryStream;
ShortFileName: String;
https: TIdHTTP;
SslIoHandler: TIdSSLIOHandlerSocket;
begin
if not FileExists(AFileName) then
begin
raise EInOutError.CreateFmt('File %s not found', [AFileName]);
end;
ShortFileName := ExtractFileName(AFileName);
URL := API_URL+ShortFileName
+ '?oauth_signature_method=PLAINTEXT&oauth_consumer_key=' + FAppKey
+ '&oauth_token=' + FOAuth.AccessToken
+ '&oauth_signature=' + FAppSecret + '%26' + FOAuth.AccessTokenSecret;
https := TIdHTTP.Create(nil);
Stream := TMemoryStream.Create;
try
SslIoHandler := TIdSSLIOHandlerSocket.Create(https);
SslIoHandler.SSLOptions.Method := sslvTLSv1;
SslIoHandler.SSLOptions.Mode := sslmUnassigned;
https.IOHandler := SslIoHandler;
Stream.LoadFromFile(AFileName);
https.Post(URL, Stream);
finally
FreeAndNil(Stream);
FreeAndNil(https);
end;
end;

Resources