0

我有一个 HTTP Web 代理服务器,它需要处理诸如......

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) 相应地处理它?因为内置的请求处理程序假设只有一个级别,但这个服务器实际上可能有无限的级别。

4

2 回答 2

0

根据 Rob 对这个问题的评论,我很快意识到这很简单。使用字符串列表,将路径信息分解为不同的列表项,划分每个斜线。然后,使用任何自定义机制来评估第一个,然后是第二个,依此类推。每个变化都会触发不同的处理程序,就像这样......

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 Module的完整代码(主要逻辑)

主要处理是从默认处理程序完成的。基本上所有传入的请求都是通过这个WebModule1DefaultHandlerAction处理每个传入请求的过程来处理的。从这里,它首先确定是否有任何指定的路径。如果没有,它只会返回主登录页面。否则,它将首先读取列出的第一个路径,并根据请求的名称调用另一个处理程序。在这种情况下,它会处理versions请求并进一步下载SomeFile.exe要保存在特定目标中的特定文件 ( )。

于 2013-06-29T22:30:44.203 回答
0

您的拆分代码可以通过以下方式完成:

function Split( StringToSplit: string; SplitChar: Char = '/' ): TStringlist;
begin
  Result                 := TStringlist.Create;
  Result.Delimiter       := SplitChar;
  Result.StrictDelimiter := True;
  Result.DelimitedText   := StringToSplit;
end;
于 2020-04-30T20:38:30.347 回答