Delphi TIdHTTPServer: не е позволено да зарежда локален ресурс от отдалечено устройство

Правя VCL Forms Application с 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, получавам две съобщения: „Не е разрешено да зарежда локален ресурс: file:///{app_path}/scripts/script1 .js', 'Не е разрешено зареждането на локален ресурс: file:///{app_path}/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