| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- unit ns_url_request;
- {
- TNSHTTPSendAndReceive class for use by itself as an HTTP client or with
- Web Service Toolkit (http://wiki.freepascal.org/Web_Service_Toolkit).
- Author: Phil Hess.
- Copyright: Copyright 2011 Phil Hess.
- License: Modified LGPL (see Free Pascal's rtl/COPYING.FPC).
- This means you can link your code to this compiled unit (statically
- in a standalone executable or dynamically in a library) without
- releasing your code. Only changes to this unit need to be made
- publicly available.
- }
- {$modeswitch ObjectiveC1}
- interface
- uses
- SysUtils,
- Classes,
- CocoaUtils,
- {$IF DEFINED(IPHONESIM) OR DEFINED(CPUARM) OR DEFINED(CPUAARCH64)} //iOS
- {$IFDEF NoiPhoneAll}
- Foundation
- {$ELSE}
- iPhoneAll
- {$ENDIF}
- {$ELSE} //macOS
- {$IFDEF NoCocoaAll}
- Foundation
- {$ELSE}
- CocoaAll
- {$ENDIF}
- {$ENDIF};
- type
- { TNSHTTPSendAndReceive }
- TNSHTTPSendAndReceive = class(TObject)
- private
- FAddress : string;
- FMethod : string;
- FTimeOut : Integer;
- FLastErrMsg : string;
- public
- property Address : string read FAddress write FAddress;
- property Method : string read FMethod write FMethod;
- property TimeOut : Integer read FTimeOut write FTimeOut;
- property LastErrMsg : string read FLastErrMsg;
- constructor Create;
- class procedure SimpleGet(AUrl: string; AStream: TStream);
- function SendAndReceive(ARequest : TStream;
- AResponse : TStream;
- Headers : TStringList) : Boolean; overload;
- function SendAndReceive(out AResponse : string) : Boolean; overload;
- function PostForm(const FormFields : string;
- out AResponse : string) : Boolean; overload;
- end;
- implementation
- constructor TNSHTTPSendAndReceive.Create;
- begin
- inherited Create;
- FMethod := 'GET';
- FTimeOut := 30;
- end;
- class procedure TNSHTTPSendAndReceive.SimpleGet(AUrl: string; AStream: TStream);
- begin
- With Self.Create do
- try
- Address:= AUrl;
- if not SendAndReceive(nil,AStream,nil) then
- raise exception.Create('SimpleGet failed');
- finally
- Free;
- end;
- end;
- function TNSHTTPSendAndReceive.SendAndReceive(ARequest : TStream;
- AResponse : TStream;
- Headers : TStringList) : Boolean;
- {Send HTTP request to current Address URL, returning downloaded data
- in AResponse stream and True as function result. If error occurs,
- return False and set LastErrMsg.
- Optional ARequest stream can be used to set the HTTP request body.
- Optional Headers list of name-value pairs can be used to set
- HTTP headers.}
- var
- urlRequest : NSMutableURLRequest;
- requestData : NSMutableData;
- HdrNum : Integer;
- urlResponse : NSURLResponse;
- error : NSError;
- urlData : NSData;
- begin
- Result := False;
- try
- urlRequest := NSMutableURLRequest.requestWithURL_cachePolicy_timeoutInterval(
- NSURL.URLWithString(NSStringUtf8(Address)),
- NSURLRequestUseProtocolCachePolicy, Timeout);
- if Method <> '' then
- urlRequest.setHTTPMethod(NSStringUtf8(Method));
- if Assigned(ARequest) and (ARequest.Size > 0) then
- begin
- try
- requestData := NSMutableData.alloc.initWithLength(ARequest.Size);
- ARequest.Position := 0;
- ARequest.ReadBuffer(requestData.mutableBytes^, ARequest.Size);
- urlRequest.setHTTPBody(requestData);
- finally
- requestData.release;
- end;
- end;
- if Assigned(Headers) then
- begin
- for HdrNum := 0 to Headers.Count-1 do
- begin
- urlRequest.addValue_forHTTPHeaderField(NSStringUtf8(Headers.ValueFromIndex[HdrNum]),
- NSStringUtf8(Headers.Names[HdrNum]));
- end;
- end;
- urlData := NSURLConnection.sendSynchronousRequest_returningResponse_error(
- urlRequest, @urlResponse, @error);
- if not Assigned(urlData) then
- begin
- FLastErrMsg := NSStringToString(error.localizedDescription);
- Exit;
- end;
- AResponse.Position := 0;
- AResponse.WriteBuffer(urlData.bytes^, urlData.length);
- AResponse.Position := 0;
- Result := True;
- except
- on E : Exception do
- begin
- FLastErrMsg := E.Message;
- end;
- end;
- end;
- function TNSHTTPSendAndReceive.SendAndReceive(out AResponse : string) : Boolean;
- {Send HTTP request to current Address URL, returning downloaded data
- in AResponse string and True as function result. If error occurs,
- return False and set LastErrMsg.}
- var
- Data : TMemoryStream;
- begin
- Data := TMemoryStream.Create;
- try
- Result := SendAndReceive(nil, Data, nil);
- if Result then
- begin
- SetLength(AResponse, Data.Size);
- if Data.Size > 0 then
- Data.Read(AResponse[1], Data.Size);
- end;
- finally
- Data.Free;
- end;
- end;
- function TNSHTTPSendAndReceive.PostForm(const FormFields : string;
- out AResponse : string) : Boolean;
- {Post FormFields to current Address URL, returning downloaded data
- in AResponse string and True as function result. If error occurs,
- return False and set LastErrMsg.
- Note FormFields must be in URL query string form (for example,
- 'name1=value1&name2=value2') and URL encoded.}
- var
- Request : TMemoryStream;
- Headers : TStringList;
- Data : TMemoryStream;
- begin
- Request := TMemoryStream.Create;
- Headers := TStringList.Create;
- Data := TMemoryStream.Create;
- try
- FMethod := 'POST';
- if FormFields <> '' then
- Request.Write(FormFields[1], Length(FormFields));
- Headers.Add('Content-Type=application/x-www-form-urlencoded');
- Headers.Add('Content-Length=' + IntToStr(Request.Size));
- Result := SendAndReceive(Request, Data, Headers);
- if Result then
- begin
- SetLength(AResponse, Data.Size);
- if Data.Size > 0 then
- Data.Read(AResponse[1], Data.Size);
- end;
- finally
- Request.Free;
- Headers.Free;
- Data.Free;
- end;
- end;
- end.
|