I make a HTTP POST
request using TIdHTTP
:
var
ssRequest, ssResponse: TStringStream;
...
IdHTTP.Post(fullUrl, ssRequest, ssResponse);
The server responds with:
400 Bad Request
and passes useful information in the response body (this is JSON in UTF-8 encoding). The problem is that in this case, TIdHTTP
generates an exception on the POST
request of type EIdHTTPProtocolException
and I can’t get the original response's bytes. I can only read EIdHTTPProtocolException.ErrorMessage
, but the national encodings are already lost in it.
ssResponse
is blank.IdHTTP.Response.ContentStream
is also blank.What can be done in this situation?
When TIdHTTP
raises the EIdHTTPProtocolException
, it takes the response's charset into account when populating the ErrorMessage
, so it should not be losing content. But as you noted, there is no direct way to access the original bytes. There is an open ticket in Indy's GitHub repo about that:
#388: Update EIdHTTPProtocolException to store original stream content
A different solution is to enable the hoNoProtocolErrorException
flag in the TIdHTTP.HTTPOptions
property to disable the exception from being raised. By default, the error body will be discarded, so also enable the hoWantProtocolErrorContent
flag so your TStream
will receive the raw bytes of the error body. You can then check the IdHTTP.ResponseCode
after IdHTTP.Post()
returns, and parse the TStream
data accordingly.
On a side note: you are receiving the response body using a TStringStream
with no encoding specified, so it will use TEncoding.Default
, which is the user's ANSI locale on Windows, and UTF-8 on Posix. You can't change the stream's encoding after construction, so if the response body does not match the stream's encoding then you will corrupt the data when reading the TStringStream.DataString
property.
If you use the overload of TIdHTTP.Post()
that returns a string
, it will take the response's charset into account when decoding the response body's bytes into a string
.