• 读DataSnap源代码(五)


     1 function TDSHTTPWebDispatcher.DispatchRequest(Sender: TObject;
     2   Request: TWebRequest; Response: TWebResponse): Boolean;
     3 begin
     4   try
     5     if Owner is TWebModule then
     6       DataSnapWebModule := TWebModule(Owner);
     7     try
     8       try
     9         RequiresServer;
    10         TDSHTTPServerWebBroker(Self.FHttpServer).DispatchDataSnap(Request, Response);
    11         Result := True;
    12       except
    13         on E: Exception do
    14         begin
    15           { Default to 500, like web services. }
    16           Response.StatusCode := 500;
    17           Result := True;
    18         end;
    19       end;
    20     except
    21       { Swallow any unexpected exception, it will bring down some web servers }
    22       Result := False;
    23     end;
    24   finally
    25     { Reset current DataSnapWebModule }
    26     DataSnapWebModule := nil;
    27   end;
    28 end;

    第10行代码中,请求被分配到TDSHTTPServerWebBorker中处理了。

     1 procedure TDSHTTPServerWebBroker.DispatchDataSnap(ARequest: TWebRequest;
     2   AResponse: TWebResponse);
     3 var
     4   LDispatch: TDSHTTPDispatch;
     5   LContext: TDSHTTPContextWebBroker;
     6 begin
     7   LDispatch := TDSHTTPApplication.Instance.HTTPDispatch;
     8   if LDispatch <> nil then
     9     DoCommand(LDispatch.Context, LDispatch.Request, LDispatch.Response)
    10   else
    11   begin
    12     LContext := TDSHTTPContextWebBroker.Create(ARequest, AResponse);
    13     try
    14       DoCommand(LContext, LContext.FRequest, LContext.FResponse);
    15     finally
    16       LContext.Free;
    17     end;
    18   end;
    19 end;

    上面的第14行代码最终会转到TDSRESTServer类处理。

    procedure TDSRESTServer.DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest;
                                      AResponseInfo: TDSHTTPResponse);

     1 procedure TDSRESTServer.DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest;
     2                                   AResponseInfo: TDSHTTPResponse);
     3 var
     4   Request: string;
     5   NextRequest: string;
     6   NextContext: string;
     7   RestCtxt: string;
     8   StartDispatch: Boolean;
     9 begin
    10 
    11   // HTTPDispatch object if necessary
    12   StartDispatch := not TDSHTTPApplication.Instance.Dispatching;
    13   if StartDispatch then
    14     TDSHTTPApplication.Instance.StartDispatch(AContext, ARequestInfo, AResponseInfo);
    15   try
    16 {$IFNDEF POSIX}
    17   if CoInitFlags = -1 then
    18     CoInitializeEx(nil, COINIT_MULTITHREADED)
    19   else
    20     CoInitializeEx(nil, CoInitFlags);
    21 {$ENDIF}
    22   try
    23     // check for context, if not found send the appropriate error message
    24     Request := ARequestInfo.URI;
    25     if Consume(FDSContext, Request, NextRequest) then
    26     begin
    27       Request := NextRequest;
    28       if Consume(FRESTContext, Request, NextRequest) then
    29       begin
    30         // datasnap/rest
    31         DoDSRESTCommand(ARequestInfo, AResponseInfo, NextRequest);
    32       end
    33       else if ConsumeOtherContext(Request, NextContext, NextRequest) then
    34       begin
    35         DoDSOtherCommand(AContext, ARequestInfo, AResponseInfo, NextContext, NextRequest, FDSServerName <> EmptyStr);
    36       end
    37       else
    38       begin
    39         RestCtxt := Trim(FRESTContext);
    40         if RestCtxt = EmptyStr then
    41           RestCtxt := SProtocolRestEmpty;
    42 
    43         AResponseInfo.ResponseNo := 501; {rest or other service not found in URI}
    44         AResponseInfo.ContentText := Format(SProtocolNotSupported, [Request, RestCtxt]);
    45         AResponseInfo.CloseConnection := true;
    46       end;
    47     end
    48     else
    49     begin
    50       // This may dispatch .js files for example
    51       DoCommandOtherContext(AContext, ARequestInfo, AResponseInfo, Request);
    52     end;
    53     if Assigned(Self.FTrace ) then
    54     begin
    55       FTrace(Self, AContext, ARequestInfo, AResponseInfo);
    56     end;
    57   finally
    58                                                      
    59     ClearInvocationMetadata();
    60 {$IFNDEF POSIX}
    61     CoUnInitialize;
    62 {$ENDIF}
    63   end;
    64   finally
    65     if StartDispatch then
    66       TDSHTTPApplication.Instance.EndDispatch;
    67   end;
    68 end;


    上面阴影的代码,一步一步的推进,先判断URI中是否包括Datasnap,再往判断是否包括REST,然后再继续处理。

    到目前,代码已经从TWebModule到TDSHTTPWebDispatcher再到TDSRESTServer类中了。

    而Delphi中,我们可以创建三种类型的DataSanp Server程序:

    一是DataSanp REST App

    二是DataSnap App

    三是DataSnap WebBroker App

    目前来看, Rest App和WebBroder App是很相似的。而 DataSanp App有些不同:

    一是没有WebModule。

    二是用 TDSHTTPService 代替了 TDSHTTPWebDispatcher。

    三是Form1中代码简化了很多了,虽然project中也出现了  IdHTTPWebBrokerBridge,但也是不同的。(可以和rest app的比较)

     1 program Project1;
     2 
     3 uses
     4   Vcl.Forms,
     5   Web.WebReq,
     6   IdHTTPWebBrokerBridge,
     7   Unit1 in 'Unit1.pas' {Form1},
     8   ServerMethodsUnit1 in 'ServerMethodsUnit1.pas',
     9   ServerContainerUnit1 in 'ServerContainerUnit1.pas' {ServerContainer1: TDataModule};
    10 
    11 {$R *.res}
    12 
    13 begin
    14   Application.Initialize;
    15   Application.MainFormOnTaskbar := True;
    16   Application.CreateForm(TForm1, Form1);
    17   Application.CreateForm(TServerContainer1, ServerContainer1);
    18   Application.Run;
    19 end.


    机制有何不同?

  • 相关阅读:
    JS数组的相关方法
    JS字符串的相关方法
    重回我的园区
    STM32F405串口UART4波特率注意问题
    NXP MCU开始学习中
    锂电池测试
    FPGA与STM32并口通信
    NXP LPC4350绝对强悍,准备入手学习
    SDRAM+FPGA+MCU
    STM32+FPGA通信成功
  • 原文地址:https://www.cnblogs.com/Jiaojiawang/p/4818944.html
Copyright © 2020-2023  润新知