I have the API key and read the sparse documentation on their site, but still having trouble getting this to work so if anyone has any examples they could share then that would be great. I do not need to worry about videos or anything fancy, just a simple upload with the return information will suit my needs.
uses IdHttp;
function PostData:string;
var
url: string;
text: string;
http: TIDHttp;
valid: boolean;
param: TStringList;
begin
http := TIDHttp.Create(nil);
http.HandleRedirects := true;
http.ReadTimeout := 5000;
param := TStringList.create;
param.Clear;
param.Add('fileupload=c:\image.png');
param.Add('key=MY_API_KEY');
param.Add('tags=tag1,tag2');
valid := true;
url := 'http://www.imageshack.us/upload_api.php';
try
text := http.Post(url, param);
except
valid := false;
end;
if valid then
PostData := text
else
PostData := '';
end;
Thx.
Kevin
I pretty much did the exact same thing last nite. Thx tho.
procedure TForm1.Button1Click(Sender: TObject);
var
MPData: TIdMultiPartFormDataStream;
sResponse: string;
begin
MPData := TIdMultiPartFormDataStream.Create;
MPData.AddFile('fileupload','c:\image.png','image/png');
MPData.AddFormField('tags','testfile,flyasia');
MPData.AddFormField('public','no');
MPData.AddFormField('key','API_KEY_HERE');
sResponse := IdHTTP1.Post('http://www.imageshack.us/upload_api.php', MPData);
MPData.Free;
Memo1.Text := sResponse;
end;
Related
How can I retrieve a JSON result from a HTTPS site?
I prefer a method to no need any DLL.
It show this error:
Error connecting with SSL.error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version.
I'm using Delphi Tokyo 10.2.
function GetUrlContent(s: string): string;
var
IdHTTP1: TIdHTTP;
begin
IdHTTP1 := TIdHTTP.Create;
try
Result := IdHTTP1.Get(s);
finally
IdHTTP1.Free;
end;
end;
procedure GetData;
var
mydata, ordername: string;
begin
ordername := 'https://www.bitstamp.net/api/ticker/';
mydata := GetUrlContent(ordername);
DBMemo7.Text := mydata;
end;
I've also tried this, but it still gets the annoying SSL error:
function GetURLAsStrin1(const aurl: string): string;
var
res, req: String;
sList: TStringList;
IdHttp: TIdHttp;
begin
IdHttp := TIdHttp.Create (nil);
try
IdHttp.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHttp);
req := aurl;
res := IdHttp.Get (req);
result := res;
finally
idHttp.Free;
end;
By default, TIdSSLIOHandlerSocketOpenSSL enables only TLS 1.0. Most likely, the site in question does not support TLS 1.0 anymore. Try enabling TLS 1.1 and 1.2, eg:
function GetUrlContent(url: string): string;
var
IdHTTP1: TIdHTTP;
begin
IdHTTP1 := TIdHTTP.Create;
try
IO := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
IO.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2] // <-- add this!
IdHttp.IOHandler := IO;
Result := IdHTTP1.Get(url);
finally
IdHTTP1.Free;
end;
end;
For newer delphi versions, I would recommend using the in-built HttpClient class. It does not require any external DLLs, and works for both http or https out of the box.
uses
System.Net.HttpClient;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Text := GetUrlContent('https://www.bitstamp.net/api/ticker/');
end;
function TForm1.GetUrlContent(Url: string): string;
var
HttpClient: THttpClient;
Response: IHttpResponse;
begin
HttpClient := THTTPClient.Create;
try
Response := HttpClient.Get(URL);
Result := Response.ContentAsString();
finally
HttpClient.Free;
end;
end;
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;
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.
I have been working on this for a while and I just can't get a successful response from the server.
All documentation for this can be found at the Bittrex Exchange Wesite
The main crux of the signature bit can be found under the heading Authentication
The hashing file I have been using can be found at Fundamentals on SourceForge. It is the one at the bottom called Fundamentals Hash 4.00.15
The reason I have been using this file is a very simple one, it seems to be the only one giving me a correct answer. Or should I say, it is giving me the correct answer compared to the result this Hashing Website is giving me.
I've tried using the Indy components to generate the correct hash, but it never seems to match the value from the website. Maybe I'm not using it correctly or the right libraries or something, but I will add the example for that as well that I created.
(As I write this, I've just tested again, and it does seem like I am getting the right answer, go figure, maybe I am using a better OpenSSL library. Anyway, I will also put my INDY example down below as well).
function Test: String;
const
FAPIKey = 'APIKEY';
FAPISecret = 'APISECRET';
FURL = 'https://bittrex.com/api/v1.1/account/getbalances?apikey=%s&nonce=%d';
var
FPost, FSignature: String;
FNonce: Integer;
Response: TStringStream;
HTTP: TIdHTTP;
SSL:TIdSSLIOHandlerSocketOpenSSL;
begin
Result := '';
FNonce := DateTimeToUnix(Now);
FPost := Format(FURL, [FAPIKey, FNonce]);
HTTP := TIdHTTP.Create;
try
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
try
HTTP.IOHandler := SSL;
FSignature := SHA512DigestToHex(CalcHMAC_SHA512(FAPISecret, FPost));
HTTP.Request.CustomHeaders.AddValue('apisign', FSignature);
Response := TStringStream.Create;
try
HTTP.Get(FPost, Response);
Result := Response.DataString;
finally
Response := nil;
end;
finally
SSL := nil;
end;
finally
HTTP := nil;
end;
end;
Prior to using this version for the hashing I was only ever getting
'{"success":false,"message":"APISIGN_NOT_PROVIDED","result":null}'
I finally moved on when I worked out the custom HTTP headers and am now getting
'{"success":false,"message":"INVALID_SIGNATURE","result":null}'
Could it be something simple as an invalid nonce, or one that is too old?
Does everything look ok or am I missing some basic component settings for the INDY components?
function Test: String;
const
FAPIKey = 'APIKEY';
FAPISecret = 'APISECRET';
FURL = 'https://bittrex.com/api/v1.1/account/getbalances?apikey=%s&nonce=%d';
var
FPost, FSignature: String;
FNonce: Integer;
Response: TStringStream;
HTTP: TIdHTTP;
SSL:TIdSSLIOHandlerSocketOpenSSL;
FSHA512Hasher: TIdHMACSHA512;
begin
Result := '';
if not LoadOpenSSLLibrary then exit;
FNonce := DateTimeToUnix(Now);
FPost := Format(FURL, [FAPIKey, FNonce]);
HTTP := TIdHTTP.Create;
try
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
try
HTTP.IOHandler := SSL;
FSHA512Hasher := TIdHMACSHA512.Create;
try
FSHA512Hasher.Key := ToBytes(FAPISecret);
FSignature := Lowercase(ToHex(FSHA512Hasher.HashValue(ToBytes(FPost))));
finally
FSHA512Hasher := nil;
end;
HTTP.Request.CustomHeaders.AddValue('apisign', FSignature);
Response := TStringStream.Create;
try
HTTP.Get(FPost, Response);
Result := Response.DataString;
finally
Response := nil;
end;
finally
SSL := nil;
end;
finally
HTTP := nil;
end;
end;
I had a similar problem which I eventually figured out. I used the hmac.pas unit which I found via google search, but had to modify it to work with 10.1 Seattle (specifically IDBytes is a little different).
IMPORTANT: I also had to modify the hmac.pas unit to remove the '0x' from the front of the HexStr variation of the functions.
ALSO: I made all inputs ansistring.
My test function for this is as follows.
function TBTXClient.Get(sCommand, sAddParams: string): string;
var
sURL: string;
nonce: string;
res: string;
sec2: string;
sha: TIDHashSha256;
hmac: TIdHMAC;
hash: string;
ms: TMemoryStream;
begin
nonce := inttostr(getticker);
sURL := 'https://bittrex.com/api/v1.1/'+sCommand+'?apikey='+MY_KEY+'&nonce='+nonce+sAddParams;
hash := THMACUtils<TIDHMacSha512>.HMAC_HexStr(MY_SECRET,sURL);
//Debug.Log('url = '+sUrl);
//Debug.Log('hash = '+hash);
QuickHTTPSGet(sURL, res, 'apisign', hash);
result := res;
end;
My Modified version of the hmac.pas unit (has some new dependencies)
unit hmac;
interface
uses
System.SysUtils,
EncdDecd,
IdHMAC,
IdSSLOpenSSL,
helpers.indy,
idglobal,
IdHash;
type
localstringtype = ansistring;
THMACUtils<T: TIdHMAC, constructor> = class
public
class function HMAC(aKey, aMessage: localstringtype): TIdBytes;
class function HMAC_HexStr(aKey, aMessage: localstringtype): localstringtype;
class function HMAC_Base64(aKey, aMessage: localstringtype): localstringtype;
end;
implementation
class function THMACUtils<T>.HMAC(aKey, aMessage: localstringtype): TIdBytes;
var
_HMAC: T;
begin
if not IdSSLOpenSSL.LoadOpenSSLLibrary then Exit;
_HMAC:= T.Create;
try
_HMAC.Key := AnsiStringToIDBytes(aKey);
Result:= _HMAC.HashValue(AnsiStringToIDBytes(aMessage));
finally
_HMAC.Free;
end;
end;
class function THMACUtils<T>.HMAC_HexStr(aKey, aMessage: localstringtype): localstringtype;
var
I: Byte;
begin
Result:= '';//'0x';
for I in HMAC(aKey, aMessage) do
Result:= Result + IntToHex(I, 2);
end;
class function THMACUtils<T>.HMAC_Base64(aKey, aMessage: localstringtype): localstringtype;
var
_HMAC: TIdBytes;
begin
_HMAC:= HMAC(aKey, aMessage);
Result:= EncodeBase64(_HMAC, Length(_HMAC));
end;
end.
You'll probably also want this helper unit.
unit helpers.indy;
interface
uses
idglobal, types, classes, sysutils, typex;
function TBytesToIDBytes(b: TBytes): TIDBytes;
function AnsiStringToIDBytes(a: ansistring): TIDBytes;
implementation
function TBytesToIDBytes(b: TBytes): TIDBytes;
var
t: ni;
begin
setlength(result, length(b));
for t := low(b) to high(b) do
result[t] := b[t];
end;
function AnsiStringToIDBytes(a: ansistring): TIDBytes;
var
t: ni;
begin
setlength(result, length(a));
for t := 0 to length(a)-1 do
result[t] := ord(a[STRZ+t]);
end;
And this cheesy function, which I borrowed from my own https unit shows how to handle the header params.
function QuickHTTPSGet(sURL: ansistring; out sOutREsponse: string;
addHead: string =''; addHeadValue: string = ''): boolean;
var
htp: IXMLhttprequest;
begin
htp := ComsXMLHTTP30.create();
try
htp.open('GET', sURL, false, null, null);
if addHead <> '' then
htp.setRequestHeader(addHead, addHeadValue);
htp.send('');
result := htp.status = 200;
if result then
sOutREsponse := htp.responsetext
else
soutResponse := 'error '+inttostr(htp.status);
except
on e: Exception do begin
result := false;
sOutResponse := 'error '+e.message;
end;
end;
end;
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;