ns_url_request.pas 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. unit ns_url_request;
  2. {
  3. TNSHTTPSendAndReceive class for use by itself as an HTTP client or with
  4. Web Service Toolkit (http://wiki.freepascal.org/Web_Service_Toolkit).
  5. Author: Phil Hess.
  6. Copyright: Copyright 2011 Phil Hess.
  7. License: Modified LGPL (see Free Pascal's rtl/COPYING.FPC).
  8. This means you can link your code to this compiled unit (statically
  9. in a standalone executable or dynamically in a library) without
  10. releasing your code. Only changes to this unit need to be made
  11. publicly available.
  12. }
  13. {$modeswitch ObjectiveC1}
  14. interface
  15. uses
  16. SysUtils,
  17. Classes,
  18. CocoaUtils,
  19. {$IF DEFINED(IPHONESIM) OR DEFINED(CPUARM) OR DEFINED(CPUAARCH64)} //iOS
  20. {$IFDEF NoiPhoneAll}
  21. Foundation
  22. {$ELSE}
  23. iPhoneAll
  24. {$ENDIF}
  25. {$ELSE} //macOS
  26. {$IFDEF NoCocoaAll}
  27. Foundation
  28. {$ELSE}
  29. CocoaAll
  30. {$ENDIF}
  31. {$ENDIF};
  32. type
  33. { TNSHTTPSendAndReceive }
  34. TNSHTTPSendAndReceive = class(TObject)
  35. private
  36. FAddress : string;
  37. FMethod : string;
  38. FTimeOut : Integer;
  39. FLastErrMsg : string;
  40. public
  41. property Address : string read FAddress write FAddress;
  42. property Method : string read FMethod write FMethod;
  43. property TimeOut : Integer read FTimeOut write FTimeOut;
  44. property LastErrMsg : string read FLastErrMsg;
  45. constructor Create;
  46. class procedure SimpleGet(AUrl: string; AStream: TStream);
  47. function SendAndReceive(ARequest : TStream;
  48. AResponse : TStream;
  49. Headers : TStringList) : Boolean; overload;
  50. function SendAndReceive(out AResponse : string) : Boolean; overload;
  51. function PostForm(const FormFields : string;
  52. out AResponse : string) : Boolean; overload;
  53. end;
  54. implementation
  55. constructor TNSHTTPSendAndReceive.Create;
  56. begin
  57. inherited Create;
  58. FMethod := 'GET';
  59. FTimeOut := 30;
  60. end;
  61. class procedure TNSHTTPSendAndReceive.SimpleGet(AUrl: string; AStream: TStream);
  62. begin
  63. With Self.Create do
  64. try
  65. Address:= AUrl;
  66. if not SendAndReceive(nil,AStream,nil) then
  67. raise exception.Create('SimpleGet failed');
  68. finally
  69. Free;
  70. end;
  71. end;
  72. function TNSHTTPSendAndReceive.SendAndReceive(ARequest : TStream;
  73. AResponse : TStream;
  74. Headers : TStringList) : Boolean;
  75. {Send HTTP request to current Address URL, returning downloaded data
  76. in AResponse stream and True as function result. If error occurs,
  77. return False and set LastErrMsg.
  78. Optional ARequest stream can be used to set the HTTP request body.
  79. Optional Headers list of name-value pairs can be used to set
  80. HTTP headers.}
  81. var
  82. urlRequest : NSMutableURLRequest;
  83. requestData : NSMutableData;
  84. HdrNum : Integer;
  85. urlResponse : NSURLResponse;
  86. error : NSError;
  87. urlData : NSData;
  88. begin
  89. Result := False;
  90. try
  91. urlRequest := NSMutableURLRequest.requestWithURL_cachePolicy_timeoutInterval(
  92. NSURL.URLWithString(NSStringUtf8(Address)),
  93. NSURLRequestUseProtocolCachePolicy, Timeout);
  94. if Method <> '' then
  95. urlRequest.setHTTPMethod(NSStringUtf8(Method));
  96. if Assigned(ARequest) and (ARequest.Size > 0) then
  97. begin
  98. try
  99. requestData := NSMutableData.alloc.initWithLength(ARequest.Size);
  100. ARequest.Position := 0;
  101. ARequest.ReadBuffer(requestData.mutableBytes^, ARequest.Size);
  102. urlRequest.setHTTPBody(requestData);
  103. finally
  104. requestData.release;
  105. end;
  106. end;
  107. if Assigned(Headers) then
  108. begin
  109. for HdrNum := 0 to Headers.Count-1 do
  110. begin
  111. urlRequest.addValue_forHTTPHeaderField(NSStringUtf8(Headers.ValueFromIndex[HdrNum]),
  112. NSStringUtf8(Headers.Names[HdrNum]));
  113. end;
  114. end;
  115. urlData := NSURLConnection.sendSynchronousRequest_returningResponse_error(
  116. urlRequest, @urlResponse, @error);
  117. if not Assigned(urlData) then
  118. begin
  119. FLastErrMsg := NSStringToString(error.localizedDescription);
  120. Exit;
  121. end;
  122. AResponse.Position := 0;
  123. AResponse.WriteBuffer(urlData.bytes^, urlData.length);
  124. AResponse.Position := 0;
  125. Result := True;
  126. except
  127. on E : Exception do
  128. begin
  129. FLastErrMsg := E.Message;
  130. end;
  131. end;
  132. end;
  133. function TNSHTTPSendAndReceive.SendAndReceive(out AResponse : string) : Boolean;
  134. {Send HTTP request to current Address URL, returning downloaded data
  135. in AResponse string and True as function result. If error occurs,
  136. return False and set LastErrMsg.}
  137. var
  138. Data : TMemoryStream;
  139. begin
  140. Data := TMemoryStream.Create;
  141. try
  142. Result := SendAndReceive(nil, Data, nil);
  143. if Result then
  144. begin
  145. SetLength(AResponse, Data.Size);
  146. if Data.Size > 0 then
  147. Data.Read(AResponse[1], Data.Size);
  148. end;
  149. finally
  150. Data.Free;
  151. end;
  152. end;
  153. function TNSHTTPSendAndReceive.PostForm(const FormFields : string;
  154. out AResponse : string) : Boolean;
  155. {Post FormFields to current Address URL, returning downloaded data
  156. in AResponse string and True as function result. If error occurs,
  157. return False and set LastErrMsg.
  158. Note FormFields must be in URL query string form (for example,
  159. 'name1=value1&name2=value2') and URL encoded.}
  160. var
  161. Request : TMemoryStream;
  162. Headers : TStringList;
  163. Data : TMemoryStream;
  164. begin
  165. Request := TMemoryStream.Create;
  166. Headers := TStringList.Create;
  167. Data := TMemoryStream.Create;
  168. try
  169. FMethod := 'POST';
  170. if FormFields <> '' then
  171. Request.Write(FormFields[1], Length(FormFields));
  172. Headers.Add('Content-Type=application/x-www-form-urlencoded');
  173. Headers.Add('Content-Length=' + IntToStr(Request.Size));
  174. Result := SendAndReceive(Request, Data, Headers);
  175. if Result then
  176. begin
  177. SetLength(AResponse, Data.Size);
  178. if Data.Size > 0 then
  179. Data.Read(AResponse[1], Data.Size);
  180. end;
  181. finally
  182. Request.Free;
  183. Headers.Free;
  184. Data.Free;
  185. end;
  186. end;
  187. end.