Delphi TIdHTTPServer: не разрешено загружать локальный ресурс с удаленного устройства

Я делаю приложение VCL Forms с TIdHTTPServer в основной форме и CommandGet процедуры IdHTTPServer:

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;

ИЗМЕНИТЬ

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;

Вот содержимое 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>

Когда я запускаю приложение и получаю доступ к http://localhost/?profile&userName=testUser, оно работает нормально, но когда я запускаю приложение и набираю chrome-браузер другого компьютера http://{my-ip4-address}/?profile&userName=testUser, я получаю два сообщения: «Не разрешено загружать локальный ресурс: файл:///{путь_приложения}/scripts/script1 .js», «Не разрешено загружать локальный ресурс: файл:///{путь_приложения}/scripts/script2.js. Содержимое HTML-страницы видно.

ИЗМЕНИТЬ

На основании комментариев и ответа index.html изменено на

 <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>

Редактируя свой код таким образом, я могу получить доступ к файлам, но проблема в том, что содержимое script1.js совпадает с содержимым script2.js. Любая идея, как правильно отправлять файлы.


person bob_saginowski    schedule 15.07.2014    source источник
comment
поместите свой script2.js на сервер и загрузите его оттуда. Сервер http://{my-ip4-address} ничего не знает о пути к файлу вашего компьютера.   -  person moskito-x    schedule 15.07.2014
comment
@moskito-x, какое свойство httpServer следует использовать для размещения файла на сервере   -  person bob_saginowski    schedule 15.07.2014
comment
@mitko.berbatov: так же, как вы помещаете index.html на сервер.   -  person moskito-x    schedule 15.07.2014
comment
@moskito-x, когда я помещаю script1.js на сервер, файл пуст. Почему это происходит.   -  person bob_saginowski    schedule 15.07.2014
comment
Пожалуйста, отредактируйте вопрос таким образом, чтобы контекст между вопросом и ответом больше не распознавался. Я отредактировал их до предыдущей версии.   -  person moskito-x    schedule 15.07.2014
comment
Посмотрите на свой index.html, там вы загружаете script1.js дважды.   -  person moskito-x    schedule 16.07.2014
comment
Проверил: index.html в порядке   -  person bob_saginowski    schedule 16.07.2014
comment
Тогда ваш index.html и файл, который вы показываете нам, различаются.   -  person moskito-x    schedule 16.07.2014
comment
Я отредактировал вопрос и файл index.html :)   -  person bob_saginowski    schedule 16.07.2014


Ответы (1)


Никогда не используйте путь к приложению ([app-path] в вашем примере HTML-кода), если HTML-файл будет передаваться на другие компьютеры. Для локальных автономных HTML-страниц это может работать, но внешние клиенты не смогут получить доступ к этому ресурсу.

Вместо этого укажите путь к JavaScript (абсолютный как /scripts/script1.js или относительный как scripts/script1.js, в зависимости от структуры виртуального каталога) и сопоставьте его с файлом на сервере на основе свойства Request.Document.

Код вашего примера никогда не читает свойство Request.Document (и даже присваивает ему значения — дважды!). Таким образом, сервер не знает, какой ресурс действительно нужен клиенту.

Ваш код должен преобразовать свойство Document в путь относительно корневой папки документа, которая может быть, например, выделенной подпапкой рабочего каталога ваших приложений. А затем проверьте, указывает ли этот путь на существующий файл. Если он существует, прочтите его и верните его содержимое. Если он не существует, верните код ошибки.

person mjn    schedule 15.07.2014
comment
Вам также необходимо установить AResponseInfo.ContentType в соответствующее значение, не полагайтесь на значение по умолчанию (то есть text/html). И избавьтесь от GetCurrentDir(), его значение динамически меняется в течение жизни приложения. Если вам нужен путь, по которому запущено приложение, используйте вместо него ExtractFilePath(Application.ExeName). И избавьтесь от логики, которая удаляет Win32\Debug из этого пути, поскольку эта подпапка больше не будет существовать после развертывания приложения на другом компьютере. - person Remy Lebeau; 15.07.2014
comment
@mjn Я отредактировал свой код (см. отредактированный вопрос), и я могу получить доступ к файлам, но проблема в том, что содержимое script1.js такое же, как содержимое script2.js. - person bob_saginowski; 16.07.2014
comment
Позвольте мне ответить вопросом: если вы напишете x := 1; x := 2;, какое значение, по вашему мнению, будет иметь x после его выполнения? Затем посмотрите на назначения потоку содержимого ответа в коде Delphi. - person mjn; 16.07.2014
comment
исправлено с помощью ARequestInfo.RawHTTPCommand для отправки требуемого файла. Спасибо за помощь @mjn - person bob_saginowski; 17.07.2014