Search code examples
delphiindyhttpserver

Delphi & Indy httpServer how stop sending 400 bad Request


I get data from a device that expects him back ACK (HTTP1/1 200 OK). My httpserver after receiving header is automatically returned 400 Bad Request (i see on WareShark). Perhaps the device is not properly built his request. How do I stop server does not return an error? So I will be able to continue communication with device.

thanks


LOG: 192.168.1.141:57565 Stat Connected.

HTTP Connect 192.168.1.141
LOG: 192.168.1.141:57565 Recv 10.4.2017 г. 00:18:43: POST / HTTP/1.1<EOL>

LOG: 192.168.1.141:57565 Recv 10.4.2017 г. 00:18:43: Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, text/*, */*<EOL>Accept-Language: en-us<EOL>Content-Type: application/x-www-form-urlencoded<EOL>Accept-Encoding: gzip, deflate<EOL>User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)<EOL>Content-Length: 579<EOL>Connection: Keep-Alive<EOL><EOL><?xml version="1.0"?><EOL><Metrics  SiteId="BG-001" Sitename="office Pazardjik"><EOL><Properties><EOL><MacAddress>00:b0:9d:7f:b7:b2</MacAddress><EOL><IpAddress>0.0.0.0</IpAddress><EOL><Timezone>2</Timezone><EOL><DST>1</DST><EOL><DeviceType>0</DeviceType><EOL><SerialNumber>8370098</SerialNumber><EOL></Properties><EOL><ReportData  Interval="1"><EOL><Report  Date="2017-04-06"><EOL><Object  Id="0" DeviceId="BG-001-01" Devicename="Main Entrance" ObjectType="0" Name="Main Entrance"><EOL><Count  StartTime="05:31:00" EndTime="05:32:00" Enters="0" Exits="0" Status="0"/><EOL></Object><EOL></Report><EOL></ReportData><EOL></Metrics><EOL>

HTTP Header 
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/x-shockwave-flash, text/*, */*
Accept-Language: en-us
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)
Content-Length: 579
Connection: Keep-Alive

LOG: 192.168.1.141:57565 Sent 10.4.2017 г. 00:18:43: HTTP/1.1 400 Bad Request<EOL>Connection: close<EOL>Content-Length: 0<EOL>Date: Sun, 09 Apr 2017 21:18:43 GMT<EOL><EOL>


LOG: 192.168.1.141:57565 Stat Disconnected.
LOG: 0.0.0.0:0 Stat Disconnected.

Solution

  • The HTTP client is sending an HTTP 1.1 request, but is not sending a required Host request header. Per RFC 2616 Section 14.23:

    A client MUST include a Host header field in all HTTP/1.1 request messages. If the requested URI does not include an Internet host name for the service being requested, then the Host header field MUST be given with an empty value. An HTTP/1.1 proxy MUST ensure that any request message it forwards does contain an appropriate Host header field that identifies the service being requested by the proxy. All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message which lacks a Host header field.

    TIdHTTPServer returns a 400 response if it receives an HTTP 1.1 request without a Host header. As you can see above, the 400 response is mandatory by the HTTP 1.1 spec. I suggest you contact the device manufacturer and report a bug about the missing Host header, maybe they can release a firmware update.

    In the meantime, you can use the TIdHTTPServer.OnHeadersAvailable event to insert a dummy Host header if it is missing:

    procedure httpServerHeadersAvailable(AContext: TIdContext; const AUri: string; AHeaders: TIdHeaderList; var VContinueProcessing: Boolean);
    begin
      if AHeaders.Values['Host'] = '' then
        AHeaders.Values['Host'] = 'myserver';
      VContinueProcessing := true;
    end;
    

    As for your log, it shows an Access Violation occurring in your OnCommandGet event handler, due to a nil pointer being accessed. That event is not triggered in the case when the client Host header is missing. So you clearly have a second issue in your code, not related to this issue.