fphttp.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  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, httproute;
  16. Type
  17. { TODO : Implement wkSession }
  18. TWebModuleKind = (wkPooled, wkOneShot{, wkSession});
  19. { THTTPContentProducer }
  20. TWebActionEvent = Procedure (Sender : TObject;
  21. ARequest : TRequest;
  22. AResponse : TResponse;
  23. Var Handled : Boolean) of object;
  24. THTTPContentProducer = Class(TComponent)
  25. private
  26. FAfterResponse: TResponseEvent;
  27. FBeforeRequest: TRequestEvent;
  28. FRequest : TRequest;
  29. FResponse: TResponse;
  30. Protected
  31. Procedure DoHandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean); virtual;
  32. Procedure DoGetContent(ARequest : TRequest; Content : TStream; Var Handled : Boolean); virtual;
  33. Function ProduceContent : String; virtual;
  34. Procedure SetRequest(ARequest: TRequest);
  35. Protected
  36. Property BeforeRequest : TRequestEvent Read FBeforeRequest Write FBeforeRequest;
  37. Property AfterResponse : TResponseEvent Read FAfterResponse Write FAfterResponse;
  38. Public
  39. Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean);
  40. Procedure GetContent(ARequest : TRequest; Content : TStream; Var Handled : Boolean);
  41. Function HaveContent : Boolean; virtual;
  42. function ContentToStream(Stream : TStream) : boolean; virtual;
  43. Property Request : TRequest Read FRequest;
  44. Property Response : TResponse Read FResponse;
  45. end;
  46. { TCustomWebAction }
  47. TCustomWebAction = Class(TCollectionItem)
  48. private
  49. FAfterResponse: TResponseEvent;
  50. FBeforeRequest: TRequestEvent;
  51. FContentproducer: THTTPContentProducer;
  52. FDefault: Boolean;
  53. FName : String;
  54. Protected
  55. procedure SetContentProducer(const AValue: THTTPContentProducer);virtual;
  56. Function GetDisplayName : String; override;
  57. Procedure SetDisplayName(const AValue : String); override;
  58. Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean);
  59. Procedure DoHandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean); virtual;
  60. Public
  61. Function GetNamePath : String; override;
  62. published
  63. Property Name : String Read GetDisplayName Write SetDisplayName;
  64. Property ContentProducer : THTTPContentProducer Read FContentproducer Write SetContentProducer;
  65. Property Default : Boolean Read FDefault Write FDefault;
  66. Property BeforeRequest : TRequestEvent Read FBeforeRequest Write FBeforeRequest;
  67. Property AfterResponse : TResponseEvent Read FAfterResponse Write FAfterResponse;
  68. end;
  69. { TCustomWebActions }
  70. TGetActionEvent = Procedure (Sender : TObject; ARequest : TRequest; Var ActionName : String) of object;
  71. TCustomWebActions = Class(TCollection)
  72. private
  73. FActionVar : String;
  74. FDefActionWhenUnknown: Boolean;
  75. FOnGetAction: TGetActionEvent;
  76. function GetActions(Index : Integer): TCustomWebAction;
  77. procedure SetActions(Index : Integer; const AValue: TCustomWebAction);
  78. Protected
  79. Function GetRequestAction(ARequest: TRequest) : TCustomWebAction;
  80. Function GetActionName(ARequest : TRequest) : String;
  81. Property ActionVar : String Read FactionVar Write FActionVar;
  82. public
  83. constructor Create(AItemClass: TCollectionItemClass);
  84. Procedure Assign(Source : TPersistent); override;
  85. Function Add : TCustomWebAction;
  86. Function ActionByName(const AName : String) : TCustomWebAction;
  87. Function FindAction(const AName : String): TCustomWebAction;
  88. Function IndexOfAction(const AName : String) : Integer;
  89. Property OnGetAction : TGetActionEvent Read FOnGetAction Write FOnGetAction;
  90. Property Actions[Index : Integer] : TCustomWebAction Read GetActions Write SetActions; Default;
  91. Property DefActionWhenUnknown : Boolean read FDefActionWhenUnknown write FDefActionWhenUnknown;
  92. end;
  93. { TCustomHTTPModule }
  94. TInitModuleEvent = Procedure (Sender : TObject; ARequest : TRequest) of object;
  95. TCustomHTTPModule = Class(TDataModule)
  96. private
  97. FAfterInitModule : TInitModuleEvent;
  98. FBaseURL: String;
  99. FCORS: TCORSSupport;
  100. FWebModuleKind: TWebModuleKind;
  101. procedure SetCORS(AValue: TCORSSupport);
  102. Protected
  103. Class Function DefaultModuleName : String; virtual;
  104. Class Function DefaultSkipStreaming : Boolean; virtual;
  105. Class Function CreateCORSSUpport : TCORSSupport; virtual;
  106. Property CORS : TCORSSupport Read FCORS Write SetCORS;
  107. public
  108. Constructor CreateNew(aOwner : TComponent; CreateMode: Integer); overload; override;
  109. Class Procedure RegisterModule(Const AModuleName : String = ''); overload;
  110. Class Procedure RegisterModule(Const AModuleName : String; ASkipStreaming : Boolean); overload;
  111. Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse); virtual; abstract;
  112. Procedure DoAfterInitModule(ARequest : TRequest); virtual;
  113. property Kind: TWebModuleKind read FWebModuleKind write FWebModuleKind default wkPooled;
  114. Property BaseURL : String Read FBaseURL Write FBaseURL;
  115. Property AfterInitModule : TInitModuleEvent Read FAfterInitModule Write FAfterInitModule;
  116. end;
  117. TCustomHTTPModuleClass = Class of TCustomHTTPModule;
  118. { TSessionHTTPModule }
  119. TSessionHTTPModule = Class(TCustomHTTPModule)
  120. Private
  121. FCreateSession : Boolean;
  122. FOnNewSession: TNotifyEvent;
  123. FOnSessionExpired: TNotifyEvent;
  124. FSession: TCustomSession;
  125. FSessionRequest : TRequest;
  126. function GetSession: TCustomSession;
  127. procedure SetSession(const AValue: TCustomSession);
  128. Protected
  129. Procedure CheckSession(ARequest : TRequest);
  130. Procedure InitSession(AResponse : TResponse);
  131. Procedure UpdateSession(AResponse : TResponse);
  132. Procedure DoneSession; virtual;
  133. Procedure Notification(AComponent : TComponent;Operation : TOperation); override;
  134. Public
  135. destructor destroy; override;
  136. Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse); override;
  137. Property CreateSession : Boolean Read FCreateSession Write FCreateSession;
  138. Property Session : TCustomSession Read GetSession Write SetSession;
  139. Property OnNewSession : TNotifyEvent Read FOnNewSession Write FOnNewSession;
  140. Property OnSessionExpired : TNotifyEvent Read FOnSessionExpired Write FOnSessionExpired;
  141. end;
  142. TSessionHTTPModuleClass = Class of TSessionHTTPModule;
  143. EWebSessionError = Class(HTTPError);
  144. { TSessionFactory }
  145. TSessionFactory = Class(TComponent)
  146. private
  147. FSessionCookie: String;
  148. FSessionCookiePath: String;
  149. FTimeOut: Integer;
  150. FCleanupInterval: Integer;
  151. FDoneCount: Integer;
  152. protected
  153. // Override in descendants
  154. Function DoCreateSession(ARequest : TRequest) : TCustomSession; virtual; abstract;
  155. Procedure DoDoneSession(Var ASession : TCustomSession); virtual; abstract;
  156. Procedure DoCleanupSessions; virtual; abstract;
  157. Property DoneCount : Integer Read FDoneCount;
  158. Public
  159. Function CreateSession(ARequest : TRequest) : TCustomSession;
  160. Procedure DoneSession(Var ASession : TCustomSession);
  161. Procedure CleanupSessions;
  162. // Number of requests before sweeping sessions for stale sessions.
  163. // Default 1000. Set to 0 to disable.
  164. // Note that for cgi programs, this will never happen, since the count is reset to 0
  165. // with each invocation. It takes a special factory to handle that, or a value of 1.
  166. Property CleanupInterval : Integer read FCleanupInterval Write FCleanUpInterval;
  167. // Default timeout for sessions, in minutes.
  168. Property DefaultTimeOutMinutes : Integer Read FTimeOut Write FTimeOut;
  169. // Default session cookie.
  170. property SessionCookie : String Read FSessionCookie Write FSessionCookie;
  171. // Default session cookie path
  172. Property SessionCookiePath : String Read FSessionCookiePath write FSessionCookiePath;
  173. end;
  174. TSessionFactoryClass = Class of TSessionFactory;
  175. { TModuleItem }
  176. TModuleItem = Class(TCollectionItem, IRouteInterface)
  177. private
  178. FModuleClass: TCustomHTTPModuleClass;
  179. FModuleName: String;
  180. FSkipStreaming: Boolean;
  181. FRouteID : Integer;
  182. Protected
  183. procedure HandleRequest(ARequest: TRequest; AResponse: TResponse);
  184. // Route.ID+1
  185. Property RouteID : Integer Read FRouteID;
  186. Public
  187. Destructor Destroy; override;
  188. Property ModuleClass : TCustomHTTPModuleClass Read FModuleClass Write FModuleClass;
  189. Property ModuleName : String Read FModuleName Write FModuleName;
  190. Property SkipStreaming : Boolean Read FSkipStreaming Write FSkipStreaming;
  191. end;
  192. { TModuleFactory }
  193. TOnModuleRequest = Procedure (Sender : TModuleItem; ARequest: TRequest; AResponse: TResponse) of object;
  194. TModuleFactory = Class(TCollection)
  195. private
  196. FOnModuleRequest: TOnModuleRequest;
  197. function GetModule(Index : Integer): TModuleItem;
  198. procedure SetModule(Index : Integer; const AValue: TModuleItem);
  199. Protected
  200. procedure DoHandleRequest(Sender : TModuleItem; ARequest: TRequest; AResponse: TResponse);
  201. Public
  202. Procedure RegisterHTTPModule(Const ModuleName : String; ModuleClass : TCustomHTTPModuleClass; SkipStreaming : Boolean = False);virtual;
  203. Procedure RegisterHTTPModule(ModuleClass : TCustomHTTPModuleClass; SkipStreaming : Boolean = False);
  204. Function FindModule(const AModuleName : String) : TModuleItem;
  205. Function ModuleByName(const AModuleName : String) : TModuleItem;
  206. Function IndexOfModule(const AModuleName : String) : Integer;
  207. Procedure RemoveModule(const AModuleName : String);
  208. function MoveModuleBeforeDefault(const AModuleName: String): Boolean;
  209. Property Modules [Index : Integer]: TModuleItem Read GetModule Write SetModule;default;
  210. Property OnModuleRequest : TOnModuleRequest Read FOnModuleRequest Write FOnModuleRequest;
  211. end;
  212. { EFPHTTPError }
  213. EFPHTTPError = Class(EHTTP);
  214. Procedure RegisterHTTPModule(ModuleClass : TCustomHTTPModuleClass; SkipStreaming : Boolean = False);
  215. Procedure RegisterHTTPModule(Const ModuleName : String; ModuleClass : TCustomHTTPModuleClass; SkipStreaming : Boolean = False);
  216. Var
  217. ModuleFactory : TModuleFactory;
  218. SessionFactoryClass : TSessionFactoryClass = nil;
  219. Function SessionFactory : TSessionFactory;
  220. Resourcestring
  221. SErrNosuchModule = 'No such module registered: "%s"';
  222. SErrNoSuchAction = 'No action found for action: "%s"';
  223. SErrUnknownAction = 'Unknown action: "%s"';
  224. SErrNoDefaultAction = 'No action name and no default action';
  225. SErrInvActNoDefaultAction = 'Invalid action name and no default action';
  226. SErrRequestNotHandled = 'Web request was not handled by actions.';
  227. SErrNoSessionFactoryClass = 'No session manager class available. Include iniwebsession unit and recompile.';
  228. SErrNoSessionOutsideRequest = 'Default session not available outside handlerequest';
  229. Implementation
  230. {$ifdef cgidebug} uses dbugintf; {$endif}
  231. Var
  232. GSM : TSessionFactory;
  233. Function SessionFactory : TSessionFactory;
  234. begin
  235. if GSM=Nil then
  236. begin
  237. if (SessionFactoryClass=Nil) then
  238. Raise EFPHTTPError.Create(SErrNoSessionFactoryClass);
  239. GSM:=SessionFactoryClass.Create(Nil)
  240. end;
  241. Result:=GSM;
  242. end;
  243. { TModuleItem }
  244. procedure TModuleItem.HandleRequest(ARequest: TRequest; AResponse: TResponse);
  245. begin
  246. if (Collection is TModuleFactory) then
  247. (Collection as TModuleFactory).DoHandleRequest(Self,ARequest,AResponse);
  248. end;
  249. destructor TModuleItem.Destroy;
  250. begin
  251. if (FRouteID>0) then
  252. httprouter.DeleteRouteByID(FRouteID-1);
  253. inherited Destroy;
  254. end;
  255. { TCustomHTTPModule }
  256. procedure TCustomHTTPModule.SetCORS(AValue: TCORSSupport);
  257. begin
  258. if FCORS=AValue then Exit;
  259. FCORS.Assign(AValue);
  260. end;
  261. Class Function TCustomHTTPModule.DefaultModuleName: String;
  262. begin
  263. Result:=ClassName;
  264. end;
  265. Class Function TCustomHTTPModule.DefaultSkipStreaming: Boolean;
  266. begin
  267. Result:=False;
  268. end;
  269. class function TCustomHTTPModule.CreateCORSSUpport: TCORSSupport;
  270. begin
  271. Result:=TCORSSupport.Create;
  272. end;
  273. constructor TCustomHTTPModule.CreateNew(aOwner: TComponent; CreateMode: Integer);
  274. begin
  275. inherited CreateNew(aOwner, CreateMode);
  276. FCORS:=CreateCORSSupport;
  277. end;
  278. Class Procedure TCustomHTTPModule.RegisterModule(Const AModuleName: String);
  279. begin
  280. RegisterModule(AModuleName,DefaultSkipStreaming);
  281. end;
  282. Class Procedure TCustomHTTPModule.RegisterModule(Const AModuleName: String;
  283. ASkipStreaming: Boolean);
  284. Var
  285. MN : String;
  286. begin
  287. MN:=AModuleName;
  288. if MN='' then
  289. MN:=DefaultModuleName;
  290. RegisterHTTPModule(MN,Self,ASkipStreaming);
  291. end;
  292. Procedure TCustomHTTPModule.DoAfterInitModule(ARequest: TRequest);
  293. begin
  294. If Assigned(FAfterInitModule) then
  295. FAfterInitModule(Self, ARequest);
  296. end;
  297. { TSessionFactory }
  298. function TSessionFactory.CreateSession(ARequest: TRequest): TCustomSession;
  299. begin
  300. Result:=DoCreateSession(ARequest);
  301. if Assigned(Result) then
  302. begin
  303. if (FTimeOut<>0) then
  304. Result.TimeoutMinutes:=FTimeOut;
  305. Result.SessionCookie:=Self.SessionCookie;
  306. Result.SessionCookiePath:=Self.SessionCookiePath;
  307. end;
  308. end;
  309. procedure TSessionFactory.DoneSession(var ASession: TCustomSession);
  310. begin
  311. DoDoneSession(ASession);
  312. if (FCleanupInterval>0) then
  313. begin
  314. Inc(FDoneCount);
  315. If (FDoneCount>=FCleanupInterval) then
  316. CleanupSessions;
  317. end;
  318. end;
  319. procedure TSessionFactory.CleanupSessions;
  320. begin
  321. FDoneCount:=0;
  322. DoCleanupSessions;
  323. end;
  324. { TModuleFactory }
  325. function TModuleFactory.GetModule(Index : Integer): TModuleItem;
  326. begin
  327. Result:=TModuleItem(Items[Index]);
  328. end;
  329. procedure TModuleFactory.SetModule(Index : Integer; const AValue: TModuleItem);
  330. begin
  331. Items[Index]:=AValue;
  332. end;
  333. procedure TModuleFactory.DoHandleRequest(Sender: TModuleItem; ARequest: TRequest; AResponse: TResponse);
  334. begin
  335. If Assigned(OnModuleRequest) then
  336. OnModuleRequest(Sender,ARequest,AResponse)
  337. else
  338. Raise EFPHTTPError.Create('Cannot handle module request, OnModuleRequest not set');
  339. end;
  340. procedure TModuleFactory.RegisterHTTPModule(const ModuleName: String; ModuleClass: TCustomHTTPModuleClass; SkipStreaming: Boolean);
  341. Var
  342. I : Integer;
  343. MI : TModuleItem;
  344. begin
  345. I:=IndexOfModule(ModuleName);
  346. If (I=-1) then
  347. begin
  348. MI:=Add as TModuleItem;
  349. MI.ModuleName:=ModuleName;
  350. MI.FRouteID:=httprouter.RegisterRoute('/'+MI.FModuleName+'/*', MI as IRouteInterface,False).ID+1;
  351. end
  352. else
  353. MI:=ModuleFactory[I];
  354. MI.ModuleClass:=ModuleClass;
  355. MI.SkipStreaming:=SkipStreaming;
  356. end;
  357. procedure TModuleFactory.RegisterHTTPModule(ModuleClass: TCustomHTTPModuleClass; SkipStreaming: Boolean);
  358. begin
  359. RegisterHTTPModule(ModuleClass.DefaultModuleName,ModuleClass,SkipStreaming);
  360. end;
  361. function TModuleFactory.FindModule(const AModuleName: String): TModuleItem;
  362. Var
  363. I : Integer;
  364. begin
  365. I:=IndexOfModule(AModuleName);
  366. If (I=-1) then
  367. Result:=Nil
  368. else
  369. Result:=GetModule(I);
  370. end;
  371. function TModuleFactory.ModuleByName(const AModuleName: String): TModuleItem;
  372. begin
  373. Result:=FindModule(AModuleName);
  374. If (Result=Nil) then
  375. Raise EFPHTTPError.CreateFmt(SErrNosuchModule,[AModuleName]);
  376. end;
  377. function TModuleFactory.IndexOfModule(const AModuleName: String): Integer;
  378. begin
  379. Result:=Count-1;
  380. While (Result>=0) and (CompareText(Modules[Result].ModuleName,AModuleName)<>0) do
  381. Dec(Result);
  382. end;
  383. procedure TModuleFactory.RemoveModule(const AModuleName: String);
  384. Var
  385. aRouteID,Idx : Integer;
  386. begin
  387. Idx:=IndexOfModule(aModuleName);
  388. if Idx<>-1 then
  389. begin
  390. aRouteID:=Modules[Idx].RouteID;
  391. HTTPRouter.DeleteRouteByID(aRouteID);
  392. Delete(Idx);
  393. end;
  394. end;
  395. function TModuleFactory.MoveModuleBeforeDefault(const AModuleName: String) : Boolean;
  396. begin
  397. Result:=HTTPRouter.MoveRouteBeforeDefault(ModuleByName(aModuleName).RouteID-1);
  398. end;
  399. procedure RegisterHTTPModule(ModuleClass: TCustomHTTPModuleClass; SkipStreaming : Boolean = False);
  400. begin
  401. ModuleFactory.RegisterHTTPModule(ModuleClass,SkipStreaming);
  402. end;
  403. procedure RegisterHTTPModule(const ModuleName: String;
  404. ModuleClass: TCustomHTTPModuleClass; SkipStreaming : Boolean = False);
  405. begin
  406. ModuleFactory.RegisterHTTPModule(ModuleName,ModuleClass,SkipStreaming);
  407. end;
  408. { THTTPContentProducer }
  409. procedure THTTPContentProducer.HandleRequest(ARequest: TRequest;
  410. AResponse: TResponse; Var Handled : Boolean);
  411. begin
  412. If Assigned(FBeforeRequest) then
  413. FBeforeRequest(Self,ARequest);
  414. DoHandleRequest(Arequest,AResponse,Handled);
  415. If Assigned(FAfterResponse) then
  416. FAfterResponse(Self,AResponse);
  417. end;
  418. procedure THTTPContentProducer.GetContent(ARequest: TRequest; Content: TStream; Var Handled : Boolean);
  419. begin
  420. If Assigned(FBeforeRequest) then
  421. FBeforeRequest(Self,ARequest);
  422. DoGetContent(Arequest,Content,Handled);
  423. end;
  424. procedure THTTPContentProducer.DoHandleRequest(ARequest: TRequest;
  425. AResponse: TResponse; Var Handled : Boolean);
  426. Var
  427. M : TMemoryStream;
  428. begin
  429. FResponse:=AResponse;
  430. M:=TMemoryStream.Create;
  431. DoGetContent(ARequest,M,Handled);
  432. AResponse.ContentStream:=M;
  433. AResponse.ContentLength:=M.Size;
  434. end;
  435. procedure THTTPContentProducer.DoGetContent(ARequest: TRequest; Content: TStream; Var Handled : Boolean);
  436. begin
  437. FRequest := ARequest;
  438. Handled:=ContentToStream(Content);
  439. end;
  440. function THTTPContentProducer.ProduceContent: String;
  441. begin
  442. Result:='';
  443. end;
  444. procedure THTTPContentProducer.SetRequest(ARequest: TRequest);
  445. begin
  446. FRequest := ARequest;
  447. end;
  448. function THTTPContentProducer.HaveContent: Boolean;
  449. begin
  450. Result:=(ProduceContent<>'');
  451. end;
  452. function THTTPContentProducer.ContentToStream(Stream: TStream) : boolean;
  453. Var
  454. S : String;
  455. begin
  456. S:=ProduceContent;
  457. If length(S)>0 then
  458. begin
  459. Stream.WriteBuffer(S[1],Length(S));
  460. Result := True;
  461. end
  462. else
  463. Result := False;
  464. end;
  465. { TCustomWebAction }
  466. procedure TCustomWebAction.SetContentProducer(const AValue: THTTPContentProducer
  467. );
  468. begin
  469. FContentProducer:=AValue;
  470. end;
  471. function TCustomWebAction.GetDisplayName: String;
  472. begin
  473. Result:=FName;
  474. If (Result='') then
  475. begin
  476. Result:=ClassName+IntToStr(self.Index);
  477. if Result[1]='T' then
  478. Delete(Result,1,1)
  479. end;
  480. end;
  481. Function TCustomWebAction.GetNamePath : String;
  482. begin
  483. Result:=FName;
  484. If (Result='') then
  485. FName:=ClassName+IntToStr(self.Index);
  486. end;
  487. procedure TCustomWebAction.SetDisplayName(const AValue: String);
  488. begin
  489. Inherited;
  490. FName:=AValue;
  491. end;
  492. procedure TCustomWebAction.HandleRequest(ARequest: TRequest; AResponse: TResponse; Var Handled : Boolean);
  493. begin
  494. If Assigned(FBeforeRequest) then
  495. FBeforeRequest(Self,ARequest);
  496. DoHandleRequest(Arequest,AResponse,Handled);
  497. If Assigned(FAfterResponse) then
  498. FAfterResponse(Self,AResponse);
  499. end;
  500. procedure TCustomWebAction.DoHandleRequest(ARequest: TRequest; AResponse: TResponse; Var Handled : Boolean);
  501. begin
  502. If Assigned(FContentProducer) then
  503. FContentProducer.HandleRequest(ARequest,AResponse,Handled)
  504. end;
  505. { TCustomWebActions }
  506. function TCustomWebActions.GetActions(Index : Integer): TCustomWebAction;
  507. begin
  508. Result:=TCustomWebAction(Items[Index]);
  509. end;
  510. procedure TCustomWebActions.SetActions(Index : Integer; const AValue: TCustomWebAction);
  511. begin
  512. Items[Index]:=AValue;
  513. end;
  514. Function TCustomWebActions.GetRequestAction(ARequest: TRequest) : TCustomWebAction;
  515. Var
  516. S : String;
  517. Function GetDefaultAction:TCustomWebAction;
  518. Var I : Integer;
  519. begin
  520. Result := nil;
  521. I:=0;
  522. While (Result=Nil) and (I<Count) do
  523. begin
  524. If Actions[I].Default then
  525. Result:=Actions[I];
  526. Inc(I);
  527. end;
  528. end;
  529. begin
  530. Result:=Nil;
  531. S:=GetActionName(ARequest);
  532. If (S<>'') then
  533. begin
  534. Result:=FindAction(S);
  535. if Result = nil then
  536. begin//no action with that name found
  537. if not DefActionWhenUnknown then
  538. Raise EFPHTTPError.CreateFmt(SErrNoSuchAction,[s])
  539. else begin
  540. Result := GetDefaultAction;
  541. if Result = nil then
  542. Raise EFPHTTPError.Create(SErrInvActNoDefaultAction);
  543. end;
  544. end;
  545. end else begin //no action name was specified
  546. Result := GetDefaultAction;
  547. If (Result=Nil) then
  548. Raise EFPHTTPError.Create(SErrNoDefaultAction);
  549. end;
  550. end;
  551. function TCustomWebActions.GetActionName(ARequest: TRequest): String;
  552. begin
  553. If (FActionVar<>'') then
  554. Result:=ARequest.QueryFields.Values[FActionVar]
  555. else
  556. Result := '';
  557. If Assigned(FOnGetAction) then
  558. FOnGetAction(Self,ARequest,Result);
  559. // GetNextPathInfo is only used after OnGetAction, so that the call to
  560. // GetNextPathInfo can be avoided in the event.
  561. If (Result='') then
  562. Result:=ARequest.GetNextPathInfo;
  563. end;
  564. constructor TCustomWebActions.Create(AItemClass: TCollectionItemClass);
  565. begin
  566. inherited Create(AItemClass);
  567. FDefActionWhenUnknown:=True;
  568. end;
  569. procedure TCustomWebActions.Assign(Source: TPersistent);
  570. begin
  571. If (Source is TCustomWebActions) then
  572. ActionVar:=(Source as TCustomWebActions).ActionVar
  573. else
  574. inherited Assign(Source);
  575. end;
  576. function TCustomWebActions.Add: TCustomWebAction;
  577. begin
  578. Result:=TCustomWebAction(Inherited Add);
  579. end;
  580. function TCustomWebActions.ActionByName(const AName: String): TCustomWebAction;
  581. begin
  582. Result:=FindAction(AName);
  583. If (Result=Nil) then
  584. Raise HTTPError.CreateFmt(SErrUnknownAction,[AName]);
  585. end;
  586. function TCustomWebActions.FindAction(const AName: String): TCustomWebAction;
  587. Var
  588. I : Integer;
  589. begin
  590. I:=IndexOfAction(AName);
  591. If (I=-1) then
  592. Result:=Nil
  593. else
  594. Result:=Actions[I];
  595. end;
  596. function TCustomWebActions.IndexOfAction(const AName: String): Integer;
  597. begin
  598. Result:=Count-1;
  599. While (Result>=0) and (CompareText(Actions[Result].Name,AName)<>0) do
  600. Dec(Result);
  601. end;
  602. function TSessionHTTPModule.GetSession: TCustomSession;
  603. begin
  604. {$ifdef cgidebug}SendMethodEnter('SessionHTTPModule.GetSession');{$endif}
  605. If (csDesigning in ComponentState) then
  606. begin
  607. {$ifdef cgidebug}SendDebug('Sending session');{$endif}
  608. Result:=FSession
  609. end
  610. else
  611. begin
  612. If (FSession=Nil) then
  613. begin
  614. {$ifdef cgidebug}SendDebug('Getting default session');{$endif}
  615. if (FSessionRequest=Nil) then
  616. Raise EFPHTTPError.Create(SErrNoSessionOutsideRequest);
  617. FSession:=SessionFactory.CreateSession(FSessionRequest);
  618. FSession.FreeNotification(Self);
  619. end;
  620. Result:=FSession
  621. end;
  622. {$ifdef cgidebug}SendMethodExit('SessionHTTPModule.GetSession');{$endif}
  623. end;
  624. procedure TSessionHTTPModule.SetSession(const AValue: TCustomSession);
  625. begin
  626. if FSession<>AValue then
  627. begin
  628. If Assigned(FSession) then
  629. FSession.RemoveFreeNotification(Self);
  630. FSession:=AValue;
  631. If Assigned(FSession) then
  632. FSession.FreeNotification(Self);
  633. end;
  634. end;
  635. procedure TSessionHTTPModule.CheckSession(ARequest : TRequest);
  636. begin
  637. {$ifdef cgidebug}SendMethodEnter('SessionHTTPModule('+Name+').CheckSession');{$endif}
  638. If CreateSession then
  639. begin
  640. If (FSession=Nil) then
  641. FSession:=SessionFactory.CreateSession(ARequest);
  642. if Assigned(FSession) then
  643. FSession.InitSession(ARequest,FOnNewSession,FOnSessionExpired);
  644. end;
  645. {$ifdef cgidebug}SendMethodExit('SessionHTTPModule('+Name+').CheckSession');{$endif}
  646. end;
  647. procedure TSessionHTTPModule.InitSession(AResponse: TResponse);
  648. begin
  649. {$ifdef cgidebug}SendMethodEnter('SessionHTTPModule('+Name+').InitSession');{$endif}
  650. If CreateSession and Assigned(FSession) then
  651. FSession.InitResponse(AResponse);
  652. {$ifdef cgidebug}SendMethodExit('SessionHTTPModule('+Name+').InitSession');{$endif}
  653. end;
  654. procedure TSessionHTTPModule.UpdateSession(AResponse: TResponse);
  655. begin
  656. If CreateSession And Assigned(FSession) then
  657. FSession.UpdateResponse(AResponse);
  658. end;
  659. procedure TSessionHTTPModule.DoneSession;
  660. begin
  661. // Session manager may or may not destroy the session.
  662. // Check if we actually have
  663. if Assigned(FSession) then
  664. SessionFactory.DoneSession(FSession);
  665. // In each case, our reference is no longer valid.
  666. FSession:=Nil;
  667. end;
  668. destructor TSessionHTTPModule.destroy;
  669. begin
  670. // Prevent memory leaks.
  671. DoneSession;
  672. inherited destroy;
  673. end;
  674. procedure TSessionHTTPModule.Notification(AComponent: TComponent;
  675. Operation: TOperation);
  676. begin
  677. {$ifdef cgidebug}SendMethodEnter('SessionHTTPModule('+Name+').Notification');{$endif}
  678. inherited Notification(AComponent, Operation);
  679. If (Operation=opRemove) then
  680. if (AComponent=FSession) Then
  681. FSession:=Nil;
  682. {$ifdef cgidebug}SendMethodExit('SessionHTTPModule('+Name+').Notification');{$endif}
  683. end;
  684. procedure TSessionHTTPModule.HandleRequest(ARequest: TRequest;
  685. AResponse: TResponse);
  686. begin
  687. FSessionRequest:=ARequest;
  688. end;
  689. Initialization
  690. ModuleFactory:=TModuleFactory.Create(TModuleItem);
  691. Finalization
  692. FreeAndNil(ModuleFactory);
  693. FreeAndNil(GSM);
  694. end.