I am sure I'm doing something wrong here. I've followed every example I can find on stackoverflow and still haven't gotten this to work in my environment. I'd love to update my controls and environment, but I'm currently locked in with what I have.
I am using:
I need to send this JSON to a URL:
"auth": {
"applicationId": "appID",
"applicationPassword": "pwd",
"accountId": "acct",
"userId": "dev"
}
There isn't anything terribly crazy about this, but when I try to post my request I tend to get a message that the request was Closed Gracefully. CheckIsReadable in IDSocketHandle.pas has Handleallocated = false. I'm not sure what I've done wrong in configuring my IdHTTP, but it just won't work.
I have tried examples from all these questions and several more, but none of these approaches seem to work for me:
Any tips would be greatly appreciated.
The current variant looks like this:
procedure Tformmaintestbed.btnJSONSendClick(Sender: TObject);
var
code: Integer;
sResponse: string;
JsonToSend: TStringStream;
begin
JsonToSend := TStringStream.Create(
'{"auth": {"applicationId": "' + edApplication.text +
'","applicationPassword": "' + edpassword.text +
'","accountId": "' + edaccount.text +
'","userId": "' + edUser.text +
'"}}');
try
HTTP1.Request.ContentType := 'application/json';
HTTP1.Request.ContentEncoding := 'utf-8';
memoRequest.lines.clear;
memoRequest.lines.add(JsonToSend);
try
sResponse := HTTP1.Post(cbAddress.text, JsonToSend);
except
on E: Exception do
ShowMessage('Error on request: '#13#10 + e.Message);
end;
memoResponse.lines.clear;
memoresponse.lines.add(sResponse);
finally
JsonToSend.Free();
end;
end;
The idHTTP component is current set like this:
object HTTP1: TIdHTTP
IOHandler = IdSSLIOHandlerSocketOpenSSL1
AuthRetries = 0
AuthProxyRetries = 0
AllowCookies = True
HandleRedirects = True
ProxyParams.BasicAuthentication = False
ProxyParams.ProxyPort = 0
Request.ContentEncoding = 'utf-8'
Request.ContentLength = -1
Request.ContentRangeEnd = 0
Request.ContentRangeStart = 0
Request.ContentRangeInstanceLength = 0
Request.ContentType = 'application/json'
Request.Accept = 'application/json'
Request.BasicAuthentication = False
Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
HTTPOptions = [hoForceEncodeParams]
Left = 564
Top = 120
end
HTTP1.Request.ContentEncoding should be HTTP1.Request.CharSet instead. UTF-8 is a charset encoding, not a content encoding. And then make sure your JSON data is actually encoded to UTF-8 before posting it. If you are using ASCII characters, the TStringStream code you showed is fine. But if you are using non-ASCII Characters, you need to encode them, such as with Utf8Encode(). TIdHTTP does not encode TStream data, it is sent as-is.
Procedure Tformmaintestbed.btnJSONSendClick(Sender: TObject);
var
Json: string;
sResponse: string;
JsonToSend: TStringStream;
begin
Json := '{"auth": {"applicationId": "' + edApplication.text +
'","applicationPassword": "' + edpassword.text +
'","accountId": "' + edaccount.text +
'","userId": "' + edUser.text +
'"}}';
memoRequest.Text := Json;
JsonToSend := TStringStream.Create(Utf8Encode(Json)); // D2007 and earlier only
//in D2009 and later, use this instead:
//JsonToSend := TStringStream.Create(Json, TEncoding.UTF8);
try
HTTP1.Request.ContentType := 'application/json';
HTTP1.Request.CharSet := 'utf-8';
try
sResponse := HTTP1.Post(cbAddress.Text, JsonToSend);
except
on E: Exception do
ShowMessage('Error on request: '#13#10 + e.Message);
end;
finally
JsonToSend.Free;
end;
memoResponse.Text := sResponse;
end;
Alternatively:
Procedure Tformmaintestbed.btnJSONSendClick(Sender: TObject);
var
Json: string;
sResponse: string;
JsonToSend: TMemoryStream;
begin
Json := '{"auth": {"applicationId": "' + edApplication.text +
'","applicationPassword": "' + edpassword.text +
'","accountId": "' + edaccount.text +
'","userId": "' + edUser.text +
'"}}';
memoRequest.Text := Json;
JsonToSend := TMemoryStream.Create;
try
WriteStringToStream(JsonToSend, Json, enUTF8);
JsonToSend.Position := 0;
HTTP1.Request.ContentType := 'application/json';
HTTP1.Request.CharSet := 'utf-8';
try
sResponse := HTTP1.Post(cbAddress.Text, JsonToSend);
except
on E: Exception do
ShowMessage('Error on request: '#13#10 + e.Message);
end;
finally
JsonToSend.Free;
end;
memoResponse.Text := sResponse;
end;
IOHandler error, that only happens if you request an HTTPS url and do not have an SSL IOHandler assigned. That requirement is still true in the latest version. - Remy Lebeau
CharSet property was added in 10.5.7 back in 2010. - Remy Lebeau
TIdHash128 was only being used with the TIdMessageDigest... classes (or did you implement your own 128bit hash?). Those classes still exist. If that is not what you are looking for, then please show your actual code that no longer works, and I will show the newer equivalent. - Remy Lebeau
TIdHash has various Hash...AsHex() methods, such as HashStringAsHex(), eg: function EncryptMD5(sString: String): String; begin with TIdHashMessageDigest5.Create do try Result := UpperCase(HashStringAsHex(sString)); finally Free; end; end; - Remy Lebeau
HashString...() methods all have encoding parameters that you need to take into account if you are hashing non-ASCII characters. A hash operates on raw bytes, not on characters. A String has to be charset-encoded to a byte array before it can then be hashed, so you have to specify the charset to use for that encoding. Your code above does not do that, so Indy's default encoding (7bit ASCII by default) will be used, unless you specify otherwise. - Remy Lebeau
Please try this:
procedure TForm1.Button1Click(Sender: TObject);
var
s: String;
Resp_Json: string;
Req_Json:TStream;
begin
s:='state=1';
s:=s+'&kind=0';
s:=s+'&tblid=0';
Req_Json:=TstringStream.Create(s);
Req_Json.Position:=0;
try
IdHTTP1.Request.UserAgent:='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36';
IdHTTP1.Request.Accept := 'application/json, text/javascript, */*; q=0.01';
IdHTTP1.Request.ContentType := 'application/x-www-form-urlencoded; charset=UTF-8';
IdHTTP1.Request.CharSet:='utf-8';
Resp_Json:=IdHTTP1.Post('http://[your URL]', Req_Json);
finally
Req_Json.Free;
end;
memo1.Lines.Add(IdHTTP1.ResponseText);
memo1.Lines.Add(Resp_Json);
end;