Héctor C.
Héctor C.

Reputation: 507

HTTP Get request to IP-based host using Indy

I have some Delphi code that connects to a servlet and I´m trying to switch from TIdTCPClient to TIdHTTP.

I connect to the servlet this way

   try
      lHTTP := TIdHTTP.Create( nil );
      responseStream := TMemoryStream.Create;
      lHTTP.Get(HttpMsg, responseStream);
      SetString( html, PAnsiChar(responseStream.Memory), responseStream.Size);
      AnotarMensaje( odDepurar, 'IMPFIS: Impresora fiscal reservada ' + html );

Where HttpMsg is localhost:6080/QRSRPServer/PedirImpresion?usuarioDMS=hector

All I´m getting is

GET localhost:6080/QRSRPServer/PedirImpresion?usuarioDMS=hector HTTP/1.1
Content-Type: text/html
Accept: text/html, */*
User-Agent: Mozilla/3.0 (compatible; Indy Library)

HTTP/1.1 400 Bad Request

The HTTP dialog that I had before was like this

GET /QRSRPServer/PedirImpresion?usuarioDMS=hector HTTP/1.1
Host: localhost:6080

HTTP/1.1 200 OK

So, I try to add the Host header, with this host: localhost:6080

   try
      lHTTP := TIdHTTP.Create( nil );
      lHTTP.Host := Host;
      responseStream := TMemoryStream.Create;
      lHTTP.Get(HttpMsg, responseStream);
      SetString( html, PAnsiChar(responseStream.Memory), responseStream.Size);
      AnotarMensaje( odDepurar, 'IMPFIS: Impresora fiscal reservada ' + html );

And I get

Socket Error # 11004

Upvotes: 0

Views: 1078

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 598011

Where HttpMsg is localhost:6080/QRSRPServer/PedirImpresion?usuarioDMS=hector

HttpMsg must begin with http:// or https://:

http://localhost:6080/QRSRPServer/PedirImpresion?usuarioDMS=hector

You should be getting an EIdUnknownProtocol exception raised when TIdHTTP parses the URL and sees the missing protocol scheme.

TIdHTTP should always be sending a Host header, but especially for an HTTP 1.1 request, but you claim it is not. This is why you are getting a Bad Request error, because HTTP 1.1 servers are required to reject an HTTP 1.1 request that omits that header.

You also claim that TIdHTTP is including the host and port values in the GET line. The ONLY time it ever does that is when connecting to a host through an HTTP proxy, but I don't see you configuring the TIdHTTP.ProxyParams property at all.

In short, TIdHTTP should not be behaving the way you claim.

The correct solution is to make sure you are passing a full URL to TIdHTTP.Get().

On a side note, your code requires html to be an AnsiString. You should change it to a standard string (which is AnsiString in D2007 and earlier) and let TIdHTTP return a string for you, then you don't need the TMemoryStream anymore:

html := lHTTP.Get(HttpMsg);

Upvotes: 3

Héctor C.
Héctor C.

Reputation: 507

It was easier than I thought. I was assuming that having a "host" paremeter that included the port would be enough but looking at a Wireshark capture I saw it was sending everything over the standard HTTP port.

So this did the trick

try
  lHTTP := TIdHTTP.Create( nil );
  lHTTP.Host := GatewayIp;
  lHTTP.Port := GatewayPuerto;
  responseStream := TMemoryStream.Create;
  lHTTP.Request.CustomHeaders.Clear;
  lHTTP.Request.CustomHeaders.Add('Host: ' + Host );
  lHTTP.Get(HttpMsg, responseStream);
  SetString( html, PAnsiChar(responseStream.Memory), responseStream.Size);
  AnotarMensaje( odDepurar, 'IMPFIS: Impresora fiscal reservada ' + html );

Upvotes: 0

Related Questions