I am attempting to connect to a secure server using a TIdHTTP
component. I have assigned a TIdSSLIOHandlerSocketOpenSSL
I/O Handler to the IOHandler
property, and I have downloaded the OpenSSL files.
When I invoke Connect()
, it generates an "A port is required" exception. Another post suggests that Host
and Port
should be assigned automatically for a TIdHTTP
. Any suggestions as to what I am doing wrong?
If I don't invoke Connect()
, the site responds with an error 406, because the connection is not secure.
Relevant bits of code are:
try
IdHttp1.Connect ('https://test-api.service.hmrc.gov.uk');
IdHttp1.Request.CustomHeaders.AddValue ('Accept', 'application/vnd.hmrc.1.0+json');
result := IdHTTP1.Get('https://test-api.service.hmrc.gov.uk/hello/world');
except
on E: Exception do
memo1.lines.add (E.ClassName + ': ' + E.message);
end;
The "Port is required" error is because the Port
property has not been assigned a value yet when Connect()
is called.
But, the thing is, unlike with other TCP client components, you are NOT supposed to call Connect()
directly at all when using TIdHTTP
. Its Get()
method (and other request methods) will handle that internally for you. So, you need to remove the Connect()
call from your code.
HTTP is a stateless protocol. The underlying TCP connection may be persistent, or it may be disconnected, between multiple requests to the same server. Client and server negotiate that on a per-request basis. TIdHTTP
handles that detail internally for you, by parsing URLs for Host and Port information (as I explained in the other post you mentioned) and disconnecting/reconnecting the TCP connection as needed.
All you have to do is provide a valid URL to Get()
(and others) and let TIdHTTP
manage the TCP connection for you.
On a separate note, you should not be using the Request.CustomHeaders
property to set the Accept
request header. Use the Request.Accept
property instead.
Try this:
IdHttp1.Request.Accept := 'application/vnd.hmrc.1.0+json';
try
Result := IdHTTP1.Get('https://test-api.service.hmrc.gov.uk/hello/world');
except
on E: Exception do
Memo1.Lines.Add(E.ClassName + ': ' + E.message);
end;
As for response code 406, the fact that you get any response at all means you have a valid HTTP connection to the server. But 406 DOES NOT mean the connection is unsecure, as you claim (in fact, it can't be, since you are requesting an HTTPS url). 406 actually means the server could not deliver its response data to you in a format that you explicitly requested as being acceptable. In this case, the response could not be given in the JSON format that you want.
So, you need to figure out why the server is not sending JSON and fix that, or you need to ammend your Accept
request header to include the format that the server wants to use instead.
My guess is the server is probably trying to send back an error message in a non-JSON format (maybe in HTML instead), so try removing your Accept
request header temporarily so you can look at the actual response, and then update your request code as needed.