Luiz Alves
Luiz Alves

Reputation: 2645

Converting C#/.NET, ruby or Python code to Delphi Indy v10

I need to use a service of messages called pushover (https://pushover.net/) and I am trying to convert the sample code posted in other programming language to use with Delphi XE7/Indy10.

I have used the following code in Delphi and I always get: "HTTP/1.1 400 Bad Request".

Procedure SendMessage;
var ...
begin 
  IdHTTP:=TIdHTTP.Create(nil);
  IdHTTP.HandleRedirects:=True;
  Resp := TStringStream.Create('', TEncoding.UTF8);
  sURL      :='https://api.pushover.net/1/messages.json?';
  postdata := 'token=aiJSSS3167JLrPAAye9srpEz27RDJ2Rm&user=uDXXXFCASKgqLGzzuJLMdf2Ymyr5dP&message=This is a Text&title=Test'

  sFPRvalue := idhttp.URL.ParamsEncode(postdata,IndyTextEncoding_UTF8);
  Sl:=IntToStr(length(postdata));

  s:=sURL+sFPRvalue;

  try
    SSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    try
      SSL1.SSLOptions.Method := sslvSSLv23;
      IdHTTP.IOHandler := SSL1;
      IdHttp.Request.CustomHeaders.AddValue('Content-Type','application/x-www-form-urlencoded');
      IdHttp.Request.CustomHeaders.AddValue('Content-Length',sl);
      strres := IdHTTP.Post(s,Resp);
    finally
      SSl1.Free;
    end;
  finally
    Resp.Free;
  end;
end;

Here are the samples posted by owner service:

C#

var parameters = new NameValueCollection {
    { "token", "APP_TOKEN" },
    { "user", "USER_KEY" },
    { "message", "hello world" }
};

using (var client = new WebClient())
{
    client.UploadValues("https://api.pushover.net/1/messages.json", parameters);
}

Python

import http.client, urllib
conn = http.client.HTTPSConnection("api.pushover.net:443")
conn.request("POST", "/1/messages.json",
  urllib.parse.urlencode({
    "token": "APP_TOKEN",
    "user": "USER_KEY",
    "message": "hello world",
  }), { "Content-type": "application/x-www-form-urlencoded" })
conn.getresponse()

Ruby

require "net/https"

url = URI.parse("https://api.pushover.net/1/messages.json")
req = Net::HTTP::Post.new(url.path)
req.set_form_data({
  :token => "APP_TOKEN",
  :user => "USER_KEY",
  :message => "hello world",
})
res = Net::HTTP.new(url.host, url.port)
res.use_ssl = true
res.verify_mode = OpenSSL::SSL::VERIFY_PEER
res.start {|http| http.request(req) }

Upvotes: 0

Views: 592

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597941

The problem is that you are calling the wrong overloaded version of TIdHTTP.Post(), and you are formatting its parameter data the wrong way. You need to use the overloaded version of Post() that takes a TStrings as input, let it encode the post data for you, and return the response data as a String, eg:

IdHTTP := TIdHTTP.Create(nil);
try
  SSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
  SSL1.SSLOptions.Method := sslvTLSv1;
  IdHTTP.IOHandler := SSL1;

  IdHTTP.HandleRedirects := True;
  IdHTTP.Request.ContentType := 'application/x-www-form-urlencoded';

  PostData := TStringList.Create;
  try
    PostData.Add('token=aiJSSS3167JLrPAAye9srpEz27RDJ2Rm');
    PostData.Add('user=uDXXXFCASKgqLGzzuJLMdf2Ymyr5dP');
    PostData.Add('message=This is a Text');
    PostData.Add('title=Test');

    try
      strres := IdHTTP.Post('https://api.pushover.net/1/messages.json', PostData);
    except
      on E: EIdHTTPProtocolException do
      begin
        if (E.ErrorCode div 100) = 4 then
        begin
          // use E.ErrorMessage as needed...
        end else begin
          raise;
        end;
      end;
    end;
  finally
    PostData.Free;
  end;
finally
  IdHTTP.Free;
end;

Upvotes: 2

Related Questions