2
0

fphttp.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. {
  2. $Id: header,v 1.1 2000/07/13 06:33:45 michael Exp $
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$H+}
  13. unit fphttp;
  14. Interface
  15. uses sysutils,classes,httpdefs;
  16. Type
  17. { THTTPContentProducer }
  18. TWebActionEvent = Procedure (Sender : TObject;
  19. ARequest : TRequest;
  20. AResponse : TResponse;
  21. Var Handled : Boolean) of object;
  22. THTTPContentProducer = Class(TComponent)
  23. private
  24. FAfterResponse: TResponseEvent;
  25. FBeforeRequest: TRequestEvent;
  26. Protected
  27. Procedure DoHandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean); virtual;
  28. Procedure DoGetContent(ARequest : TRequest; Content : TStream; Var Handled : Boolean); virtual;
  29. Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean);
  30. Function ProduceContent : String; virtual;
  31. Protected
  32. Property BeforeRequest : TRequestEvent Read FBeforeRequest Write FBeforeRequest;
  33. Property AfterResponse : TResponseEvent Read FAfterResponse Write FAfterResponse;
  34. Public
  35. Procedure GetContent(ARequest : TRequest; Content : TStream; Var Handled : Boolean);
  36. Function HaveContent : Boolean; virtual;
  37. Procedure ContentToStream(Stream : TStream); virtual;
  38. end;
  39. { TCustomWebAction }
  40. TCustomWebAction = Class(TCollectionItem)
  41. private
  42. FAfterResponse: TResponseEvent;
  43. FBeforeRequest: TRequestEvent;
  44. FContentproducer: THTTPContentProducer;
  45. FDefault: Boolean;
  46. FName : String;
  47. Protected
  48. procedure SetContentProducer(const AValue: THTTPContentProducer);virtual;
  49. Function GetDisplayName : String; override;
  50. Procedure SetDisplayName(AValue : String);
  51. Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean);
  52. Procedure DoHandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean); virtual;
  53. published
  54. Property Name : String Read GetDisplayName Write SetDisplayName;
  55. Property ContentProducer : THTTPContentProducer Read FContentproducer Write SetContentProducer;
  56. Property Default : Boolean Read FDefault Write FDefault;
  57. Property BeforeRequest : TRequestEvent Read FBeforeRequest Write FBeforeRequest;
  58. Property AfterResponse : TResponseEvent Read FAfterResponse Write FAfterResponse;
  59. end;
  60. { TCustomWebActions }
  61. TGetActionEvent = Procedure (Sender : TObject; ARequest : TRequest; Var ActionName : String) of object;
  62. TCustomWebActions = Class(TCollection)
  63. private
  64. FActionVar : String;
  65. FOnGetAction: TGetActionEvent;
  66. function GetActions(Index : Integer): TCustomWebAction;
  67. procedure SetActions(Index : Integer; const AValue: TCustomWebAction);
  68. Protected
  69. Function GetRequestAction(ARequest: TRequest) : TCustomWebAction;
  70. Function GetActionName(ARequest : TRequest) : String;
  71. Property ActionVar : String Read FactionVar Write FActionVar;
  72. public
  73. Procedure Assign(Source : TPersistent); override;
  74. Function Add : TCustomWebAction;
  75. Function ActionByName(AName : String) : TCustomWebAction;
  76. Function FindAction(AName : String): TCustomWebAction;
  77. Function IndexOfAction(AName : String) : Integer;
  78. Property OnGetAction : TGetActionEvent Read FOnGetAction Write FOnGetAction;
  79. Property Actions[Index : Integer] : TCustomWebAction Read GetActions Write SetActions; Default;
  80. end;
  81. TCustomHTTPModule = Class(TDataModule)
  82. public
  83. Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse); virtual; abstract;
  84. end;
  85. TCustomHTTPModuleClass = Class of TCustomHTTPModule;
  86. { TModuleItem }
  87. TModuleItem = Class(TCollectionItem)
  88. private
  89. FModuleClass: TCustomHTTPModuleClass;
  90. FModuleName: String;
  91. Public
  92. Property ModuleClass : TCustomHTTPModuleClass Read FModuleClass Write FModuleClass;
  93. Property ModuleName : String Read FModuleName Write FModuleName;
  94. end;
  95. { TModuleFactory }
  96. TModuleFactory = Class(TCollection)
  97. private
  98. function GetModule(Index : Integer): TModuleItem;
  99. procedure SetModule(Index : Integer; const AValue: TModuleItem);
  100. Public
  101. Function FindModule(AModuleName : String) : TModuleItem;
  102. Function ModuleByName(AModuleName : String) : TModuleItem;
  103. Function IndexOfModule(AModuleName : String) : Integer;
  104. Property Modules [Index : Integer]: TModuleItem Read GetModule Write SetModule;default;
  105. end;
  106. EFPHTTPError = Class(Exception);
  107. Procedure RegisterHTTPModule(ModuleClass : TCustomHTTPModuleClass);
  108. Procedure RegisterHTTPModule(Const ModuleName : String; ModuleClass : TCustomHTTPModuleClass);
  109. Var
  110. ModuleFactory : TModuleFactory;
  111. Resourcestring
  112. SErrNosuchModule = 'No such module registered: "%s"';
  113. SErrNoSuchAction = 'No action found for action: "%s"';
  114. SErrUnknownAction = 'Unknown action: "%s"';
  115. SErrNoDefaultAction = 'No action name and no default action';
  116. SErrRequestNotHandled = 'Web request was not handled by actions.';
  117. Implementation
  118. {$ifdef cgidebug}
  119. uses dbugintf;
  120. {$endif}
  121. { TModuleFactory }
  122. function TModuleFactory.GetModule(Index : Integer): TModuleItem;
  123. begin
  124. Result:=TModuleItem(Items[Index]);
  125. end;
  126. procedure TModuleFactory.SetModule(Index : Integer; const AValue: TModuleItem);
  127. begin
  128. Items[Index]:=AValue;
  129. end;
  130. function TModuleFactory.FindModule(AModuleName: String): TModuleItem;
  131. Var
  132. I : Integer;
  133. begin
  134. I:=IndexOfModule(AModuleName);
  135. If (I=-1) then
  136. Result:=Nil
  137. else
  138. Result:=GetModule(I);
  139. end;
  140. function TModuleFactory.ModuleByName(AModuleName: String): TModuleItem;
  141. begin
  142. Result:=FindModule(AModuleName);
  143. If (Result=Nil) then
  144. Raise EFPHTTPError.CreateFmt(SErrNosuchModule,[AModuleName]);
  145. end;
  146. function TModuleFactory.IndexOfModule(AModuleName: String): Integer;
  147. begin
  148. Result:=Count-1;
  149. While (Result>=0) and (CompareText(Modules[Result].ModuleName,AModuleName)<>0) do
  150. Dec(Result);
  151. end;
  152. procedure RegisterHTTPModule(ModuleClass: TCustomHTTPModuleClass);
  153. begin
  154. RegisterHTTPModule(ModuleClass.ClassName,ModuleClass);
  155. end;
  156. procedure RegisterHTTPModule(const ModuleName: String;
  157. ModuleClass: TCustomHTTPModuleClass);
  158. Var
  159. I : Integer;
  160. MI : TModuleItem;
  161. begin
  162. I:=ModuleFactory.IndexOfModule(ModuleName);
  163. If (I=-1) then
  164. begin
  165. MI:=ModuleFactory.Add as TModuleItem;
  166. MI.ModuleName:=ModuleName;
  167. end
  168. else
  169. MI:=ModuleFactory[I];
  170. MI.ModuleClass:=ModuleClass;
  171. end;
  172. { THTTPContentProducer }
  173. procedure THTTPContentProducer.HandleRequest(ARequest: TRequest;
  174. AResponse: TResponse; Var Handled : Boolean);
  175. begin
  176. If Assigned(FBeforeRequest) then
  177. FBeforeRequest(Self,ARequest);
  178. DoHandleRequest(Arequest,AResponse,Handled);
  179. If Assigned(FAfterResponse) then
  180. FAfterResponse(Self,AResponse);
  181. end;
  182. procedure THTTPContentProducer.GetContent(ARequest: TRequest; Content: TStream; Var Handled : Boolean);
  183. begin
  184. If Assigned(FBeforeRequest) then
  185. FBeforeRequest(Self,ARequest);
  186. DoGetContent(Arequest,Content,Handled);
  187. end;
  188. procedure THTTPContentProducer.DoHandleRequest(ARequest: TRequest;
  189. AResponse: TResponse; Var Handled : Boolean);
  190. Var
  191. M : TMemoryStream;
  192. begin
  193. M:=TMemoryStream.Create;
  194. DoGetContent(ARequest,M,Handled);
  195. AResponse.ContentStream:=M;
  196. end;
  197. procedure THTTPContentProducer.DoGetContent(ARequest: TRequest; Content: TStream; Var Handled : Boolean);
  198. begin
  199. Handled:=HaveContent;
  200. If Handled then
  201. ContentToStream(Content);
  202. end;
  203. function THTTPContentProducer.ProduceContent: String;
  204. begin
  205. Result:='';
  206. end;
  207. function THTTPContentProducer.HaveContent: Boolean;
  208. begin
  209. Result:=(ProduceContent<>'');
  210. end;
  211. procedure THTTPContentProducer.ContentToStream(Stream: TStream);
  212. Var
  213. S : String;
  214. begin
  215. S:=ProduceContent;
  216. If length(S)>0 then
  217. Stream.WriteBuffer(S[1],Length(S));
  218. end;
  219. { TCustomWebAction }
  220. procedure TCustomWebAction.SetContentProducer(const AValue: THTTPContentProducer
  221. );
  222. begin
  223. FContentProducer:=AValue;
  224. end;
  225. function TCustomWebAction.GetDisplayName: String;
  226. begin
  227. If (FName='') then
  228. FName:=ClassName+IntToStr(self.Index);
  229. Result:=FName;
  230. end;
  231. procedure TCustomWebAction.SetDisplayName(AValue: String);
  232. begin
  233. Inherited;
  234. FName:=AValue;
  235. end;
  236. procedure TCustomWebAction.HandleRequest(ARequest: TRequest; AResponse: TResponse; Var Handled : Boolean);
  237. begin
  238. If Assigned(FBeforeRequest) then
  239. FBeforeRequest(Self,ARequest);
  240. DoHandleRequest(Arequest,AResponse,Handled);
  241. If Assigned(FAfterResponse) then
  242. FAfterResponse(Self,AResponse);
  243. end;
  244. procedure TCustomWebAction.DoHandleRequest(ARequest: TRequest; AResponse: TResponse; Var Handled : Boolean);
  245. begin
  246. If Assigned(FContentProducer) then
  247. FContentProducer.HandleRequest(ARequest,AResponse,Handled)
  248. end;
  249. { TCustomWebActions }
  250. function TCustomWebActions.GetActions(Index : Integer): TCustomWebAction;
  251. begin
  252. Result:=TCustomWebAction(Items[Index]);
  253. end;
  254. procedure TCustomWebActions.SetActions(Index : Integer; const AValue: TCustomWebAction);
  255. begin
  256. Items[Index]:=AValue;
  257. end;
  258. Function TCustomWebActions.GetRequestAction(ARequest: TRequest) : TCustomWebAction;
  259. Var
  260. I : Integer;
  261. S : String;
  262. begin
  263. Result:=Nil;
  264. S:=GetActionName(ARequest);
  265. If (S<>'') then
  266. Result:=FindAction(S)
  267. else
  268. begin
  269. I:=0;
  270. While (Result=Nil) and (I<Count) do
  271. begin
  272. If Actions[i].Default then
  273. Result:=Actions[i];
  274. Inc(i);
  275. end;
  276. If (Result=Nil) then
  277. Raise EFPHTTPError.Create(SErrNoDefaultAction);
  278. end;
  279. end;
  280. function TCustomWebActions.GetActionName(ARequest: TRequest): String;
  281. begin
  282. If Assigned(FOnGetAction) then
  283. FOnGetAction(Self,ARequest,Result);
  284. If (Result='') then
  285. begin
  286. If (FActionVar<>'') then
  287. Result:=ARequest.QueryFields.Values[FActionVar];
  288. If (Result='') then
  289. Result:=ARequest.GetNextPathInfo;
  290. end;
  291. end;
  292. procedure TCustomWebActions.Assign(Source: TPersistent);
  293. begin
  294. If (Source is TCustomWebActions) then
  295. ActionVar:=(Source as TCustomWebActions).ActionVar
  296. else
  297. inherited Assign(Source);
  298. end;
  299. function TCustomWebActions.Add: TCustomWebAction;
  300. begin
  301. Result:=TCustomWebAction(Inherited Add);
  302. end;
  303. function TCustomWebActions.ActionByName(AName: String): TCustomWebAction;
  304. begin
  305. Result:=FindAction(AName);
  306. If (Result=Nil) then
  307. Raise HTTPError.CreateFmt(SErrUnknownAction,[AName]);
  308. end;
  309. function TCustomWebActions.FindAction(AName: String): TCustomWebAction;
  310. Var
  311. I : Integer;
  312. begin
  313. I:=IndexOfAction(AName);
  314. If (I=-1) then
  315. Result:=Nil
  316. else
  317. Result:=Actions[I];
  318. end;
  319. function TCustomWebActions.IndexOfAction(AName: String): Integer;
  320. begin
  321. Result:=Count-1;
  322. While (Result>=0) and (CompareText(Actions[Result].Name,AName)<>0) do
  323. Dec(Result);
  324. end;
  325. Initialization
  326. ModuleFactory:=TModuleFactory.Create(TModuleItem);
  327. Finalization
  328. FreeAndNil(ModuleFactory);
  329. end.