Quick.HttpClient.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. { ***************************************************************************
  2. Copyright (c) 2016-2018 Kike Pérez
  3. Unit : Quick.HttpClient
  4. Description : Json Http Client
  5. Author : Kike Pérez
  6. Version : 1.1
  7. Created : 22/05/2018
  8. Modified : 27/05/2018
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.HttpClient;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. Classes,
  26. SysUtils,
  27. {$IFDEF DELPHIXE8_UP}
  28. System.Net.HttpClient,
  29. System.Net.URLClient,
  30. System.NetConsts,
  31. System.JSON;
  32. {$ELSE}
  33. {$IFDEF DELPHIXE7_UP}
  34. System.JSON,
  35. {$ENDIF}
  36. IdHTTP,
  37. IdException,
  38. {$IFDEF FPC}
  39. fpjson;
  40. {$ELSE}
  41. Data.DBXJSON;
  42. {$ENDIF}
  43. {$ENDIF}
  44. type
  45. IHttpRequestResponse = interface
  46. ['{64DC58F7-B551-4619-85E9-D13E781529CD}']
  47. function StatusCode : Integer;
  48. function StatusText : string;
  49. function Response : TJSONObject;
  50. end;
  51. THttpRequestResponse = class(TInterfacedObject,IHttpRequestResponse)
  52. private
  53. fStatusCode : Integer;
  54. fStatusText : string;
  55. fResponse : TJSONObject;
  56. public
  57. {$IFDEF DELPHIXE8_UP}
  58. constructor Create(aResponse : IHTTPResponse; const aContent : string);
  59. {$ELSE}
  60. constructor Create(aResponse : TIdHTTPResponse; const aContent : string);
  61. {$ENDIF}
  62. destructor Destroy; override;
  63. function StatusCode : Integer;
  64. function StatusText : string;
  65. function Response : TJSONObject;
  66. end;
  67. TJsonHttpClient = class
  68. private
  69. {$IFDEF DELPHIXE8_UP}
  70. fHTTPClient : System.Net.HttpClient.THTTPClient;
  71. {$ELSE}
  72. fHTTPClient : TIdHTTP;
  73. {$ENDIF}
  74. fUserAgent : string;
  75. fContentType : string;
  76. fResponseTimeout : Integer;
  77. fConnectionTimeout : Integer;
  78. fHandleRedirects : Boolean;
  79. procedure SetContentType(const aValue: string);
  80. procedure SetUserAgent(const aValue: string);
  81. procedure SetResponseTimeout(const aValue: Integer);
  82. procedure SetConnectionTimeout(const aValue: Integer);
  83. procedure SetHandleRedirects(const aValue: Boolean);
  84. public
  85. constructor Create;
  86. destructor Destroy; override;
  87. property UserAgent : string read fUserAgent write SetUserAgent;
  88. property ContentType : string read fContentType write SetContentType;
  89. property ResponseTimeout : Integer read fResponseTimeout write SetResponseTimeout;
  90. property ConnectionTimeout : Integer read fConnectionTimeout write SetConnectionTimeout;
  91. property HandleRedirects : Boolean read fHandleRedirects write SetHandleRedirects;
  92. function Get(const aURL : string) : IHttpRequestResponse;
  93. function Post(const aURL, aInContent : string) : IHttpRequestResponse; overload;
  94. function Post(const aURL : string; aInContent : TStream) : IHttpRequestResponse; overload;
  95. function Post(const aURL : string; aJsonContent : TJsonObject) : IHttpRequestResponse; overload;
  96. function Put(const aURL, aInContent : string) : IHttpRequestResponse;
  97. end;
  98. implementation
  99. const
  100. DEF_USER_AGENT = 'XLHttpClient';
  101. constructor TJsonHttpClient.Create;
  102. begin
  103. {$IFDEF DELPHIXE8_UP}
  104. fHTTPClient := THTTPClient.Create;
  105. fHTTPClient.ContentType := 'application/json';
  106. fHTTPClient.UserAgent := DEF_USER_AGENT;
  107. {$ELSE}
  108. fHTTPClient := TIdHTTP.Create(nil);
  109. fHTTPClient.Request.ContentType := 'application/json';
  110. fHTTPClient.Request.UserAgent := DEF_USER_AGENT;
  111. {$ENDIF}
  112. end;
  113. destructor TJsonHttpClient.Destroy;
  114. begin
  115. fHTTPClient.Free;
  116. inherited;
  117. end;
  118. function TJsonHttpClient.Get(const aURL : string) : IHttpRequestResponse;
  119. var
  120. {$IFDEF DELPHIXE8_UP}
  121. resp : IHTTPResponse;
  122. {$ELSE}
  123. resp : TIdHTTPResponse;
  124. {$ENDIF}
  125. bodycontent : TStringStream;
  126. responsecontent : TStringStream;
  127. begin
  128. bodycontent := TStringStream.Create;
  129. try
  130. responsecontent := TStringStream.Create;
  131. try
  132. {$IFDEF DELPHIXE8_UP}
  133. resp := fHTTPClient.Get(aURL,responsecontent,nil);
  134. {$ELSE}
  135. {$If Defined(FPC) OR Not Defined(DELPHIXE8_UP)}
  136. fHTTPClient.Get(aURL,responsecontent);
  137. {$ELSE}
  138. fHTTPClient.Get(aURL,responsecontent,nil);
  139. {$ENDIF}
  140. resp := fHTTPClient.Response;
  141. {$ENDIF}
  142. Result := THttpRequestResponse.Create(resp,responsecontent.DataString);
  143. finally
  144. responsecontent.Free;
  145. end;
  146. finally
  147. bodycontent.Free;
  148. end;
  149. end;
  150. function TJsonHttpClient.Post(const aURL, aInContent : string) : IHttpRequestResponse;
  151. var
  152. {$IFDEF DELPHIXE8_UP}
  153. resp : IHTTPResponse;
  154. {$ELSE}
  155. resp : TIdHTTPResponse;
  156. {$ENDIF}
  157. responsecontent : TStringStream;
  158. postcontent : TStringStream;
  159. begin
  160. postcontent := TStringStream.Create(Utf8Encode(aInContent));
  161. try
  162. //postcontent.WriteString(aInContent);
  163. responsecontent := TStringStream.Create;
  164. try
  165. {$IFDEF DELPHIXE8_UP}
  166. resp := fHTTPClient.Post(aURL,postcontent,responsecontent);
  167. {$ELSE}
  168. {$IFDEF FPC}
  169. try
  170. fHTTPClient.Post(aURL,postcontent,responsecontent);
  171. fHTTPClient.Disconnect(False);
  172. except
  173. on E : Exception do
  174. begin
  175. if e.ClassType <> EIdConnClosedGracefully then raise e;
  176. end;
  177. end;
  178. {$ELSE}
  179. fHTTPClient.Post(aURL,postcontent,responsecontent);
  180. {$ENDIF}
  181. resp := fHTTPClient.Response;
  182. {$ENDIF}
  183. Result := THttpRequestResponse.Create(resp,responsecontent.DataString);
  184. finally
  185. responsecontent.Free;
  186. end;
  187. finally
  188. postcontent.Free;
  189. end;
  190. end;
  191. function TJsonHttpClient.Post(const aURL : string; aInContent : TStream) : IHttpRequestResponse;
  192. var
  193. {$IFDEF DELPHIXE8_UP}
  194. resp : IHTTPResponse;
  195. {$ELSE}
  196. resp : TIdHTTPResponse;
  197. {$ENDIF}
  198. responsecontent : TStringStream;
  199. begin
  200. //postcontent.WriteString(aInContent);
  201. responsecontent := TStringStream.Create;
  202. try
  203. {$IFDEF DELPHIXE8_UP}
  204. resp := fHTTPClient.Post(aURL,aInContent,responsecontent);
  205. {$ELSE}
  206. {$IFDEF FPC}
  207. try
  208. fHTTPClient.Post(aURL,aInContent,responsecontent);
  209. fHTTPClient.Disconnect(False);
  210. except
  211. on E : Exception do
  212. begin
  213. if e.ClassType <> EIdConnClosedGracefully then raise e;
  214. end;
  215. end;
  216. {$ELSE}
  217. fHTTPClient.Post(aURL,aInContent,responsecontent);
  218. {$ENDIF}
  219. resp := fHTTPClient.Response;
  220. {$ENDIF}
  221. Result := THttpRequestResponse.Create(resp,responsecontent.DataString);
  222. finally
  223. responsecontent.Free;
  224. end;
  225. end;
  226. function TJsonHttpClient.Post(const aURL : string; aJsonContent : TJsonObject) : IHttpRequestResponse;
  227. begin
  228. {$IFDEF DELPHIXE8_UP}
  229. Result := Self.Post(aURL,aJsonContent.ToJSON);
  230. {$ELSE}
  231. {$IFDEF FPC}
  232. Result := Self.Post(aURL,aJsonContent.AsJson);
  233. {$ELSE}
  234. Result := Self.Post(aURL,aJsonContent.ToString);
  235. {$ENDIF}
  236. {$ENDIF}
  237. end;
  238. function TJsonHttpClient.Put(const aURL, aInContent : string) : IHttpRequestResponse;
  239. var
  240. {$IFDEF DELPHIXE8_UP}
  241. resp : IHTTPResponse;
  242. {$ELSE}
  243. resp : TIdHTTPResponse;
  244. {$ENDIF}
  245. responsecontent : TStringStream;
  246. postcontent : TStringStream;
  247. begin
  248. postcontent := TStringStream.Create(Utf8Encode(aInContent));
  249. try
  250. //postcontent.WriteString(aInContent);
  251. responsecontent := TStringStream.Create;
  252. try
  253. {$IFDEF DELPHIXE8_UP}
  254. resp := fHTTPClient.Put(aURL,postcontent,responsecontent);
  255. {$ELSE}
  256. {$IFDEF FPC}
  257. try
  258. fHTTPClient.Put(aURL,postcontent,responsecontent);
  259. fHTTPClient.Disconnect(False);
  260. except
  261. on E : Exception do
  262. begin
  263. if e.ClassType <> EIdConnClosedGracefully then raise e;
  264. end;
  265. end;
  266. {$ELSE}
  267. fHTTPClient.Post(aURL,postcontent,responsecontent);
  268. {$ENDIF}
  269. resp := fHTTPClient.Response;
  270. {$ENDIF}
  271. Result := THttpRequestResponse.Create(resp,responsecontent.DataString);
  272. finally
  273. responsecontent.Free;
  274. end;
  275. finally
  276. postcontent.Free;
  277. end;
  278. end;
  279. procedure TJsonHttpClient.SetConnectionTimeout(const aValue: Integer);
  280. begin
  281. fConnectionTimeout := aValue;
  282. {$IFDEF DELPHIXE8_UP}
  283. fHTTPClient.ConnectionTimeout := aValue;
  284. {$ELSE}
  285. fHTTPClient.ConnectTimeout := aValue;
  286. {$ENDIF}
  287. end;
  288. procedure TJsonHttpClient.SetContentType(const aValue: string);
  289. begin
  290. fContentType := aValue;
  291. {$IFDEF DELPHIXE8_UP}
  292. fHTTPClient.ContentType := aValue;
  293. {$ELSE}
  294. fHTTPClient.Request.ContentType := aValue;
  295. {$ENDIF}
  296. end;
  297. procedure TJsonHttpClient.SetHandleRedirects(const aValue: Boolean);
  298. begin
  299. fHandleRedirects := aValue;
  300. {$IFDEF DELPHIXE8_UP}
  301. fHTTPClient.HandleRedirects := aValue;
  302. {$ELSE}
  303. fHTTPClient.HandleRedirects := aValue;
  304. {$ENDIF}
  305. end;
  306. procedure TJsonHttpClient.SetResponseTimeout(const aValue: Integer);
  307. begin
  308. fResponseTimeout := aValue;
  309. {$IFDEF DELPHIXE8_UP}
  310. fHTTPClient.ResponseTimeout := aValue;
  311. {$ELSE}
  312. fHTTPClient.ReadTimeout := aValue;
  313. {$ENDIF}
  314. end;
  315. procedure TJsonHttpClient.SetUserAgent(const aValue: string);
  316. begin
  317. fUserAgent := aValue;
  318. {$IFDEF DELPHIXE8_UP}
  319. fHTTPClient.UserAgent := aValue;
  320. {$ELSE}
  321. fHTTPClient.Request.UserAgent := aValue;
  322. {$ENDIF}
  323. end;
  324. { THttpRequestResponse }
  325. {$IFDEF DELPHIXE8_UP}
  326. constructor THttpRequestResponse.Create(aResponse: IHTTPResponse; const aContent : string);
  327. begin
  328. fStatusCode := aResponse.StatusCode;
  329. fStatusText := aResponse.StatusText;
  330. if aContent <> '' then fResponse := TJSONObject.ParseJSONValue(aContent) as TJSONObject;
  331. //if response is not json, get as json result
  332. if fResponse = nil then
  333. begin
  334. fResponse := TJSONObject.Create;
  335. fResponse.AddPair('Result',aContent);
  336. end;
  337. end;
  338. {$ELSE}
  339. constructor THttpRequestResponse.Create(aResponse : TIdHTTPResponse; const aContent : string);
  340. begin
  341. fStatusCode := aResponse.ResponseCode;
  342. fStatusText := aResponse.ResponseText;
  343. {$If Defined(FPC) OR Defined(DELPHIXE8_UP)}
  344. if (aContent.Contains('{')) and (aContent.Contains('}')) then fResponse := GetJSON(aContent) as TJsonObject;
  345. {$ELSE}
  346. if (aContent.Contains('{')) and (aContent.Contains('}')) then fResponse:= TJsonObject.ParseJSONValue(aContent) as TJsonObject;
  347. {$ENDIF}
  348. //if response is not json, get as json result
  349. if fResponse = nil then
  350. begin
  351. fResponse := TJSONObject.Create;
  352. {$IFDEF DELPHIXE4_UP}
  353. fResponse.AddPair('Result',aContent);
  354. {$ELSE}
  355. fResponse.Add('Result',aContent);
  356. {$ENDIF}
  357. end;
  358. end;
  359. {$ENDIF}
  360. destructor THttpRequestResponse.Destroy;
  361. begin
  362. if Assigned(fResponse) then fResponse.Free;
  363. inherited;
  364. end;
  365. function THttpRequestResponse.Response: TJSONObject;
  366. begin
  367. Result := fResponse;
  368. end;
  369. function THttpRequestResponse.StatusCode: Integer;
  370. begin
  371. Result := fStatusCode;
  372. end;
  373. function THttpRequestResponse.StatusText: string;
  374. begin
  375. Result := fStatusText;
  376. end;
  377. end.