Search code examples
javascripthtmldelphiindyhttpserver

Indy TIdHTTPServer OnCommandGet javascript in html not executing


I have a TIdHTTPServer that sends javascript code in an html file to the browser with tag <script language="javascript"> in the <head> tag. I don't have access to the html file so I cannot change it's content. I use HTTPServerCommandGet to send the contents of this file to the browser like this :

procedure TMainForm.HTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  responseMemoryStream : TMemoryStream;
begin
  responseMemoryStream := TMemoryStream.Create;
  try
    AResponseInfo.ContentType := 'text/html';
    AResponseInfo.ContentEncoding := 'UTF-8';
    AResponseInfo.CharSet := 'UTF-8';
    responseMemoryStream.LoadFromFile(ExtractFilePath(Application.ExeName) + 'index.html');
    AResponseInfo.ContentStream := TMemoryStream.Create;
    TMemoryStream(AResponseInfo.ContentStream).LoadFromStream(responseMemoryStream);
  finally
    responseMemoryStream.Free;
  end;
end;

When I then make a GET command from an internet browser it sometimes loads the javascript, but sometimes it doesn't - when I use Firefox there are no problems, but when I use Chrome or IE the javascript never executes. Is there a way to force the execution of the javascript code somehow with the AResponseInfo variable or there is nothing I can do to fix this ?

This is what part of the index.html looks like :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta name="keywords" content="" />
    <meta name="description" content="" />
    <meta  charset=utf8 />
    <title>My title</title>
    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
    <script language="javascript">
        var map;
        var flag_for_map_massage = 0;
        var map_marker = 0;
        function initmap()
        {
            var html;
            var map_divtxt = "<div id=\"map_canvas\" style=\"width:200px;height:150px;\" ></div>";
            document.getElementById("google_map").innerHTML = map_divtxt;
            var latlng = new google.maps.LatLng(100.12345, 200.12345);

            var options = {
                zoom: 17,
                center: latlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            var map1 = new google.maps.Map(document.getElementById("map_canvas"), options);

            var html = "<table>" +
                    "<tr><td>GMBH Address</td> </tr>";

            infowindow = new google.maps.InfoWindow({
                content: html
            });
            var marker1 = new google.maps.Marker({
                position: new google.maps.LatLng(100.12345, 200.12345),
                map: map1

            });
            //     infowindow.open(map1, marker1);
            google.maps.event.addListener(marker1, "click", function() {
                infowindow.open(map1, marker1);
            });
        }

    </script>
</head>
<body onload="initmap();">  
  <div class="entry">
    <div id="google_map">
    </div>
  </div> 
</body>
</html>

Solution

  • All your server can do is deliver the HTML to the browser, nothing more. It is browser's responsibility to process the HTML, retrieve external resources, execute scripts, etc. If the browser is not functioning correctly, then chances are the HTML/script has errors in it to begin with. That has nothing to do with your server (unless you are corrupting the data you are sending).

    With that said, you do not need to use two streams in your OnCommandGet code, that is overkill. One stream is enough. Also, utf-8 is not a valid ContentEncoding value, so you need to remove that.

    Try this:

    procedure TMainForm.HTTPServerCommandGet(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    begin
      AResponseInfo.ContentType := 'text/html';
      AResponseInfo.CharSet := 'utf-8';
      AResponseInfo.ContentStream := TMemoryStream.Create;
      TMemoryStream(AResponseInfo.ContentStream).LoadFromFile(ExtractFilePath(Application.ExeName) + 'index.html');
    end;
    

    Alternatively:

    procedure TMainForm.HTTPServerCommandGet(AContext: TIdContext;
      ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    begin
      AResponseInfo.ContentType := 'text/html';
      AResponseInfo.CharSet := 'utf-8';
      AResponseInfo.ContentStream := TIdReadFileExclusiveStream.Create(ExtractFilePath(Application.ExeName) + 'index.html');
    end;
    

    And, of course, make sure you are paying attention to the ARequestInfo.Document property and only serving index.html if the browser is actually requesting index.html and not some other file on your server.