How i can use IdHTTP
to send message as PostMan
dos below:
My first attempt was as follow:
function TIdFoo.SendIM(const AID, AMessage: string): Boolean;
const
_URL = 'https://URL.com/SendMessage';
var
Params : TStringStream;
Response : string;
LMsg : string;
begin
Result := False;
LMsg := '-----------------------------13932'+
'Content-Type: application/json; charset=utf-8'+
'Content-Description: message'+ sLineBreak+ '{"message":{"Type":1,"body":"'+AMessage+'"},"to":["'+AID+'"]}'+
'-----------------------------13932--;'+sLineBreak;
Params := TStringStream.Create(LMsg, TEncoding.UTF8);
try
IdHTTP.Request.CustomHeaders.AddValue('authorization', 'Bearer ' + FToken);
IdHTTP.Request.CustomHeaders.AddValue('Origin', 'https://www.URL.com');
IdHTTP.Request.UserAgent := 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36';
IdHTTP.Request.Accept := '*/*';
IdHTTP.Request.Referer := 'https://www.URL.com/en-us/';
IdHTTP.Request.Host := 'URL.com';
IdHTTP.Request.AcceptEncoding := 'gzip, deflate, br';
IdHTTP.Request.AcceptLanguage := 'Accept-Language';
IdHTTP.Request.ContentType := 'multipart/mixed; boundary="---------------------------13932"';
Params.Position := 0;
try
Response := IdHTTP.Post(_URL, Params);
Result := True;
except
on E: Exception do
Writeln('Error on Send Message request: '#13#10, e.Message);
end;
Writeln(IdHTTP.Request.RawHeaders.Text);
finally
Params.Free;
end;
end;
The second attempt i try it this way
function TIdFoo.SendIM(const AID, AMessage: string): Boolean;
const
_URL = 'https://URL.com/SendMessage';
var
Params : TStringStream;
Response : string;
LMsg : string;
begin
Result := False;
LMsg := '{"message":{"Type":1,"body":"'+AMessage+'"},"to":["'+AID+'"]}';
Params := TStringStream.Create(LMsg, TEncoding.UTF8);
try
IdHTTP.Request.CustomHeaders.AddValue('authorization', 'Bearer ' + FToken);
IdHTTP.Request.CustomHeaders.AddValue('Origin', 'https://www.URL.com');
IdHTTP.Request.CustomHeaders.AddValue('Content-Description', 'message'); // I addedd this as on PostMan Body
IdHTTP.Request.UserAgent := 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36';
IdHTTP.Request.Accept := '*/*';
IdHTTP.Request.Referer := 'https://www.URL.com/en-us/';
IdHTTP.Request.Host := 'URL.com';
IdHTTP.Request.AcceptEncoding := 'gzip, deflate, br';
IdHTTP.Request.AcceptLanguage := 'Accept-Language';
IdHTTP.Request.ContentType := 'application/json; charset=utf-8'; // I alos changed this as it shown on PostMan body
Params.Position := 0;
try
Response := IdHTTP.Post(_URL, Params);
Result := True;
except
on E: Exception do
Writeln('Error on Send Message request: '#13#10, e.Message);
end;
Writeln(IdHTTP.Request.RawHeaders.Text);
finally
Params.Free;
end;
end;
Both attempts gives HTTP/1.1 400 Bad Request
.
Can any advice my what i', doing wrong?
In your first example, your "raw" MIME data is not formatted correctly:
You are missing a bunch of required line breaks. And don't use the
sLineBreak
constant, as its value is platform-specific. MIME expects line breaks to useCRLF
specifically. Indy has anEOL
constant for that value.You have an erroneous semicolon on the end of the closing boundary line.
You are also not setting the
Request.AcceptEncoding
property correctly. DO NOT enable encodings manually, unless you are prepared to actually handle them manually in responses (which your code is not).TIdHTTP
handlesgzip
anddeflate
encodings for you, if you assign aTIdZLibCompressorBase
-derived component, likeTIdCompressorZLib
, to theTIdHTTP.Compressor
property. Don't worry about thebr
encoding, it is not widely used. In short, leave theRequest.AcceptEncoding
at its default and letTIdHTTP
manage it for you.You are also not setting the
Request.AcceptLanguage
property correctly. You should be setting it to'en-US,en;q=0.8'
, not to'Accept-Language'
.Your first example should work if you make these fixes, eg:
Alternatively:
Alternatively:
In your second example, your "raw" data is just the JSON by itself, not any MIME wrapping it. You are putting MIME headers in the HTTP headers, where they don't belong. This example will not work if the server expects MIME data and not just raw JSON data.
You are also making the same mistakes with the
Request.AcceptEncoding
andRequest.AcceptLanguage
properties.Since you are posting data in MIME format, an easier way to handle this would have been to use Indy's
TIdMultipartFormDataStream
class instead, and let it handle the MIME formatting for you. However, that class does not currently support:setting the stream's
RequestContentType
property to a custom value (in this case,'multipart/mixed'
instead of'multipart/form-data'
). Though, you can use an accessor class to accomplish this, since theFRequestContentType
member isprotected
.omitting the
Content-Disposition: form-data
header on individual fields. This might trip up servers that are not expectingform-data
submissions.specifying the
Content-Description
MIME header at all (see Add support for user-defined MIME headers in TIdMultipartFormDataStream in Indy's issue tracker on GitHub).So you will have to continue resorting to formatting the MIME data manually. You just have to make sure you get it right.