AFAIK Indy uses HTTP version 1.0 for posts.
By default, yes. You can disable that behavior by enabling the hoKeepOrigProtocol flag in the TIdHTTP.HTTPOptions property, then Post() will respect whichever version you specify in the TIdHTTP.ProtocolVersion property.
Also, Indy handles empty response and turns it into:
if Length(LLocalHTTP.Response.ResponseText) = 0 then begin
// Support for HTTP responses without status line and headers
LLocalHTTP.Response.ResponseText := 'HTTP/1.0 200 OK'; {do not localize}
That is to handle old HTTP 0.9 servers, which don't send status lines or headers in responses (they also don't technically support POST either, only GET).
The ResponseText should NEVER be empty when communicating with an HTTP 1.0+ server.
Simple severs might expect Content-Length header directly after Content-Type header.
No HTTP server should *require* that, as it is forbidden by the HTTP specification to *require* headers be in any particular order.
client.AddHeader('Content-Length', IntToStr(length(sJSON)));
That will fail to work if the JSON contains any non-ASCII characters. The 'Content-Length' is the number of *bytes* being sent, not the number of *characters*. So, if the JSON is encoded as UTF-8 during transmission, the 'Content-Length' must be set to the number of UTF-8 bytes being sent.
Indy keeps the connection alive:
Connection: keep-alive
HTTP 1.1 defaults to keep-alive semantics, unless you specify otherwise. TIdHTTP explicitly requests keep-alive semantics in HTTP 1.0 unless you specify otherwise (in the TIdHTTP.Request.Connection property). Ultimately, it is the server that decides whether a keep-alive is actually used or not, and that is reflected in the server's response (in the TIdHTTP.Response.KeepAlive property).
Keep-alive or not has no effect whatsoever on how the server processes a POST request, though. It only affects whether the socket connection is kept open or is closed after the response is sent.