13

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:

  • Delphi 7
  • Indy 10.0.52
  • ulkJSON.pas v1.07

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
8
  • When the request has been sent successfully, what does "just won't work" mean then? What is it that you expect to happen? Commented Jun 3, 2014 at 22:18
  • 1
    1) JSON is just a text string: Tidhttp should work fine, 2) You should probably set "content-type" in the HTTP header to "text/json" or "application/json", 3) You should definitely use a tool like Wireshark or Fiddler2 to see if your JSON is getting sent, and how (or if) the server is responding. Commented Jun 3, 2014 at 22:33
  • 2
    Please show the actual code that is not working for you. Don't just direct us to look at other people's examples. Show the code that YOU are actually using. You likely did not incorporate those examples into your project correctly. Commented Jun 3, 2014 at 23:06
  • I set the content type to match the examples listed in the posts. There will be a response JSON message that I can parse to get a token. That token can then be used to make other calls to the site. With Fiddler running no messages showed up for me. Looks like I'm not even getting a message out. Commented Jun 3, 2014 at 23:09
  • If you want help with your code that isn't working, it's important that you post the code that isn't working. It's also hard to tell what you've done wrong with "configuring your IdHTTP" when you don't show how you're configuring it. If you want help here, you'll need to include the relevant information. It's pointless asking us to speculate on what might be wrong, when you can include what you're doing and we can try and specifically help you. Please edit your question and add the information there, where it can be properly formatted and people can easily find it. Thanks. Commented Jun 3, 2014 at 23:10

2 Answers 2

12

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;
Sign up to request clarification or add additional context in comments.

12 Comments

It looks like my version of Indy is different from yours. I don't have a HTTP1.Request.CharSet property and if I don't set a a IOHandler then mine will get this: Error on request: IOHandler value is not valid
10.0.52 is a VERY old version. The current version is 10.6.0. As for the 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.
The CharSet property was added in 10.5.7 back in 2010.
If I can convince my work to upgrade Indy do you know if any of the version have issues with Delphi 7? I see on their dev snapshot page that there are a few version of 10.6.0 Indy 10.6.0 - XE6 RTM/ Indy 10.6.0 - XE5 RTM/ Indy 10.6.0 - XE4 RTM/ Indy 10.5.8 - XE2 RTM/ Indy 10.5.7 - XE RTM/ Indy 10.5.5 - RS2010 RTM/
Those are tags so we know which SVN revision of Indy was shipped with each major Delphi release in recent years. Indy itself still supports Delphi versions going all the way back to Delphi 5.
|
1

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;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.