11
votes

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
2
When the request has been sent successfully, what does "just won't work" mean then? What is it that you expect to happen? - JensG
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. - FoggyDay
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. - Remy Lebeau
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. - Jared Sherman
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. - Ken White

2 Answers

11
votes

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;
1
votes

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;