Bad Request in Post idHTTP with Delphi

Asked

Viewed 2,576 times

1

I am trying to communicate with the API of an Ecommerce and all dozens of attempts that did only receive as response "HTTP request failed 400 HTTP/1.1 400 Bad Request".

So I have been informed I have to send a post and on body inform consumer_key, consumer_secret and code.

One important thing is that I have to pass this information on the body of the post and not as parameters.

I tested by Postman using x-www-form-urlencoded, informed the url and put the above information in Body and it worked.

At Delphi I’m sending in the form below:

lHTTP:= TIdHTTP.Create(nil);
IdSSLIOHandlerSocketOpenSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);

StringList := TStringList.Create;
StringStream := TStringStream.Create('', TEncoding.UTF8);
StringList.Add('consumer_key = abcdefg');
StringList.Add('&consumer_secret = hijklmn');
StringList.Add('&code = opqrstuvxz');
StringStream.WriteString(StringList.text);

lHTTP.Request.CustomHeaders.Clear;
lHTTP.IOHandler := IdSSLIOHandlerSocketOpenSSL;
lHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
lHTTP.Request.CharSet:= 'utf-8';
lHTTP.HandleRedirects := True;
lHTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36';
lHTTP.Request.Method:='POST';
Result:= lHTTP.Post(Url, StringStream);

Below is the PHP example provided by Ecommerce:

$params["consumer_key"] = "### Chave da Aplicação ###";
$params["consumer_secret"] = "### Chave Secreta da Aplicação ###";
$params["code"] = "### Código de Autorização ###";

$url = "https://{api_address}/auth/?".http_build_query($params);

ob_start();

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_exec($ch);

What’s missing? Or what I’m doing wrong ?

Thank you in advance.

1 answer

1


I don’t know much about Delphi (I only had a brief experience with Object Pascal, which maybe today should be a little different from both), but it seems to me that this:

StringList.Add('consumer_key = abcdefg');
StringList.Add('&consumer_secret = hijklmn');
StringList.Add('&code = opqrstuvxz');

This should be it:

StringList.Add('consumer_key=abcdefg');
StringList.Add('consumer_secret=hijklmn');
StringList.Add('code=opqrstuvxz');

If the & and no spaces separating the = key and value. This is according to all the examples I found and some of the documentation.

Following the examples I found and your PHP code seems to me to be running unnecessary things:

lHTTP.Request.CustomHeaders.Clear; # Não parece necessário
lHTTP.IOHandler := IdSSLIOHandlerSocketOpenSSL;
lHTTP.Request.ContentType := 'application/x-www-form-urlencoded'; # Não parece necessário (não estou certo)
lHTTP.Request.CharSet:= 'utf-8'; # Não parece necessário
lHTTP.HandleRedirects := True;
lHTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'; # Não parece necessário
lHTTP.Request.Method:='POST'; # Não parece necessário
Result:= lHTTP.Post(Url, StringStream);

Maybe only this already resolves (since the API seems to have worked properly with PHP):

 lHTTP:= TIdHTTP.Create(nil);
 IdSSLIOHandlerSocketOpenSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);

StringList := TStringList.Create;
StringList.Add('consumer_key=abcdefg');
StringList.Add('consumer_secret=hijklmn');
StringList.Add('code=opqrstuvxz');

lResult := lHTTP.Post(Url, StringList);

I believe that the StringStream is only necessary if you are actually trying to convert to UTF8 (if the data comes from other sources), if your .dpr is saved as UTF-8 so you may not even need it.

What you should probably do in future scripts is encode the parameters passed (I’m not sure if for the TIdHTTP.Create that’s really necessary, it’s more "speculation" of mine), so I’ve seen the standard methods for using this are:

uses
  IdURI;

...

TIdURI.URLEncode(valor);

It should look something like:

StringList.Add(TIdURI.URLEncode(chave) + '=' + TIdURI.URLEncode(valor));

Note that HTTPApp.URLEncode this in disuse, prefer System.NetEncoding.TURLEncoding

  • It was the same mistake. I had tried to do so before.

  • Sorry, I had been trying without &. I removed the spaces and the error changed: HTTP request failed 401 HTTP/1.1 401 Unauthorized

  • It worked my friend. Thank you very much. The hard thing is to know that I spent two days banging my head because of the blank spaces. But it worked, let’s move on!

  • @Marcellocainelli please mark the answer as correct

Browser other questions tagged

You are not signed in. Login or sign up in order to post.