Quick.HttpClient.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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. IdHTTP,
  34. IdException,
  35. {$IFDEF FPC}
  36. fpjson;
  37. {$ELSE}
  38. Data.DBXJSON;
  39. {$ENDIF}
  40. {$ENDIF}
  41. type
  42. IHttpRequestResponse = interface
  43. ['{64DC58F7-B551-4619-85E9-D13E781529CD}']
  44. function StatusCode : Integer;
  45. function StatusText : string;
  46. function Response : TJSONObject;
  47. end;
  48. THttpRequestResponse = class(TInterfacedObject,IHttpRequestResponse)
  49. private
  50. fStatusCode : Integer;
  51. fStatusText : string;
  52. fResponse : TJSONObject;
  53. public
  54. {$IFDEF DELPHIXE8_UP}
  55. constructor Create(aResponse : IHTTPResponse; const aContent : string);
  56. {$ELSE}
  57. constructor Create(aResponse : TIdHTTPResponse; const aContent : string);
  58. {$ENDIF}
  59. destructor Destroy; override;
  60. function StatusCode : Integer;
  61. function StatusText : string;
  62. function Response : TJSONObject;
  63. end;
  64. TJsonHttpClient = class
  65. private
  66. {$IFDEF DELPHIXE8_UP}
  67. fHTTPClient : System.Net.HttpClient.THTTPClient;
  68. {$ELSE}
  69. fHTTPClient : TIdHTTP;
  70. {$ENDIF}
  71. fUserAgent : string;
  72. fContentType : string;
  73. fResponseTimeout : Integer;
  74. fConnectionTimeout : Integer;
  75. fHandleRedirects : Boolean;
  76. procedure SetContentType(const aValue: string);
  77. procedure SetUserAgent(const aValue: string);
  78. procedure SetResponseTimeout(const aValue: Integer);
  79. procedure SetConnectionTimeout(const aValue: Integer);
  80. procedure SetHandleRedirects(const aValue: Boolean);
  81. public
  82. constructor Create;
  83. destructor Destroy; override;
  84. property UserAgent : string read fUserAgent write SetUserAgent;
  85. property ContentType : string read fContentType write SetContentType;
  86. property ResponseTimeout : Integer read fResponseTimeout write SetResponseTimeout;
  87. property ConnectionTimeout : Integer read fConnectionTimeout write SetConnectionTimeout;
  88. property HandleRedirects : Boolean read fHandleRedirects write SetHandleRedirects;
  89. function Get(const aURL : string) : IHttpRequestResponse;
  90. function Post(const aURL, aInContent : string) : IHttpRequestResponse; overload;
  91. function Post(const aURL : string; aInContent : TStream) : IHttpRequestResponse; overload;
  92. function Post(const aURL : string; aJsonContent : TJsonObject) : IHttpRequestResponse; overload;
  93. function Put(const aURL, aInContent : string) : IHttpRequestResponse;
  94. end;
  95. implementation
  96. const
  97. DEF_USER_AGENT = 'XLHttpClient';
  98. constructor TJsonHttpClient.Create;
  99. begin
  100. {$IFDEF DELPHIXE8_UP}
  101. fHTTPClient := THTTPClient.Create;
  102. fHTTPClient.ContentType := 'application/json';
  103. fHTTPClient.UserAgent := DEF_USER_AGENT;
  104. {$ELSE}
  105. fHTTPClient := TIdHTTP.Create(nil);
  106. fHTTPClient.Request.ContentType := 'application/json';
  107. fHTTPClient.Request.UserAgent := DEF_USER_AGENT;
  108. {$ENDIF}
  109. end;
  110. destructor TJsonHttpClient.Destroy;
  111. begin
  112. fHTTPClient.Free;
  113. inherited;
  114. end;
  115. function TJsonHttpClient.Get(const aURL : string) : IHttpRequestResponse;
  116. var
  117. {$IFDEF DELPHIXE8_UP}
  118. resp : IHTTPResponse;
  119. {$ELSE}
  120. resp : TIdHTTPResponse;
  121. {$ENDIF}
  122. bodycontent : TStringStream;
  123. responsecontent : TStringStream;
  124. begin
  125. bodycontent := TStringStream.Create;
  126. try
  127. responsecontent := TStringStream.Create;
  128. try
  129. {$IFDEF DELPHIXE8_UP}
  130. resp := fHTTPClient.Get(aURL,responsecontent,nil);
  131. {$ELSE}
  132. {$IFDEF FPC}
  133. fHTTPClient.Get(aURL,responsecontent);
  134. {$ELSE}
  135. fHTTPClient.Get(aURL,responsecontent,nil);
  136. {$ENDIF}
  137. resp := fHTTPClient.Response;
  138. {$ENDIF}
  139. Result := THttpRequestResponse.Create(resp,responsecontent.DataString);
  140. finally
  141. responsecontent.Free;
  142. end;
  143. finally
  144. bodycontent.Free;
  145. end;
  146. end;
  147. function TJsonHttpClient.Post(const aURL, aInContent : string) : IHttpRequestResponse;
  148. var
  149. {$IFDEF DELPHIXE8_UP}
  150. resp : IHTTPResponse;
  151. {$ELSE}
  152. resp : TIdHTTPResponse;
  153. {$ENDIF}
  154. responsecontent : TStringStream;
  155. postcontent : TStringStream;
  156. begin
  157. postcontent := TStringStream.Create(Utf8Encode(aInContent));
  158. try
  159. //postcontent.WriteString(aInContent);
  160. responsecontent := TStringStream.Create;
  161. try
  162. {$IFDEF DELPHIXE8_UP}
  163. resp := fHTTPClient.Post(aURL,postcontent,responsecontent);
  164. {$ELSE}
  165. {$IFDEF FPC}
  166. try
  167. fHTTPClient.Post(aURL,postcontent,responsecontent);
  168. fHTTPClient.Disconnect(False);
  169. except
  170. on E : Exception do
  171. begin
  172. if e.ClassType <> EIdConnClosedGracefully then raise e;
  173. end;
  174. end;
  175. {$ELSE}
  176. fHTTPClient.Post(aURL,postcontent,responsecontent);
  177. {$ENDIF}
  178. resp := fHTTPClient.Response;
  179. {$ENDIF}
  180. Result := THttpRequestResponse.Create(resp,responsecontent.DataString);
  181. finally
  182. responsecontent.Free;
  183. end;
  184. finally
  185. postcontent.Free;
  186. end;
  187. end;
  188. function TJsonHttpClient.Post(const aURL : string; aInContent : TStream) : IHttpRequestResponse;
  189. var
  190. {$IFDEF DELPHIXE8_UP}
  191. resp : IHTTPResponse;
  192. {$ELSE}
  193. resp : TIdHTTPResponse;
  194. {$ENDIF}
  195. responsecontent : TStringStream;
  196. begin
  197. //postcontent.WriteString(aInContent);
  198. responsecontent := TStringStream.Create;
  199. try
  200. {$IFDEF DELPHIXE8_UP}
  201. resp := fHTTPClient.Post(aURL,aInContent,responsecontent);
  202. {$ELSE}
  203. {$IFDEF FPC}
  204. try
  205. fHTTPClient.Post(aURL,aInContent,responsecontent);
  206. fHTTPClient.Disconnect(False);
  207. except
  208. on E : Exception do
  209. begin
  210. if e.ClassType <> EIdConnClosedGracefully then raise e;
  211. end;
  212. end;
  213. {$ELSE}
  214. fHTTPClient.Post(aURL,aInContent,responsecontent);
  215. {$ENDIF}
  216. resp := fHTTPClient.Response;
  217. {$ENDIF}
  218. Result := THttpRequestResponse.Create(resp,responsecontent.DataString);
  219. finally
  220. responsecontent.Free;
  221. end;
  222. end;
  223. function TJsonHttpClient.Post(const aURL : string; aJsonContent : TJsonObject) : IHttpRequestResponse;
  224. begin
  225. {$IFDEF DELPHIXE8_UP}
  226. Result := Self.Post(aURL,aJsonContent.ToJSON);
  227. {$ELSE}
  228. {$IFDEF FPC}
  229. Result := Self.Post(aURL,aJsonContent.AsJson);
  230. {$ELSE}
  231. Result := Self.Post(aURL,aJsonContent.ToString);
  232. {$ENDIF}
  233. {$ENDIF}
  234. end;
  235. function TJsonHttpClient.Put(const aURL, aInContent : string) : IHttpRequestResponse;
  236. var
  237. {$IFDEF DELPHIXE8_UP}
  238. resp : IHTTPResponse;
  239. {$ELSE}
  240. resp : TIdHTTPResponse;
  241. {$ENDIF}
  242. responsecontent : TStringStream;
  243. postcontent : TStringStream;
  244. begin
  245. postcontent := TStringStream.Create(Utf8Encode(aInContent));
  246. try
  247. //postcontent.WriteString(aInContent);
  248. responsecontent := TStringStream.Create;
  249. try
  250. {$IFDEF DELPHIXE8_UP}
  251. resp := fHTTPClient.Put(aURL,postcontent,responsecontent);
  252. {$ELSE}
  253. {$IFDEF FPC}
  254. try
  255. fHTTPClient.Put(aURL,postcontent,responsecontent);
  256. fHTTPClient.Disconnect(False);
  257. except
  258. on E : Exception do
  259. begin
  260. if e.ClassType <> EIdConnClosedGracefully then raise e;
  261. end;
  262. end;
  263. {$ELSE}
  264. fHTTPClient.Post(aURL,postcontent,responsecontent);
  265. {$ENDIF}
  266. resp := fHTTPClient.Response;
  267. {$ENDIF}
  268. Result := THttpRequestResponse.Create(resp,responsecontent.DataString);
  269. finally
  270. responsecontent.Free;
  271. end;
  272. finally
  273. postcontent.Free;
  274. end;
  275. end;
  276. procedure TJsonHttpClient.SetConnectionTimeout(const aValue: Integer);
  277. begin
  278. fConnectionTimeout := aValue;
  279. {$IFDEF DELPHIXE8_UP}
  280. fHTTPClient.ConnectionTimeout := aValue;
  281. {$ELSE}
  282. fHTTPClient.ConnectTimeout := aValue;
  283. {$ENDIF}
  284. end;
  285. procedure TJsonHttpClient.SetContentType(const aValue: string);
  286. begin
  287. fContentType := aValue;
  288. {$IFDEF DELPHIXE8_UP}
  289. fHTTPClient.ContentType := aValue;
  290. {$ELSE}
  291. fHTTPClient.Request.ContentType := aValue;
  292. {$ENDIF}
  293. end;
  294. procedure TJsonHttpClient.SetHandleRedirects(const aValue: Boolean);
  295. begin
  296. fHandleRedirects := aValue;
  297. {$IFDEF DELPHIXE8_UP}
  298. fHTTPClient.HandleRedirects := aValue;
  299. {$ELSE}
  300. fHTTPClient.HandleRedirects := aValue;
  301. {$ENDIF}
  302. end;
  303. procedure TJsonHttpClient.SetResponseTimeout(const aValue: Integer);
  304. begin
  305. fResponseTimeout := aValue;
  306. {$IFDEF DELPHIXE8_UP}
  307. fHTTPClient.ResponseTimeout := aValue;
  308. {$ELSE}
  309. fHTTPClient.ReadTimeout := aValue;
  310. {$ENDIF}
  311. end;
  312. procedure TJsonHttpClient.SetUserAgent(const aValue: string);
  313. begin
  314. fUserAgent := aValue;
  315. {$IFDEF DELPHIXE8_UP}
  316. fHTTPClient.UserAgent := aValue;
  317. {$ELSE}
  318. fHTTPClient.Request.UserAgent := aValue;
  319. {$ENDIF}
  320. end;
  321. { THttpRequestResponse }
  322. {$IFDEF DELPHIXE8_UP}
  323. constructor THttpRequestResponse.Create(aResponse: IHTTPResponse; const aContent : string);
  324. begin
  325. fStatusCode := aResponse.StatusCode;
  326. fStatusText := aResponse.StatusText;
  327. if aContent <> '' then fResponse := TJSONObject.ParseJSONValue(aContent) as TJSONObject;
  328. //if response is not json, get as json result
  329. if fResponse = nil then
  330. begin
  331. fResponse := TJSONObject.Create;
  332. fResponse.AddPair('Result',aContent);
  333. end;
  334. end;
  335. {$ELSE}
  336. constructor THttpRequestResponse.Create(aResponse : TIdHTTPResponse; const aContent : string);
  337. begin
  338. fStatusCode := aResponse.ResponseCode;
  339. fStatusText := aResponse.ResponseText;
  340. if (aContent.Contains('{')) and (aContent.Contains('}')) then fResponse := GetJSON(aContent) as TJsonObject;
  341. //if response is not json, get as json result
  342. if fResponse = nil then
  343. begin
  344. fResponse := TJSONObject.Create;
  345. fResponse.Add('Result',aContent);
  346. end;
  347. end;
  348. {$ENDIF}
  349. destructor THttpRequestResponse.Destroy;
  350. begin
  351. if Assigned(fResponse) then fResponse.Free;
  352. inherited;
  353. end;
  354. function THttpRequestResponse.Response: TJSONObject;
  355. begin
  356. Result := fResponse;
  357. end;
  358. function THttpRequestResponse.StatusCode: Integer;
  359. begin
  360. Result := fStatusCode;
  361. end;
  362. function THttpRequestResponse.StatusText: string;
  363. begin
  364. Result := fStatusText;
  365. end;
  366. end.