brookfclhttpappbroker.pas 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. (*
  2. Brook for Free Pascal
  3. Copyright (C) 2014-2019 Mario Ray Mahardhika
  4. See the file LICENSE.txt, included in this distribution,
  5. for details about the copyright.
  6. This library is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. *)
  10. { FCL HTTPApp broker. }
  11. unit BrookFCLHttpAppBroker;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses
  15. BrookClasses, BrookApplication, BrookLog, BrookRouter, BrookUtils,
  16. BrookConsts, BrookHttpConsts, BrookHttpDefsBroker, BrookMessages, HttpDefs,
  17. CustWeb, CustHttpApp, FPHttpServer, Classes, SysUtils;
  18. type
  19. TBrookHttpApplication = class;
  20. { TBrookApplication }
  21. TBrookApplication = class(TBrookInterfacedObject, IBrookApplication)
  22. private
  23. FApp: TBrookHttpApplication;
  24. function GetTerminated: Boolean;
  25. public
  26. constructor Create; virtual;
  27. destructor Destroy; override;
  28. procedure CreateForm(AInstanceClass: TComponentClass; out AReference);
  29. function Instance: TObject;
  30. procedure Run;
  31. procedure Terminate;
  32. property Terminated: Boolean read GetTerminated;
  33. end;
  34. { TBrookHttpApplication }
  35. TBrookHttpApplication = class(TCustomHttpApplication)
  36. private
  37. FShowTermMsg: Boolean;
  38. protected
  39. function InitializeWebHandler: TWebHandler; override;
  40. public
  41. property ShowTermMsg: Boolean read FShowTermMsg write FShowTermMsg;
  42. end;
  43. { TBrookHttpConnectionRequest }
  44. TBrookHttpConnectionRequest = class(TFPHttpConnectionRequest)
  45. protected
  46. procedure DeleteTempUploadedFiles; override;
  47. function GetTempUploadFileName(const AName, AFileName: string;
  48. ASize: Int64): string; override;
  49. function RequestUploadDir: string; override;
  50. procedure InitRequestVars; override;
  51. end;
  52. { TBrookHttpConnectionResponse }
  53. TBrookHttpConnectionResponse = class(TFPHttpConnectionResponse)
  54. protected
  55. procedure CollectHeaders(AHeaders: TStrings); override;
  56. end;
  57. { TBrookEmbeddedHttpServer }
  58. TBrookEmbeddedHttpServer = class(TEmbeddedHttpServer)
  59. protected
  60. function CreateRequest: TFPHttpConnectionRequest; override;
  61. function CreateResponse(
  62. ARequest: TFPHttpConnectionRequest): TFPHttpConnectionResponse; override;
  63. end;
  64. { TBrookHttpServerHandler }
  65. TBrookHttpServerHandler = class(TFPHttpServerHandler)
  66. protected
  67. function CreateServer: TEmbeddedHttpServer; override;
  68. public
  69. procedure HandleRequest(ARequest: TRequest; AResponse: TResponse); override;
  70. procedure ShowRequestException(R: TResponse; E: Exception); override;
  71. end;
  72. var
  73. SBrookHttpServerTerminalMsg: string =
  74. 'Open the ''%s'' URL in your browser.'
  75. {$IFDEF UNIX} + LineEnding + LineEnding + 'Use [Ctrl+C] to quit ...'{$ENDIF};
  76. function BrookHttpServerTerminalMsg: string;
  77. implementation
  78. function BrookHttpServerTerminalMsg: string;
  79. var
  80. VUrl: string;
  81. begin
  82. if BrookSettings.RootUrl = '' then
  83. VUrl := 'http://localhost'
  84. else
  85. VUrl := BrookSettings.RootUrl;
  86. if VUrl[Length(VUrl)] = US then
  87. System.Delete(VUrl, Length(VUrl), 1);
  88. if not (BrookSettings.Port in [0, 80]) then
  89. VUrl += ':' + IntToStr(BrookSettings.Port);
  90. Result := Format(SBrookHttpServerTerminalMsg, [VUrl]);
  91. end;
  92. { TBrookApplication }
  93. function TBrookApplication.GetTerminated: Boolean;
  94. begin
  95. Result := FApp.Terminated;
  96. end;
  97. constructor TBrookApplication.Create;
  98. begin
  99. FApp := TBrookHttpApplication.Create(nil);
  100. FApp.Initialize;
  101. FApp.ShowTermMsg := System.IsConsole;
  102. end;
  103. destructor TBrookApplication.Destroy;
  104. begin
  105. FApp.Free;
  106. inherited Destroy;
  107. end;
  108. procedure TBrookApplication.CreateForm(AInstanceClass: TComponentClass;
  109. out AReference);
  110. var
  111. VReference: TComponent;
  112. begin
  113. VReference := AInstanceClass.Create(nil);
  114. TComponent(AReference) := VReference;
  115. FApp.InsertComponent(VReference);
  116. end;
  117. function TBrookApplication.Instance: TObject;
  118. begin
  119. Result := FApp;
  120. end;
  121. procedure TBrookApplication.Run;
  122. begin
  123. if BrookSettings.Port <> 0 then
  124. FApp.Port := BrookSettings.Port;
  125. if BrookSettings.RootUrl <> '' then
  126. FApp.ApplicationURL := BrookSettings.RootUrl;
  127. if FApp.ShowTermMsg then
  128. WriteLn(BrookHttpServerTerminalMsg);
  129. FApp.Run;
  130. end;
  131. procedure TBrookApplication.Terminate;
  132. begin
  133. FApp.Terminate;
  134. end;
  135. { TBrookHttpApplication }
  136. function TBrookHttpApplication.InitializeWebHandler: TWebHandler;
  137. begin
  138. Result := TBrookHttpServerHandler.Create(Self);
  139. end;
  140. { TBrookHttpConnectionRequest }
  141. procedure TBrookHttpConnectionRequest.DeleteTempUploadedFiles;
  142. begin
  143. if BrookSettings.DeleteUploadedFiles then
  144. inherited;
  145. end;
  146. function TBrookHttpConnectionRequest.GetTempUploadFileName(const AName,
  147. AFileName: string; ASize: Int64): string;
  148. begin
  149. if BrookSettings.KeepUploadedNames then
  150. Result := RequestUploadDir + AFileName
  151. else
  152. Result := inherited GetTempUploadFileName(AName, AFileName, ASize);
  153. end;
  154. function TBrookHttpConnectionRequest.RequestUploadDir: string;
  155. begin
  156. Result := BrookSettings.DirectoryForUploads;
  157. if Result = '' then
  158. Result := GetTempDir;
  159. Result := IncludeTrailingPathDelimiter(Result);
  160. end;
  161. procedure TBrookHttpConnectionRequest.InitRequestVars;
  162. var
  163. VMethod: string;
  164. begin
  165. VMethod := Method;
  166. if VMethod = ES then
  167. raise Exception.Create(SBrookNoRequestMethodError);
  168. case VMethod of
  169. BROOK_HTTP_REQUEST_METHOD_DELETE, BROOK_HTTP_REQUEST_METHOD_PUT,
  170. BROOK_HTTP_REQUEST_METHOD_PATCH:
  171. begin
  172. InitPostVars;
  173. if HandleGetOnPost then
  174. InitGetVars;
  175. end;
  176. else
  177. inherited;
  178. end;
  179. end;
  180. { TBrookHttpConnectionResponse }
  181. procedure TBrookHttpConnectionResponse.CollectHeaders(AHeaders: TStrings);
  182. begin
  183. AHeaders.Add(BROOK_HTTP_HEADER_X_POWERED_BY + HS +
  184. 'Brook for Free Pascal and FCL-Web.');
  185. inherited CollectHeaders(AHeaders);
  186. end;
  187. { TBrookEmbeddedHttpServer }
  188. function TBrookEmbeddedHttpServer.CreateRequest: TFPHttpConnectionRequest;
  189. begin
  190. Result := TBrookHttpConnectionRequest.Create;
  191. end;
  192. function TBrookEmbeddedHttpServer.CreateResponse(
  193. ARequest: TFPHttpConnectionRequest): TFPHttpConnectionResponse;
  194. begin
  195. Result := TBrookHttpConnectionResponse.Create(ARequest);
  196. end;
  197. { TBrookHttpServerHandler }
  198. function TBrookHttpServerHandler.CreateServer: TEmbeddedHttpServer;
  199. begin
  200. Result := TBrookEmbeddedHttpServer.Create(Self);
  201. end;
  202. procedure TBrookHttpServerHandler.HandleRequest(ARequest: TRequest;
  203. AResponse: TResponse);
  204. var
  205. VLog: string;
  206. begin
  207. AResponse.ContentType := BrookFormatContentType;
  208. if BrookSettings.LogActive then
  209. begin
  210. VLog := LineEnding;
  211. if ARequest.PathInfo <> ES then
  212. VLog += '<PathInfo>' + LineEnding + ARequest.PathInfo + LineEnding +
  213. '</PathInfo>' + LineEnding;
  214. if ARequest.CookieFields.Count > 0 then
  215. VLog += '<Cookies>' + LineEnding + ARequest.CookieFields.Text +
  216. '</Cookies>' + LineEnding;
  217. if ARequest.ContentFields.Count > 0 then
  218. VLog += '<Fields>' + LineEnding + ARequest.ContentFields.Text +
  219. '</Fields>' + LineEnding;
  220. if ARequest.QueryFields.Count > 0 then
  221. VLog += '<Params>' + LineEnding + ARequest.QueryFields.Text +
  222. '</Params>' + LineEnding;
  223. end;
  224. try
  225. TBrookRouter.Service.Route(ARequest, AResponse);
  226. TBrookHttpConnectionRequest(ARequest).DeleteTempUploadedFiles;
  227. if BrookSettings.LogActive and (AResponse.Contents.Count > 0) then
  228. begin
  229. VLog += '<Content>' + LineEnding + AResponse.Contents.Text +
  230. '</Content>';
  231. TBrookLogger.Service.Info(VLog);
  232. end;
  233. except
  234. on E: Exception do
  235. begin
  236. if BrookSettings.LogActive then
  237. TBrookLogger.Service.Error(VLog, E);
  238. ShowRequestException(AResponse, E);
  239. end;
  240. end;
  241. end;
  242. procedure TBrookHttpServerHandler.ShowRequestException(R: TResponse; E: Exception);
  243. begin
  244. BrookShowRequestException(Self, R, E);
  245. end;
  246. initialization
  247. BrookRegisterApp(TBrookApplication.Create);
  248. finalization
  249. BrookUnregisterApp;
  250. end.