0

次のようなリクエストを処理する必要がある HTTP Web Broker Server があります。

http://myserver.com/versions/2013.6.0.0/ML/Files/SomeFile.exe

参照用のサーバー自体は、自動ソフトウェア更新用の情報と特定の個々のファイルをホストしています (多くの個々の更新可能なファイルが関係しています)。

そのため、Web モジュールでリクエスト ハンドラを作成しますが、このリクエストのパス情報 ( Request.PathInfo) は...

/versions/2013.6.0.0/ML/Files/SomeFile.exe

...しかし、最初の部分だけを検出する必要があります...

/versions

これを検出したら、次のバージョン番号を処理する必要があります...

/2013.6.0.0

...この場合、Web サーバーは、そのバージョンに固有のクライアントの要求データを認識しています。次の部分はアプリケーション版です...

/ML

次に、このバージョン/エディションの組み合わせに関連する特定のファイルを探していることを指定します...

/Files

...そして最後に実際のファイル...

/SomeFile.exe

この URL は Web サーバー上の実際のディレクトリを表しているわけではありません。実際の場所はSomeFile.exeまったく異なる可能性があります (これらのファイルの場所を検出する方法については別の話です)。

問題は、このパス情報の階層をどのように検出し、Web モジュールで利用可能なリクエスト ハンドラー アクション (TCollection) を使用してそれに応じて処理する必要があるかということです。組み込みのリクエスト ハンドラはレベルが 1 つしかないことを前提としていますが、このサーバーには実質的に無限のレベルがある可能性があります。

4

2 に答える 2

0

質問に対するロブのコメントに基づいて、これがいかに簡単に達成できるかすぐにわかりました。文字列リストを使用して、パス情報を各スラッシュを分割するさまざまなリスト項目に分割します。次に、任意のカスタム メカニズムを使用して最初のものを評価し、次に 2 番目、というように評価します。各バリエーションは、次のように異なるハンドラー プロシージャをトリガーします...

unit uUpdateServerWebModule;

interface

uses System.SysUtils, System.Classes, Web.HTTPApp, Update.Common;

type
  TWebModule1 = class(TWebModule)
    procedure WebModule1DefaultHandlerAction(Sender: TObject;
      Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
  private
    procedure HandleVersionCheck(Request: TWebRequest; Response: TWebResponse;
      PathInfo: TStringList);
    procedure HandleInfoCheck(Request: TWebRequest; Response: TWebResponse;
      PathInfo: TStringList);
    procedure HandleException(Request: TWebRequest; Response: TWebResponse;
      PathInfo: TStringList; const Code: Integer);
  public
    { Public declarations }
  end;

var
  WebModuleClass: TComponentClass = TWebModule1;

implementation

{$R *.dfm}

procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  L: TStringList;
  S, T: String;
  P: Integer;
  procedure A(const Text: String);
  begin
    S:= S + Text + sLineBreak;
  end;
begin
  //Break down URL by slashes into list
  L:= TStringList.Create;
  try
    S:= Request.PathInfo;
    if Copy(S, Length(S)-1, 1) <> '/' then
      S:= S + '/';
    Delete(S, 1, 1);
    while Length(S) > 0 do begin
      P:= Pos('/', S);
      T:= Copy(S, 1, P-1);
      Delete(S, 1, P);
      L.Append(T);
    end;
    if L.Count > 0 then begin
      //Handle path info list
      if LowerCase(L[0]) = 'ver' then begin
        HandleVersionCheck(Request, Response, L);
      end else
      if LowerCase(L[0]) = 'info' then begin
        HandleInfoCheck(Request, Response, L);
      end else begin
        HandleException(Request, Response, L, 0);
      end;
    end else begin
      //No page specified, return default page
      Response.Content:= 'Application Update Server';
    end;
  finally
    L.Free;
  end;
end;

procedure TWebModule1.HandleVersionCheck(Request: TWebRequest;
  Response: TWebResponse; PathInfo: TStringList);
var
  EC: String;
  FN: String;
  Ver: TVersion;
begin
  if LowerCase(PathInfo[1]) = 'info' then begin
    //Next parameter: Edition Code
    EC:= LowerCase(PathInfo[2]);
    if (EC = 'ml') or (EC = 'sl') or (EC = 'lt') then begin
      //Return current version info for specified software edition...
    end else begin
      HandleException(Request, Response, PathInfo, 4);
    end;
  end else begin
    //Next parameter: Version Number(s)
    Ver:= TVersion.Create;
    try
      Ver.Version:= PathInfo[1];
      if (Ver.Ver1 > 0) and (Ver.Ver2 > 0) then begin
        //Next parameter: Edition Code
        EC:= LowerCase(PathInfo[2]);
        if (EC = 'ml') or (EC = 'sl') or (EC = 'lt') then begin
          //Next parameter: Version/Edition Commands
          if LowerCase(PathInfo[3]) = 'update' then begin
            //Return stream of full verion update installer app...
            Response.ContentType:= 'application/octet-stream';

          end else
          if LowerCase(PathInfo[3]) = 'files' then begin
            //Next parameter: Specific filename
            FN:= PathInfo[4];
            //Return stream of specific file...
            Response.ContentType:= 'application/octet-stream';

          end else begin
            HandleException(Request, Response, PathInfo, 1);
          end;
        end else begin
          HandleException(Request, Response, PathInfo, 2);
        end;
      end else begin
        HandleException(Request, Response, PathInfo, 3);
      end;
    finally
      Ver.Free;
    end;
  end;
end;

procedure TWebModule1.HandleInfoCheck(Request: TWebRequest;
  Response: TWebResponse; PathInfo: TStringList);
begin
  //Return information about all software and their current versions...
end;

procedure TWebModule1.HandleException(Request: TWebRequest;
  Response: TWebResponse; PathInfo: TStringList; const Code: Integer);
begin
  //Return error information...
  Response.Content:= 'EXCEPTION: '+IntToStr(Code);
end;

end.

これは、Web モジュールの完全なコード (メイン ロジック) です。

主な処理は、デフォルト ハンドラーから行われます。基本的に、すべての着信要求はWebModule1DefaultHandlerAction、各着信要求を処理するこの手順を介して処理されます。ここから、最初にパスが指定されているかどうかを識別します。そうでない場合は、メインのランディング ページを返すだけです。それ以外の場合は、最初にリストされたパスを読み取り、要求された名前に応じて別のハンドラー プロシージャを呼び出します。この場合、versions要求を処理し、特定のファイル ( ) をさらにダウンロードSomeFile.exeして、特定の場所に保存します。

于 2013-06-29T22:30:44.203 に答える