bob_saginowski
bob_saginowski

Reputation: 1429

Delphi TIdHTTPServer: not allowed to load local resourse from remote device

I'm making a VCL Forms Application with a TIdHTTPServer on the main form and a CommandGet of the IdHTTPServer procedure:

procedure TForm6.IdHTTPServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  indexStream: TFileStream;
  path, indexPath: string;
begin
  AResponseInfo.CharSet := 'UTF-8';
  path := GetCurrentDir.Remove(GetCurrentDir.Length - Length('Win32\Debug'));
  ARequestInfo.Document := path + 'scripts/script1.js';
  ARequestInfo.Document := path + 'scripts/script2.js';

  if pos('profile', ARequestInfo.UnparsedParams) > 0 then
  begin
    indexPath := path + 'index.html';  
    AResponseInfo.ContentStream := TFileStream.Create(indexPath, fmOpenReadWrite);
  end;
end;

EDIT

procedure TForm6.IdHTTPServerCommandGet(AContext: TIdContext;
   ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  applicationDirectory: string;
begin
  AResponseInfo.CharSet := 'UTF-8';
  AResponseInfo.FreeContentStream := True;
  applicationDirectory := ExtractFilePath(Application.ExeName)
    .Remove(ExtractFilePath(Application.ExeName).Length -
    Length('Win32\Debug') - 1);
  AResponseInfo.ContentStream := TFileStream.Create(applicationDirectory +
     'scripts/script1.js', fmOpenRead or fmShareDenyWrite);
  AResponseInfo.ContentStream := TFileStream.Create(applicationDirectory +
     'scripts/script2.js', fmOpenRead or fmShareDenyWrite);

  if pos('profile&userName=', ARequestInfo.UnparsedParams) > 0 then
  begin
    AResponseInfo.ContentStream :=
       TFileStream.Create(applicationDirectory + 'index.html', fmOpenRead);
  end;
  // other requests
end;

Here is the content of index.html:

<html>
  <head>
    <title>Profile</title>
    <script type="text/javascript" src="[app-path]/scripts/script1.js "></script>
    <script type="text/javascript" src="[app-path]/scripts/script2.js "></script>
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="pragma" content="no-cache">
  </head>
  <body>
  <!-- Page content -->
  </body>
</html>

When I start the application and access http://localhost/?profile&userName=testUser it works fine but when I start the application and type in other computer's chrome browser http://{my-ip4-address}/?profile&userName=testUser I get two messages: 'Not allowed to load local resource: file:///{app_path}/scripts/script1.js', 'Not allowed to load local resource: file:///{app_path}/scripts/script2.js. The content of the HTML page is visible.

EDIT

Based on the comments and answer index.html changed to

 <html>
  <head>
    <title>Profile</title>
    <script type="text/javascript" src="/scripts/script1.js "></script>
    <script type="text/javascript" src="/scripts/script2.js "></script>
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="pragma" content="no-cache">
  </head>
  <body>
  <!-- Page content -->
  </body>
</html>

Editing my code like this I can access files but the problem is that the content of script1.js is same as the content of script2.js. Any idea how to send the files correctly.

Upvotes: 1

Views: 1722

Answers (1)

mjn
mjn

Reputation: 36654

Never use the application path ([app-path] in your example HTML code) if the HTML file is going to be served to other computers. For local stand-alone HTML pages this might work, but external clients will not be able to access that resource.

Instead, specify the path to the JavaScript (absolute as /scripts/script1.js or relative like scripts/script1.js, depending on the virtual directory structure) and resolve it to the file on the server based on the Request.Document property.

Your example code nevers read the Request.Document property (and even assigns values to it - twice!). So the server does not know which resource the client actually wants.

Your code must transform the Document property into a path relative to a document root folder, which might be a dedicated subfolder of your applications working directory for example. And then check if this path points to an existing file. If it exists, read it and return its content. If it does not exist, return an error code.

Upvotes: 3

Related Questions