读DataSnap源代码(五)
function TDSHTTPWebDispatcher.DispatchRequest(Sender: TObject;
Request: TWebRequest; Response: TWebResponse): Boolean;
begin
try
if Owner is TWebModule then
DataSnapWebModule := TWebModule(Owner);
try
try
RequiresServer;
TDSHTTPServerWebBroker(Self.FHttpServer).DispatchDataSnap(Request, Response);
Result := True;
except
on E: Exception do
begin
{ Default to 500, like web services. }
Response.StatusCode := ;
Result := True;
end;
end;
except
{ Swallow any unexpected exception, it will bring down some web servers }
Result := False;
end;
finally
{ Reset current DataSnapWebModule }
DataSnapWebModule := nil;
end;
end;
第10行代码中,请求被分配到TDSHTTPServerWebBorker中处理了。
procedure TDSHTTPServerWebBroker.DispatchDataSnap(ARequest: TWebRequest;
AResponse: TWebResponse);
var
LDispatch: TDSHTTPDispatch;
LContext: TDSHTTPContextWebBroker;
begin
LDispatch := TDSHTTPApplication.Instance.HTTPDispatch;
if LDispatch <> nil then
DoCommand(LDispatch.Context, LDispatch.Request, LDispatch.Response)
else
begin
LContext := TDSHTTPContextWebBroker.Create(ARequest, AResponse);
try
DoCommand(LContext, LContext.FRequest, LContext.FResponse);
finally
LContext.Free;
end;
end;
end;
上面的第14行代码最终会转到TDSRESTServer类处理。
procedure TDSRESTServer.DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest;
AResponseInfo: TDSHTTPResponse);
procedure TDSRESTServer.DoCommand(AContext: TDSHTTPContext; ARequestInfo: TDSHTTPRequest;
AResponseInfo: TDSHTTPResponse);
var
Request: string;
NextRequest: string;
NextContext: string;
RestCtxt: string;
StartDispatch: Boolean;
begin // HTTPDispatch object if necessary
StartDispatch := not TDSHTTPApplication.Instance.Dispatching;
if StartDispatch then
TDSHTTPApplication.Instance.StartDispatch(AContext, ARequestInfo, AResponseInfo);
try
{$IFNDEF POSIX}
if CoInitFlags = - then
CoInitializeEx(nil, COINIT_MULTITHREADED)
else
CoInitializeEx(nil, CoInitFlags);
{$ENDIF}
try
// check for context, if not found send the appropriate error message
Request := ARequestInfo.URI;
if Consume(FDSContext, Request, NextRequest) then
begin
Request := NextRequest;
if Consume(FRESTContext, Request, NextRequest) then
begin
// datasnap/rest
DoDSRESTCommand(ARequestInfo, AResponseInfo, NextRequest);
end
else if ConsumeOtherContext(Request, NextContext, NextRequest) then
begin
DoDSOtherCommand(AContext, ARequestInfo, AResponseInfo, NextContext, NextRequest, FDSServerName <> EmptyStr);
end
else
begin
RestCtxt := Trim(FRESTContext);
if RestCtxt = EmptyStr then
RestCtxt := SProtocolRestEmpty; AResponseInfo.ResponseNo := ; {rest or other service not found in URI}
AResponseInfo.ContentText := Format(SProtocolNotSupported, [Request, RestCtxt]);
AResponseInfo.CloseConnection := true;
end;
end
else
begin
// This may dispatch .js files for example
DoCommandOtherContext(AContext, ARequestInfo, AResponseInfo, Request);
end;
if Assigned(Self.FTrace ) then
begin
FTrace(Self, AContext, ARequestInfo, AResponseInfo);
end;
finally ClearInvocationMetadata();
{$IFNDEF POSIX}
CoUnInitialize;
{$ENDIF}
end;
finally
if StartDispatch then
TDSHTTPApplication.Instance.EndDispatch;
end;
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的比较)
program Project1; uses
Vcl.Forms,
Web.WebReq,
IdHTTPWebBrokerBridge,
Unit1 in 'Unit1.pas' {Form1},
ServerMethodsUnit1 in 'ServerMethodsUnit1.pas',
ServerContainerUnit1 in 'ServerContainerUnit1.pas' {ServerContainer1: TDataModule}; {$R *.res} begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TServerContainer1, ServerContainer1);
Application.Run;
end.
机制有何不同?
读DataSnap源代码(五)的更多相关文章
- 读DataSnap源代码(一)
Delphi的DataSnap用了一段时间了,但一直感觉有些地方还不够了解,所以花时间阅读了源代码,特作此烂笔头. Datasnap是在之前的WebBorker基础上搭建的,DataSnap向导自动生 ...
- 读DataSnap源代码(六)
具体分析一下DataSanp App与Rest, WebBroker App的不同,先看TDSHTTPService. **************************************** ...
- 读DataSnap源代码(四)
继续篇中的 function TCustomWebDispatcher.DispatchAction(Request: TWebRequest; Response: TWebResponse): Bo ...
- 读DataSnap源代码(三)
function TWebRequestHandler.HandleRequest(Request: TWebRequest; Response: TWebResponse): Boolean; va ...
- 读DataSnap源代码(二)
program Project1; {$APPTYPE GUI} {$R *.dres} uses Vcl.Forms, Web.WebReq, IdHTTPWebBrokerBridge, Form ...
- 读Flask源代码学习Python--config原理
读Flask源代码学习Python--config原理 个人学习笔记,水平有限.如果理解错误的地方,请大家指出来,谢谢!第一次写文章,发现好累--!. 起因 莫名其妙在第一份工作中使用了从来没有接 ...
- session自己定义存储,怎样更好地进行session共享;读tomcat7源代码,org.apache.catalina.session.FileStore可知
session自己定义存储.怎样更好地进行session共享: 读tomcat源代码,org.apache.catalina.session.FileStore可知 一.详见: 方法1 public ...
- dotnet 读 WPF 源代码笔记 布局时 Arrange 如何影响元素渲染坐标
大家是否好奇,在 WPF 里面,对 UIElement 重写 OnRender 方法进行渲染的内容,是如何受到上层容器控件的布局而进行坐标偏移.如有两个放入到 StackPanel 的自定义 UIEl ...
- dotnet 读 WPF 源代码笔记 渲染收集是如何触发
在 WPF 里面,渲染可以从架构上划分为两层.上层是 WPF 框架的 OnRender 之类的函数,作用是收集应用程序渲染的命令.上层将收集到的应用程序绘制渲染的命令传给下层,下层是 WPF 的 GF ...
随机推荐
- python自学第四天,字符串用法
String 的用法 names="张三 welcome {city}" print(names.capitalize())#首字母大写 print(names.count(&qu ...
- python中pass语句的作用是什么
pass语句不会执行任何操作,一般作为占位符或者创建站位程序,whileFalse:pass.
- python scrapy 把cookie并转化为字典的形式
在用scrapy设置cookie的时候,需要从网页上对应的页面把cookie字段复制下来,并转化为字典的形式,下面代码是对cookie的转化过程 # -*- coding: utf-8 -*- cla ...
- 3--Selenium环境准备--Eclipse 引入 selenium-server包
1.下载selenium-server包 selenium-server-standalone包是Seleniumd的核心jar包,其中包含了各种元素定位和调用浏览器的方法.下载jar包后,在ID ...
- PAT 乙级 1056. 组合数的和(15)
给定N个非0的个位数字,用其中任意2个数字都可以组合成1个2位的数字.要求所有可能组合出来的2位数字的和.例如给定2.5.8,则可以组合出:25.28.52.58.82.85,它们的和为330. 输入 ...
- python --flask框架的搭建--(flask,python2,python3都可以运行)
在linux搭建flask开发环境: (1)virtualenv -p python3 flasky ---创建虚拟环境 (2)source flasky/bin/act ...
- 【转载】 强化学习(三)用动态规划(DP)求解
原文地址: https://www.cnblogs.com/pinard/p/9463815.html ------------------------------------------------ ...
- tmux-2.3 conf
set-window-option -g automatic-rename off set -g allow-rename off # 把前缀键从 C-b 更改为 C-a set -g prefix ...
- linux下history命令显示执行时间
想在输入history命令之后,显示自己历史的命令执行的时间,需要在用户目录下~/.bashrc的文件末尾追加添加如下几行 之前一直想看一下自己历史命令执行的时间,找了很多教程都没有卵用,最终参考了如 ...
- UDP方式实现广域网的P2P通信
最近在研究P2P通信,希望能够穿透路由器. 当前的做法只是使用TCP协议进行客户端与服务器端通信,使用UDP协议进行客户端之间的打洞操作,UDP的方式的源码在下方. 一直没有实现TCP的打洞,如果有实 ...