Delphi HTTP Post JSON

delphi, indy, json

Solution

`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;

Problem

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: - Post JSON data to RESTful datasnap server from delphi client - Sending a JSON encoded object using Indy and Delphi - Delphi TIdhttp Post JSON? - Delphi TIdhttp Post JSON? - What’s the simplest way to call Http POST url using Delphi? 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 ```

Original source

Related problems