2013-10-30 00:48:23 +01:00
|
|
|
|
unit MVCFramework.RESTClient;
|
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
|
|
uses
|
|
|
|
|
Classes,
|
|
|
|
|
IdBaseComponent,
|
|
|
|
|
IdComponent,
|
|
|
|
|
IdTCPConnection,
|
|
|
|
|
IdTCPClient,
|
|
|
|
|
IdHTTP,
|
|
|
|
|
idURI,
|
2014-09-05 12:47:40 +02:00
|
|
|
|
{$IF CompilerVersion < 27}
|
2014-04-16 22:52:25 +02:00
|
|
|
|
Data.DBXJSON,
|
|
|
|
|
{$ELSE}
|
|
|
|
|
System.JSON,
|
|
|
|
|
{$IFEND}
|
2013-10-30 00:48:23 +01:00
|
|
|
|
IdMultipartFormData,
|
2015-06-03 22:47:07 +02:00
|
|
|
|
System.SysUtils, Data.DB, IdIOHandler,
|
|
|
|
|
IdCompressorZLib, //Ezequiel J. M<>ller
|
|
|
|
|
IdSSLOpenSSL; //Ezequiel J. M<>ller
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
TArrayOfString = array of string;
|
2014-03-24 17:37:08 +01:00
|
|
|
|
THttpCommand = (httpGET, httpPOST, httpPUT, httpDELETE, httpPATCH, httpTRACE);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
IRESTResponse = interface
|
|
|
|
|
function BodyAsString: string;
|
|
|
|
|
function BodyAsJsonObject: TJSONObject;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
function BodyAsJsonValue: TJSONValue;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function ResponseCode: Word;
|
|
|
|
|
function ResponseText: string;
|
|
|
|
|
function Headers: TStringlist;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function GetContentType: string;
|
|
|
|
|
function GetContentEncoding: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function Body: TStringStream;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function GetHeaderValue(const Name: string): string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
procedure SetResponseCode(AResponseCode: Word);
|
|
|
|
|
procedure SetResponseText(AResponseText: string);
|
|
|
|
|
procedure SetHeaders(AHeaders: TStrings);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
TRESTResponse = class(TInterfacedObject, IRESTResponse)
|
|
|
|
|
private
|
2013-11-05 14:57:50 +01:00
|
|
|
|
FBody: TStringStream;
|
|
|
|
|
FResponseCode: Word;
|
|
|
|
|
FResponseText: string;
|
|
|
|
|
FHeaders: TStringlist;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FBodyAsJSONValue: TJSONValue;
|
2013-11-05 14:57:50 +01:00
|
|
|
|
FContentType: string;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
FContentEncoding: string;
|
|
|
|
|
function GetHeader(const Value: string): string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
public
|
2014-03-31 11:25:16 +02:00
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function BodyAsString: string;
|
|
|
|
|
function BodyAsJsonObject: TJSONObject;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
function BodyAsJsonValue: TJSONValue;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function ResponseCode: Word;
|
|
|
|
|
function ResponseText: string;
|
|
|
|
|
function Headers: TStringlist;
|
|
|
|
|
function Body: TStringStream;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function GetContentType: string;
|
|
|
|
|
function GetContentEncoding: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
procedure SetResponseCode(AResponseCode: Word);
|
|
|
|
|
procedure SetResponseText(AResponseText: string);
|
|
|
|
|
procedure SetHeaders(AHeaders: TStrings);
|
|
|
|
|
constructor Create; virtual;
|
|
|
|
|
destructor Destroy; override;
|
2014-03-31 11:25:16 +02:00
|
|
|
|
function GetHeaderValue(const Name: string): string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
TRESTClient = class(TInterfacedObject)
|
|
|
|
|
private
|
2013-11-05 14:57:50 +01:00
|
|
|
|
FServerName: string;
|
|
|
|
|
FServerPort: Word;
|
|
|
|
|
FBodyParams: TStringlist;
|
|
|
|
|
FQueryStringParams: TStringlist;
|
|
|
|
|
FAccept: string;
|
|
|
|
|
FRawBody: TStringStream;
|
|
|
|
|
FHTTP: TIdHTTP;
|
|
|
|
|
FContentType: string;
|
|
|
|
|
FLastSessionID: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FNextRequestIsAsynch: Boolean;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FAsynchProc: TProc<IRESTResponse>;
|
|
|
|
|
FAsynchProcErr: TProc<Exception>;
|
2013-11-05 14:57:50 +01:00
|
|
|
|
FPrimaryThread: TThread;
|
|
|
|
|
FMultiPartFormData: TIdMultiPartFormDataStream;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FAsynchProcAlways: TProc;
|
2014-04-01 22:32:57 +02:00
|
|
|
|
FProtocol: string;
|
2014-04-02 20:27:17 +02:00
|
|
|
|
FSynchronized: Boolean;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
FContentEncoding: string;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function EncodeQueryStringParams(const AQueryStringParams: TStrings;
|
|
|
|
|
IncludeQuestionMark: Boolean = true): string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
procedure SetBodyParams(const Value: TStringlist);
|
|
|
|
|
procedure SetQueryStringParams(const Value: TStringlist);
|
|
|
|
|
procedure SetAccept(const Value: string);
|
|
|
|
|
procedure SetContentType(const Value: string);
|
|
|
|
|
function GetSessionID: string;
|
|
|
|
|
procedure SetSessionID(const Value: string);
|
|
|
|
|
function GetBodyParams: TStringlist;
|
|
|
|
|
function GetQueryStringParams: TStringlist;
|
|
|
|
|
function GetRawBody: TStringStream;
|
|
|
|
|
procedure SetReadTimeout(const Value: Integer);
|
|
|
|
|
function GetReadTimeout: Integer;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
procedure StartAsynchRequest(AHTTPMethod: THttpCommand; AUrl: string;
|
|
|
|
|
ABodyString: string); overload;
|
2015-02-16 14:25:09 +01:00
|
|
|
|
procedure StartAsynchRequest(AHTTPMethod: THttpCommand; AUrl: string); overload;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
procedure SetConnectionTimeout(const Value: Integer);
|
|
|
|
|
function GetConnectionTimeout: Integer;
|
|
|
|
|
procedure SetRequestHeaders(const Value: TStringlist);
|
2015-04-01 17:01:23 +02:00
|
|
|
|
procedure SetPassword(const Value: string);
|
|
|
|
|
procedure SetUserName(const Value: string);
|
|
|
|
|
function GetPassword: string;
|
|
|
|
|
function GetUserName: string;
|
|
|
|
|
function GetUseBasicAuthentication: Boolean;
|
|
|
|
|
procedure SetUseBasicAuthentication(const Value: Boolean);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
strict protected
|
|
|
|
|
FRequestHeaders: TStringlist;
|
|
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
procedure HandleCookies;
|
|
|
|
|
function EncodeResourceParams(AResourceParams: array of string): string;
|
|
|
|
|
function HttpCommandToString(const AHttpCommand: THttpCommand): string;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function SendHTTPCommand(const ACommand: THttpCommand;
|
|
|
|
|
const AAccept, AContentType, AUrl: string; ABodyParams: TStrings): IRESTResponse;
|
|
|
|
|
function SendHTTPCommandWithBody(const ACommand: THttpCommand;
|
|
|
|
|
const AAccept, AContentType, AUrl: string; ABodyString: string): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
procedure HandleRequestCookies;
|
|
|
|
|
function GetMultipartFormData: TIdMultiPartFormDataStream;
|
|
|
|
|
|
|
|
|
|
public
|
2015-04-01 17:01:23 +02:00
|
|
|
|
constructor Create(const AServerName: string; AServerPort: Word = 80;
|
|
|
|
|
AIOHandler: TIdIOHandler = nil); virtual;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function AddFile(const FieldName, FileName: string; const ContentType: string = '')
|
2015-02-16 14:25:09 +01:00
|
|
|
|
: TRESTClient;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
|
|
|
|
|
function Asynch(AProc: TProc<IRESTResponse>; AProcErr: TProc<Exception> = nil;
|
|
|
|
|
AProcAlways: TProc = nil; ASynchronized: Boolean = false): TRESTClient;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function ClearAllParams: TRESTClient;
|
|
|
|
|
function ResetSession: TRESTClient;
|
|
|
|
|
function Accept(const AcceptHeader: string): TRESTClient; overload;
|
|
|
|
|
function Accept: string; overload;
|
2015-06-03 22:47:07 +02:00
|
|
|
|
function SSL(const Enabled: Boolean = True): TRESTClient; //Ezequiel J. M<>ller
|
|
|
|
|
function Compression(const Enabled: Boolean = True): TRESTClient; //Ezequiel J. M<>ller
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function ContentType(const ContentTypeHeader: string): TRESTClient; overload;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function ContentType: string; overload;
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function ContentEncoding(const ContentEncodingHeader: string): TRESTClient; overload;
|
2014-04-10 13:56:23 +02:00
|
|
|
|
function ContentEncoding: string; overload;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
// requests
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function doGET(AResource: string; AResourceParams: array of string): IRESTResponse;
|
|
|
|
|
function doPOST(AResource: string; AResourceParams: array of string): IRESTResponse; overload;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function doPOST(AResource: string; AResourceParams: array of string; AJSONValue: TJSONValue;
|
|
|
|
|
AOwnsJSONBody: Boolean = true): IRESTResponse; overload;
|
|
|
|
|
function doPOST(AResource: string; AResourceParams: array of string; ABodyString: string)
|
2014-03-24 17:37:08 +01:00
|
|
|
|
: IRESTResponse; overload;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function doPATCH(AResource: string; AResourceParams: array of string; AJSONValue: TJSONValue;
|
|
|
|
|
AOwnsJSONBody: Boolean = true): IRESTResponse; overload;
|
|
|
|
|
function doPATCH(AResource: string; AResourceParams: array of string; ABodyString: string)
|
2013-10-30 00:48:23 +01:00
|
|
|
|
: IRESTResponse; overload;
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function doPUT(AResource: string; AResourceParams: array of string): IRESTResponse; overload;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function doPUT(AResource: string; AResourceParams: array of string; AJSONValue: TJSONValue;
|
|
|
|
|
AOwnsJSONBody: Boolean = true): IRESTResponse; overload;
|
|
|
|
|
function doPUT(AResource: string; AResourceParams: array of string; ABodyString: string)
|
2013-10-30 00:48:23 +01:00
|
|
|
|
: IRESTResponse; overload;
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function doDELETE(AResource: string; AResourceParams: array of string): IRESTResponse;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
property UserName: string read GetUserName write SetUserName;
|
|
|
|
|
property Password: string read GetPassword write SetPassword;
|
|
|
|
|
property UseBasicAuthentication: Boolean read GetUseBasicAuthentication
|
|
|
|
|
write SetUseBasicAuthentication;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
property BodyParams: TStringlist read GetBodyParams write SetBodyParams;
|
|
|
|
|
property RawBody: TStringStream read GetRawBody;
|
2015-02-16 14:25:09 +01:00
|
|
|
|
property QueryStringParams: TStringlist read GetQueryStringParams write SetQueryStringParams;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
property SessionID: string read GetSessionID write SetSessionID;
|
|
|
|
|
property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
|
2015-02-16 14:25:09 +01:00
|
|
|
|
property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
|
|
|
|
|
property RequestHeaders: TStringlist read FRequestHeaders write SetRequestHeaders;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
// dataset specific methods
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function DSUpdate(const URL: string; DataSet: TDataSet; const KeyValue: string): IRESTResponse;
|
|
|
|
|
function DSInsert(const URL: string; DataSet: TDataSet): IRESTResponse;
|
|
|
|
|
function DSDelete(const URL: string; const KeyValue: string): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function StringsToArrayOfString(const AStrings: TStrings): TArrayOfString;
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
2014-04-01 02:12:34 +02:00
|
|
|
|
uses
|
|
|
|
|
ObjectsMappers;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
{ TRSF }
|
|
|
|
|
|
|
|
|
|
function StringsToArrayOfString(const AStrings: TStrings): TArrayOfString;
|
|
|
|
|
|
|
|
|
|
var
|
|
|
|
|
i: Integer;
|
|
|
|
|
begin
|
|
|
|
|
SetLength(Result, AStrings.Count);
|
|
|
|
|
if AStrings.Count = 0 then
|
|
|
|
|
Exit;
|
|
|
|
|
for i := 0 to AStrings.Count - 1 do
|
|
|
|
|
Result[i] := AStrings[i];
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.Accept(const AcceptHeader: string): TRESTClient;
|
|
|
|
|
begin
|
|
|
|
|
SetAccept(AcceptHeader);
|
|
|
|
|
Result := Self;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.Accept: string;
|
|
|
|
|
begin
|
|
|
|
|
Result := FAccept;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-06-03 22:47:07 +02:00
|
|
|
|
function TRESTClient.Compression(const Enabled: Boolean): TRESTClient; //Ezequiel J. M<>ller
|
|
|
|
|
begin
|
|
|
|
|
if Enabled then
|
|
|
|
|
begin
|
|
|
|
|
if not Assigned(FHTTP.Compressor) then
|
|
|
|
|
FHTTP.Compressor := TIdCompressorZLib.Create(FHTTP);
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
if (FHTTP.Compressor <> nil) then
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.Compressor.Free;
|
|
|
|
|
FHTTP.Compressor := nil;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
Result := Self;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.SSL(const Enabled: Boolean): TRESTClient; //Ezequiel J. M<>ller
|
|
|
|
|
begin
|
|
|
|
|
if Enabled then
|
|
|
|
|
begin
|
|
|
|
|
if not Assigned(FHTTP.IOHandler) then
|
|
|
|
|
FHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(FHTTP);
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
if (FHTTP.IOHandler <> nil) then
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.IOHandler.Free;
|
|
|
|
|
FHTTP.IOHandler := nil;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
Result := Self;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function TRESTClient.AddFile(const FieldName, FileName, ContentType: string): TRESTClient;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
GetMultipartFormData.AddFile(FieldName, FileName, ContentType);
|
2014-06-27 15:30:39 +02:00
|
|
|
|
Result := Self;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.Asynch(AProc: TProc<IRESTResponse>; AProcErr: TProc<Exception>;
|
|
|
|
|
AProcAlways: TProc; ASynchronized: Boolean): TRESTClient;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
FNextRequestIsAsynch := true;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FAsynchProc := AProc;
|
|
|
|
|
FAsynchProcErr := AProcErr;
|
|
|
|
|
FAsynchProcAlways := AProcAlways;
|
2014-04-02 20:27:17 +02:00
|
|
|
|
FSynchronized := ASynchronized;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
Result := Self;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.ClearAllParams: TRESTClient;
|
|
|
|
|
begin
|
|
|
|
|
if Assigned(FRawBody) then
|
|
|
|
|
begin
|
|
|
|
|
FRawBody.Size := 0;
|
|
|
|
|
FRawBody.Position := 0;
|
|
|
|
|
end;
|
|
|
|
|
if Assigned(FBodyParams) then
|
|
|
|
|
FBodyParams.Clear;
|
|
|
|
|
if Assigned(FQueryStringParams) then
|
|
|
|
|
FQueryStringParams.Clear;
|
|
|
|
|
Result := Self;
|
2014-04-02 20:27:17 +02:00
|
|
|
|
FNextRequestIsAsynch := false;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FAsynchProc := nil;
|
|
|
|
|
FAsynchProcErr := nil;
|
|
|
|
|
FAsynchProcAlways := nil;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
UseBasicAuthentication := false;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2014-04-10 13:56:23 +02:00
|
|
|
|
function TRESTClient.ContentEncoding(const ContentEncodingHeader: string): TRESTClient;
|
|
|
|
|
begin
|
|
|
|
|
FContentEncoding := ContentEncodingHeader;
|
|
|
|
|
Result := Self;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.ContentEncoding: string;
|
|
|
|
|
begin
|
|
|
|
|
Result := FContentEncoding;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function TRESTClient.ContentType: string;
|
|
|
|
|
begin
|
|
|
|
|
Result := FContentType;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.ContentType(const ContentTypeHeader: string): TRESTClient;
|
|
|
|
|
begin
|
|
|
|
|
SetContentType(ContentTypeHeader);
|
|
|
|
|
Result := Self;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
constructor TRESTClient.Create(const AServerName: string; AServerPort: Word;
|
|
|
|
|
AIOHandler: TIdIOHandler);
|
2014-04-01 22:32:57 +02:00
|
|
|
|
var
|
2014-06-27 15:30:39 +02:00
|
|
|
|
Pieces: TArray<string>;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
inherited Create;
|
|
|
|
|
FPrimaryThread := TThread.CurrentThread;
|
|
|
|
|
FServerName := AServerName;
|
|
|
|
|
FServerPort := AServerPort;
|
|
|
|
|
FBodyParams := nil; // TStringlist.Create;
|
|
|
|
|
FQueryStringParams := nil; // TStringlist.Create;
|
|
|
|
|
FRawBody := nil; // TStringStream.Create('');
|
|
|
|
|
FAccept := 'application/json';
|
|
|
|
|
FContentType := 'application/json; charset=utf-8';
|
|
|
|
|
FRequestHeaders := TStringlist.Create;
|
2014-04-01 22:32:57 +02:00
|
|
|
|
if AServerName.Contains('://') then
|
|
|
|
|
begin
|
|
|
|
|
Pieces := FServerName.Split(['://'], 2, TStringSplitOptions.ExcludeEmpty);
|
|
|
|
|
FProtocol := Pieces[0];
|
|
|
|
|
FServerName := Pieces[1];
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
FProtocol := 'http';
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
FHTTP := TIdHTTP.Create(nil);
|
|
|
|
|
FHTTP.ReadTimeout := 20000;
|
2015-06-03 22:47:07 +02:00
|
|
|
|
if (AIOHandler <> nil) then //Ezequiel J. M<>ller
|
|
|
|
|
FHTTP.IOHandler := AIOHandler //Ezequiel J. M<>ller
|
|
|
|
|
else
|
|
|
|
|
SSL(False); //Ezequiel J. M<>ller
|
|
|
|
|
Compression(False); //Ezequiel J. M<>ller
|
|
|
|
|
FHTTP.HandleRedirects := True; //Ezequiel J. M<>ller
|
|
|
|
|
FHTTP.Request.CustomHeaders.FoldLines := False; //Ezequiel J. M<>ller
|
|
|
|
|
FHTTP.Request.BasicAuthentication := True;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
// FHTTP.AllowCookies := true;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
destructor TRESTClient.Destroy;
|
|
|
|
|
begin
|
|
|
|
|
FreeAndNil(FBodyParams);
|
|
|
|
|
FreeAndNil(FQueryStringParams);
|
|
|
|
|
FreeAndNil(FRawBody);
|
|
|
|
|
FreeAndNil(FRequestHeaders);
|
|
|
|
|
FreeAndNil(FMultiPartFormData);
|
|
|
|
|
FHTTP.Free;
|
|
|
|
|
inherited;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function TRESTClient.doDELETE(AResource: string; AResourceParams: array of string): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
2014-04-01 02:12:34 +02:00
|
|
|
|
URL: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
URL := FProtocol + '://' + FServerName + ':' + inttostr(FServerPort) + AResource +
|
|
|
|
|
EncodeResourceParams(AResourceParams) + EncodeQueryStringParams(FQueryStringParams);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
if FNextRequestIsAsynch then
|
|
|
|
|
begin
|
|
|
|
|
Result := nil;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
StartAsynchRequest(httpDELETE, URL);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
2014-04-01 02:12:34 +02:00
|
|
|
|
Result := SendHTTPCommand(httpDELETE, FAccept, FContentType, URL, nil);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
ClearAllParams;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-02-16 14:25:09 +01:00
|
|
|
|
procedure TRESTClient.StartAsynchRequest(AHTTPMethod: THttpCommand; AUrl: string);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2013-11-09 14:22:11 +01:00
|
|
|
|
StartAsynchRequest(AHTTPMethod, AUrl, '');
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
procedure TRESTClient.StartAsynchRequest(AHTTPMethod: THttpCommand; AUrl: string;
|
|
|
|
|
ABodyString: string);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
|
|
|
|
th: TThread;
|
|
|
|
|
begin
|
|
|
|
|
th := TThread.CreateAnonymousThread(
|
|
|
|
|
procedure
|
|
|
|
|
var
|
|
|
|
|
R: IRESTResponse;
|
|
|
|
|
begin
|
|
|
|
|
try
|
2015-02-16 14:25:09 +01:00
|
|
|
|
R := SendHTTPCommandWithBody(AHTTPMethod, FAccept, FContentType, AUrl, ABodyString);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
TMonitor.Enter(TObject(R));
|
|
|
|
|
try
|
2014-04-02 20:27:17 +02:00
|
|
|
|
if FSynchronized then
|
|
|
|
|
TThread.Synchronize(nil,
|
|
|
|
|
procedure
|
|
|
|
|
begin
|
|
|
|
|
FAsynchProc(R);
|
|
|
|
|
end)
|
|
|
|
|
else
|
|
|
|
|
FAsynchProc(R);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
finally
|
|
|
|
|
TMonitor.Exit(TObject(R));
|
|
|
|
|
end;
|
|
|
|
|
except
|
|
|
|
|
on E: Exception do
|
|
|
|
|
begin
|
2014-04-02 20:27:17 +02:00
|
|
|
|
if FSynchronized then
|
|
|
|
|
TThread.Synchronize(nil,
|
|
|
|
|
procedure
|
|
|
|
|
begin
|
|
|
|
|
FAsynchProcErr(E);
|
|
|
|
|
end)
|
|
|
|
|
else
|
|
|
|
|
FAsynchProcErr(E);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
if Assigned(FAsynchProcAlways) then
|
2014-04-02 20:27:17 +02:00
|
|
|
|
begin
|
|
|
|
|
if FSynchronized then
|
|
|
|
|
TThread.Synchronize(nil,
|
|
|
|
|
procedure
|
|
|
|
|
begin
|
|
|
|
|
FAsynchProcAlways();
|
|
|
|
|
end)
|
|
|
|
|
else
|
|
|
|
|
FAsynchProcAlways();
|
|
|
|
|
end;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
ClearAllParams;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end);
|
|
|
|
|
th.Start;
|
|
|
|
|
end;
|
|
|
|
|
|
2014-04-02 20:27:17 +02:00
|
|
|
|
function TRESTClient.doGET(AResource: string; AResourceParams: array of string): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
2014-04-01 02:12:34 +02:00
|
|
|
|
URL: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
URL := FProtocol + '://' + FServerName + ':' + inttostr(FServerPort) + AResource +
|
|
|
|
|
EncodeResourceParams(AResourceParams) + EncodeQueryStringParams(FQueryStringParams);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
if FNextRequestIsAsynch then
|
|
|
|
|
begin
|
|
|
|
|
Result := nil;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
StartAsynchRequest(httpGET, URL);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
2014-04-01 02:12:34 +02:00
|
|
|
|
Result := SendHTTPCommand(httpGET, FAccept, FContentType, URL, nil);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
ClearAllParams;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2014-04-02 20:27:17 +02:00
|
|
|
|
function TRESTClient.doPOST(AResource: string; AResourceParams: array of string): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
|
|
|
|
s: string;
|
|
|
|
|
begin
|
|
|
|
|
try
|
2015-04-01 17:01:23 +02:00
|
|
|
|
Result := SendHTTPCommand(httpPOST, FAccept, FContentType, FProtocol + '://' + FServerName + ':'
|
|
|
|
|
+ inttostr(FServerPort) + AResource + EncodeResourceParams(AResourceParams) +
|
|
|
|
|
EncodeQueryStringParams(FQueryStringParams), FBodyParams);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
except
|
|
|
|
|
on E: EIdHTTPProtocolException do
|
|
|
|
|
begin
|
|
|
|
|
s := E.Message;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
ClearAllParams;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.doPOST(AResource: string; AResourceParams: array of string;
|
|
|
|
|
AJSONValue: TJSONValue; AOwnsJSONBody: Boolean): IRESTResponse;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
begin
|
2013-11-11 12:23:49 +01:00
|
|
|
|
if not Assigned(AJSONValue) then
|
|
|
|
|
raise Exception.Create('AJSONValue is nil');
|
2013-11-09 14:22:11 +01:00
|
|
|
|
try
|
2015-01-30 10:36:54 +01:00
|
|
|
|
Result := doPOST(AResource, AResourceParams,
|
2015-02-16 14:25:09 +01:00
|
|
|
|
{$IF CompilerVersion >= 28}
|
|
|
|
|
AJSONValue.ToJSON
|
|
|
|
|
{$ELSE}
|
|
|
|
|
AJSONValue.ToString
|
|
|
|
|
{$ENDIF});
|
2013-11-09 14:22:11 +01:00
|
|
|
|
finally
|
|
|
|
|
if AOwnsJSONBody then
|
|
|
|
|
FreeAndNil(AJSONValue);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.doPATCH(AResource: string; AResourceParams: array of string;
|
|
|
|
|
ABodyString: string): IRESTResponse;
|
2014-03-24 17:37:08 +01:00
|
|
|
|
var
|
2014-04-01 02:12:34 +02:00
|
|
|
|
URL: string;
|
2014-03-24 17:37:08 +01:00
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
URL := FProtocol + '://' + FServerName + ':' + inttostr(FServerPort) + AResource +
|
|
|
|
|
EncodeResourceParams(AResourceParams) + EncodeQueryStringParams(FQueryStringParams);
|
2014-03-24 17:37:08 +01:00
|
|
|
|
|
|
|
|
|
if FNextRequestIsAsynch then
|
|
|
|
|
begin
|
|
|
|
|
Result := nil;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
StartAsynchRequest(httpPOST, URL, ABodyString);
|
2014-03-24 17:37:08 +01:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
2015-02-16 14:25:09 +01:00
|
|
|
|
Result := SendHTTPCommandWithBody(httpPATCH, FAccept, FContentType, URL, ABodyString);
|
2014-03-24 17:37:08 +01:00
|
|
|
|
ClearAllParams;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.doPATCH(AResource: string; AResourceParams: array of string;
|
|
|
|
|
AJSONValue: TJSONValue; AOwnsJSONBody: Boolean): IRESTResponse;
|
2014-03-24 17:37:08 +01:00
|
|
|
|
begin
|
|
|
|
|
if not Assigned(AJSONValue) then
|
|
|
|
|
raise Exception.Create('AJSONValue is nil');
|
|
|
|
|
try
|
2015-01-30 10:36:54 +01:00
|
|
|
|
Result := doPATCH(AResource, AResourceParams,
|
2015-02-16 14:25:09 +01:00
|
|
|
|
{$IF CompilerVersion >= 28}
|
|
|
|
|
AJSONValue.ToJSON
|
|
|
|
|
{$ELSE}
|
|
|
|
|
AJSONValue.ToString
|
|
|
|
|
{$ENDIF});
|
2014-03-24 17:37:08 +01:00
|
|
|
|
finally
|
|
|
|
|
if AOwnsJSONBody then
|
|
|
|
|
FreeAndNil(AJSONValue);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.doPOST(AResource: string; AResourceParams: array of string;
|
|
|
|
|
ABodyString: string): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
2014-04-01 02:12:34 +02:00
|
|
|
|
URL: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
URL := FProtocol + '://' + FServerName + ':' + inttostr(FServerPort) + AResource +
|
|
|
|
|
EncodeResourceParams(AResourceParams) + EncodeQueryStringParams(FQueryStringParams);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
if FNextRequestIsAsynch then
|
|
|
|
|
begin
|
|
|
|
|
Result := nil;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
StartAsynchRequest(httpPOST, URL, ABodyString);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
2015-02-16 14:25:09 +01:00
|
|
|
|
Result := SendHTTPCommandWithBody(httpPOST, FAccept, FContentType, URL, ABodyString);
|
2013-11-09 14:22:11 +01:00
|
|
|
|
ClearAllParams;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.doPUT(AResource: string; AResourceParams: array of string; ABodyString: string)
|
|
|
|
|
: IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
2014-04-01 02:12:34 +02:00
|
|
|
|
URL: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
URL := FProtocol + '://' + FServerName + ':' + inttostr(FServerPort) + AResource +
|
|
|
|
|
EncodeResourceParams(AResourceParams) + EncodeQueryStringParams(FQueryStringParams);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
if FNextRequestIsAsynch then
|
|
|
|
|
begin
|
|
|
|
|
Result := nil;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
StartAsynchRequest(httpPUT, URL, ABodyString);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
2015-02-16 14:25:09 +01:00
|
|
|
|
Result := SendHTTPCommandWithBody(httpPUT, FAccept, FContentType, URL, ABodyString);
|
2013-11-11 12:23:49 +01:00
|
|
|
|
ClearAllParams;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end;
|
|
|
|
|
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function TRESTClient.DSDelete(const URL, KeyValue: string): IRESTResponse;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
begin
|
|
|
|
|
Result := doDELETE(URL, [KeyValue]);
|
|
|
|
|
end;
|
|
|
|
|
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function TRESTClient.DSInsert(const URL: string; DataSet: TDataSet): IRESTResponse;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
begin
|
|
|
|
|
Result := doPOST(URL, [], DataSet.AsJSONObjectString);
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.DSUpdate(const URL: string; DataSet: TDataSet; const KeyValue: string)
|
|
|
|
|
: IRESTResponse;
|
2014-04-01 02:12:34 +02:00
|
|
|
|
begin
|
|
|
|
|
Result := doPUT(URL, [KeyValue], DataSet.AsJSONObjectString);
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.doPUT(AResource: string; AResourceParams: array of string;
|
|
|
|
|
AJSONValue: TJSONValue; AOwnsJSONBody: Boolean = true): IRESTResponse;
|
2013-11-11 12:23:49 +01:00
|
|
|
|
begin
|
|
|
|
|
if not Assigned(AJSONValue) then
|
|
|
|
|
raise Exception.Create('AJSONValue is nil');
|
|
|
|
|
|
|
|
|
|
try
|
2015-01-30 10:36:54 +01:00
|
|
|
|
Result := doPUT(AResource, AResourceParams,
|
2015-02-16 14:25:09 +01:00
|
|
|
|
{$IF CompilerVersion >= 28}
|
|
|
|
|
AJSONValue.ToJSON
|
|
|
|
|
{$ELSE}
|
|
|
|
|
AJSONValue.ToString
|
|
|
|
|
{$ENDIF});
|
2013-11-11 12:23:49 +01:00
|
|
|
|
finally
|
|
|
|
|
if AOwnsJSONBody then
|
|
|
|
|
FreeAndNil(AJSONValue);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function TRESTClient.doPUT(AResource: string; AResourceParams: array of string): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
Result := SendHTTPCommand(httpPUT, FAccept, FContentType, FProtocol + '://' + FServerName + ':' +
|
|
|
|
|
inttostr(FServerPort) + AResource + EncodeResourceParams(AResourceParams) +
|
|
|
|
|
EncodeQueryStringParams(FQueryStringParams), FBodyParams);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
ClearAllParams;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function TRESTClient.EncodeResourceParams(AResourceParams: array of string): string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
|
|
|
|
i: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Result := '';
|
|
|
|
|
for i := low(AResourceParams) to high(AResourceParams) do
|
|
|
|
|
Result := Result + '/' + TIdURI.ParamsEncode(AResourceParams[i]);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.GetBodyParams: TStringlist;
|
|
|
|
|
begin
|
|
|
|
|
if not Assigned(FBodyParams) then
|
|
|
|
|
FBodyParams := TStringlist.Create;
|
|
|
|
|
Result := FBodyParams;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.GetConnectionTimeout: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Result := FHTTP.ConnectTimeout;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.GetMultipartFormData: TIdMultiPartFormDataStream;
|
|
|
|
|
begin
|
|
|
|
|
if not Assigned(FMultiPartFormData) then
|
|
|
|
|
FMultiPartFormData := TIdMultiPartFormDataStream.Create;
|
|
|
|
|
Result := FMultiPartFormData;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.GetPassword: string;
|
|
|
|
|
begin
|
|
|
|
|
Result := FHTTP.Request.Password;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function TRESTClient.GetQueryStringParams: TStringlist;
|
|
|
|
|
begin
|
|
|
|
|
if not Assigned(FQueryStringParams) then
|
|
|
|
|
FQueryStringParams := TStringlist.Create;
|
|
|
|
|
Result := FQueryStringParams;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.GetRawBody: TStringStream;
|
|
|
|
|
begin
|
|
|
|
|
if not Assigned(FRawBody) then
|
|
|
|
|
FRawBody := TStringStream.Create('');
|
|
|
|
|
Result := FRawBody;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.GetSessionID: string;
|
|
|
|
|
begin
|
|
|
|
|
Result := Self.FLastSessionID;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.GetUseBasicAuthentication: Boolean;
|
|
|
|
|
begin
|
|
|
|
|
Result := FHTTP.Request.BasicAuthentication;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.GetUserName: string;
|
|
|
|
|
begin
|
|
|
|
|
Result := FHTTP.Request.Password;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function TRESTClient.GetReadTimeout: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Result := FHTTP.ReadTimeout;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.EncodeQueryStringParams(const AQueryStringParams: TStrings;
|
|
|
|
|
IncludeQuestionMark: Boolean = true): string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
|
|
|
|
i: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Result := '';
|
|
|
|
|
if not Assigned(AQueryStringParams) or (AQueryStringParams.Count = 0) then
|
|
|
|
|
Exit;
|
|
|
|
|
if IncludeQuestionMark then
|
|
|
|
|
Result := '?';
|
|
|
|
|
|
|
|
|
|
for i := 0 to AQueryStringParams.Count - 1 do
|
|
|
|
|
begin
|
|
|
|
|
if i > 0 then
|
|
|
|
|
Result := Result + '&';
|
2015-04-01 17:01:23 +02:00
|
|
|
|
Result := Result + AQueryStringParams.Names[i] + '=' +
|
|
|
|
|
TIdURI.ParamsEncode(AQueryStringParams.ValueFromIndex[i]);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.HandleCookies;
|
|
|
|
|
var
|
2013-11-05 14:57:50 +01:00
|
|
|
|
s: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
arr: TArray<string>;
|
|
|
|
|
begin
|
|
|
|
|
// Log('Received cookies', FHTTP.Response.RawHeaders.Text);
|
|
|
|
|
for s in FHTTP.Response.RawHeaders do
|
|
|
|
|
begin
|
|
|
|
|
if s.StartsWith('Set-Cookie', true) then
|
|
|
|
|
begin
|
|
|
|
|
arr := s.Split([':'], 2);
|
|
|
|
|
if arr[1].trim.StartsWith('dtsessionid') then
|
|
|
|
|
begin
|
|
|
|
|
arr := arr[1].Split(['='], 2);
|
|
|
|
|
FLastSessionID := TIdURI.URLDecode(arr[1].Split([';'])[0]);
|
|
|
|
|
end;
|
|
|
|
|
Break;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.HandleRequestCookies;
|
|
|
|
|
var
|
|
|
|
|
i: Integer;
|
|
|
|
|
begin
|
|
|
|
|
if Assigned(FHTTP.CookieManager) then
|
|
|
|
|
FHTTP.CookieManager.CookieCollection.Clear;
|
|
|
|
|
if not FLastSessionID.trim.IsEmpty then
|
2015-02-16 14:25:09 +01:00
|
|
|
|
FHTTP.Request.CustomHeaders.AddValue('Cookie', 'dtsessionid=' + FLastSessionID);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
for i := 0 to FRequestHeaders.Count - 1 do
|
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
FHTTP.Request.CustomHeaders.AddValue(FRequestHeaders.Names[i],
|
|
|
|
|
FRequestHeaders.ValueFromIndex[i]);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-02-16 14:25:09 +01:00
|
|
|
|
function TRESTClient.HttpCommandToString(const AHttpCommand: THttpCommand): string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
case AHttpCommand of
|
|
|
|
|
httpGET:
|
|
|
|
|
Result := 'GET';
|
|
|
|
|
httpPOST:
|
|
|
|
|
Result := 'POST';
|
|
|
|
|
httpPUT:
|
|
|
|
|
Result := 'PUT';
|
|
|
|
|
httpDELETE:
|
|
|
|
|
Result := 'DELETE';
|
2013-11-05 14:57:50 +01:00
|
|
|
|
else
|
|
|
|
|
raise Exception.Create('Unknown HttpCommand in TRSF.HttpCommandToString');
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTClient.ResetSession: TRESTClient;
|
|
|
|
|
begin
|
|
|
|
|
SessionID := '';
|
|
|
|
|
if Assigned(FHTTP.CookieManager) then
|
|
|
|
|
FHTTP.CookieManager.CookieCollection.Clear;
|
|
|
|
|
FHTTP.Request.RawHeaders.Clear;
|
|
|
|
|
Result := Self;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.SendHTTPCommand(const ACommand: THttpCommand;
|
|
|
|
|
const AAccept, AContentType, AUrl: string; ABodyParams: TStrings): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
Result := TRESTResponse.Create;
|
|
|
|
|
FHTTP.Request.RawHeaders.Clear;
|
|
|
|
|
FHTTP.Request.CustomHeaders.Clear;
|
|
|
|
|
FHTTP.Request.Accept := AAccept;
|
|
|
|
|
FHTTP.Request.ContentType := AContentType;
|
|
|
|
|
HandleRequestCookies;
|
|
|
|
|
try
|
|
|
|
|
case ACommand of
|
|
|
|
|
httpGET:
|
|
|
|
|
begin
|
|
|
|
|
Result.Body.Position := 0;
|
|
|
|
|
FHTTP.Get(AUrl, Result.Body);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
httpPOST:
|
|
|
|
|
begin
|
|
|
|
|
if GetMultipartFormData.Size = 0 then
|
|
|
|
|
begin
|
|
|
|
|
Result.Body.Position := 0;
|
|
|
|
|
GetRawBody; // creates the body
|
|
|
|
|
FHTTP.Post(AUrl, FRawBody, Result.Body);
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.Post(AUrl, GetMultipartFormData, Result.Body);
|
|
|
|
|
GetMultipartFormData.Clear;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
httpPUT:
|
|
|
|
|
begin
|
2015-02-16 14:25:09 +01:00
|
|
|
|
if GetMultipartFormData.Size <> 0 then { TODO -oDaniele -cGeneral : Rework please!!! }
|
2013-10-30 00:48:23 +01:00
|
|
|
|
raise Exception.Create('Only POST can Send Files');
|
|
|
|
|
Result.Body.Position := 0;
|
|
|
|
|
if Assigned(ABodyParams) and (ABodyParams.Count > 0) then
|
|
|
|
|
begin
|
|
|
|
|
GetRawBody.Size := 0;
|
2014-04-02 20:27:17 +02:00
|
|
|
|
GetRawBody.WriteString(EncodeQueryStringParams(ABodyParams, false));
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
FHTTP.Put(AUrl, FRawBody, Result.Body);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
httpDELETE:
|
|
|
|
|
begin
|
|
|
|
|
Result.Body.Position := 0;
|
|
|
|
|
FHTTP.Delete(AUrl);
|
|
|
|
|
GetRawBody.Size := 0;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
except
|
|
|
|
|
on E: EIdHTTPProtocolException do
|
|
|
|
|
begin
|
|
|
|
|
Result.Body.WriteString(E.ErrorMessage);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
HandleCookies;
|
|
|
|
|
Result.SetResponseCode(FHTTP.Response.ResponseCode);
|
|
|
|
|
Result.SetResponseText(FHTTP.Response.ResponseText);
|
|
|
|
|
Result.SetHeaders(FHTTP.Response.RawHeaders);
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
function TRESTClient.SendHTTPCommandWithBody(const ACommand: THttpCommand;
|
|
|
|
|
const AAccept, AContentType, AUrl: string; ABodyString: string): IRESTResponse;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
Result := TRESTResponse.Create;
|
|
|
|
|
FHTTP.Request.RawHeaders.Clear;
|
|
|
|
|
FHTTP.Request.CustomHeaders.Clear;
|
|
|
|
|
FHTTP.Request.Accept := AAccept;
|
|
|
|
|
FHTTP.Request.ContentType := AContentType;
|
|
|
|
|
HandleRequestCookies;
|
|
|
|
|
try
|
|
|
|
|
case ACommand of
|
|
|
|
|
httpGET:
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.Get(AUrl, Result.Body);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
httpPOST:
|
|
|
|
|
begin
|
|
|
|
|
if GetMultipartFormData.Size <> 0 then
|
|
|
|
|
raise Exception.Create('This method cannot send files');
|
|
|
|
|
|
|
|
|
|
RawBody.Position := 0;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FRawBody.Size := 0;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
{$WARNINGS OFF}
|
2015-06-03 22:47:07 +02:00
|
|
|
|
if (LowerCase(FHTTP.Request.CharSet) = 'utf-8') then //Ezequiel Juliano M<>ller - Start
|
|
|
|
|
FRawBody.WriteString(UTF8ToString(ABodyString))
|
|
|
|
|
else
|
|
|
|
|
FRawBody.WriteString(ABodyString); //Ezequiel Juliano M<>ller - End
|
2015-04-01 17:01:23 +02:00
|
|
|
|
{$WARNINGS ON}
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FHTTP.Post(AUrl, FRawBody, Result.Body);
|
|
|
|
|
end;
|
|
|
|
|
|
2014-03-24 17:37:08 +01:00
|
|
|
|
httpPATCH:
|
|
|
|
|
begin
|
2015-04-01 17:01:23 +02:00
|
|
|
|
raise Exception.Create
|
|
|
|
|
('Sorry, PATCH is not supported by the RESTClient because is not supportd by the TidHTTP');
|
2014-03-24 17:37:08 +01:00
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
httpPUT:
|
|
|
|
|
begin
|
|
|
|
|
RawBody.Position := 0;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FRawBody.Size := 0;
|
2015-04-01 17:01:23 +02:00
|
|
|
|
{$WARNINGS OFF}
|
2015-06-03 22:47:07 +02:00
|
|
|
|
if (LowerCase(FHTTP.Request.CharSet) = 'utf-8') then //Ezequiel Juliano M<>ller - Start
|
|
|
|
|
FRawBody.WriteString(UTF8ToString(ABodyString))
|
|
|
|
|
else
|
|
|
|
|
FRawBody.WriteString(ABodyString); //Ezequiel Juliano M<>ller - End
|
2015-04-01 17:01:23 +02:00
|
|
|
|
{$WARNINGS ON}
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FHTTP.Put(AUrl, FRawBody, Result.Body);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
httpDELETE:
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.Delete(AUrl);
|
|
|
|
|
RawBody.Size := 0;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
except
|
|
|
|
|
on E: EIdHTTPProtocolException do
|
|
|
|
|
begin
|
|
|
|
|
Result.Body.WriteString(E.ErrorMessage);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
HandleCookies;
|
|
|
|
|
Result.SetResponseCode(FHTTP.Response.ResponseCode);
|
|
|
|
|
Result.SetResponseText(FHTTP.Response.ResponseText);
|
|
|
|
|
Result.SetHeaders(FHTTP.Response.RawHeaders);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.SetAccept(const Value: string);
|
|
|
|
|
begin
|
|
|
|
|
FAccept := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.SetBodyParams(const Value: TStringlist);
|
|
|
|
|
begin
|
|
|
|
|
FBodyParams := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.SetConnectionTimeout(const Value: Integer);
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.ConnectTimeout := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.SetContentType(const Value: string);
|
|
|
|
|
begin
|
|
|
|
|
FContentType := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
procedure TRESTClient.SetPassword(const Value: string);
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.Request.Password := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
procedure TRESTClient.SetQueryStringParams(const Value: TStringlist);
|
|
|
|
|
begin
|
|
|
|
|
FQueryStringParams := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.SetSessionID(const Value: string);
|
|
|
|
|
begin
|
|
|
|
|
FLastSessionID := Value;
|
|
|
|
|
if Assigned(FHTTP.CookieManager) then
|
|
|
|
|
FHTTP.CookieManager.CookieCollection.Clear;
|
|
|
|
|
end;
|
|
|
|
|
|
2015-04-01 17:01:23 +02:00
|
|
|
|
procedure TRESTClient.SetUseBasicAuthentication(const Value: Boolean);
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.Request.BasicAuthentication := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.SetUserName(const Value: string);
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.Request.UserName := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
procedure TRESTClient.SetReadTimeout(const Value: Integer);
|
|
|
|
|
begin
|
|
|
|
|
FHTTP.ReadTimeout := Value;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTClient.SetRequestHeaders(const Value: TStringlist);
|
|
|
|
|
begin
|
|
|
|
|
FRequestHeaders.Assign(Value);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
{ TRESTResponse }
|
|
|
|
|
|
|
|
|
|
function TRESTResponse.Body: TStringStream;
|
|
|
|
|
begin
|
|
|
|
|
Result := FBody;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTResponse.BodyAsJsonObject: TJSONObject;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
begin
|
|
|
|
|
Result := BodyAsJsonValue as TJSONObject;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTResponse.BodyAsJsonValue: TJSONValue;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
try
|
2013-11-09 14:22:11 +01:00
|
|
|
|
if not Assigned(FBodyAsJSONValue) then
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
if BodyAsString = '' then
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FBodyAsJSONValue := nil
|
2013-10-30 00:48:23 +01:00
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
try
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FBodyAsJSONValue := TJSONObject.ParseJSONValue(BodyAsString);
|
|
|
|
|
// if Assigned(V) then
|
|
|
|
|
// FBodyAsJSONObject := V as TJSONObject;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
except
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FBodyAsJSONValue := nil;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
2013-11-09 14:22:11 +01:00
|
|
|
|
Result := FBodyAsJSONValue;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
except
|
|
|
|
|
on E: Exception do
|
|
|
|
|
begin
|
|
|
|
|
raise;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTResponse.BodyAsString: string;
|
|
|
|
|
var
|
|
|
|
|
ss: TStringStream;
|
|
|
|
|
begin
|
2013-11-05 14:57:50 +01:00
|
|
|
|
if FContentEncoding.IsEmpty then
|
|
|
|
|
FContentEncoding := 'UTF-8';
|
|
|
|
|
ss := TStringStream.Create('', TEncoding.GetEncoding(FContentEncoding));
|
2013-10-30 00:48:23 +01:00
|
|
|
|
try
|
|
|
|
|
FBody.Position := 0;
|
|
|
|
|
FBody.SaveToStream(ss);
|
|
|
|
|
Result := ss.DataString;
|
|
|
|
|
finally
|
|
|
|
|
ss.Free;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
constructor TRESTResponse.Create;
|
|
|
|
|
begin
|
|
|
|
|
inherited;
|
|
|
|
|
FHeaders := TStringlist.Create;
|
|
|
|
|
FBody := TStringStream.Create('', TEncoding.UTF8);
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FBodyAsJSONValue := nil;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
destructor TRESTResponse.Destroy;
|
|
|
|
|
begin
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FreeAndNil(FBodyAsJSONValue);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FHeaders.Free;
|
|
|
|
|
FBody.Free;
|
|
|
|
|
inherited;
|
|
|
|
|
end;
|
|
|
|
|
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function TRESTResponse.GetContentEncoding: string;
|
2013-11-05 14:57:50 +01:00
|
|
|
|
begin
|
|
|
|
|
Result := FContentEncoding;
|
|
|
|
|
end;
|
|
|
|
|
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function TRESTResponse.GetContentType: string;
|
2013-11-05 14:57:50 +01:00
|
|
|
|
begin
|
|
|
|
|
Result := FContentType;
|
|
|
|
|
end;
|
|
|
|
|
|
2014-06-27 15:30:39 +02:00
|
|
|
|
function TRESTResponse.GetHeader(const Value: string): string;
|
2013-11-05 14:57:50 +01:00
|
|
|
|
var
|
2014-06-27 15:30:39 +02:00
|
|
|
|
s: string;
|
2013-11-05 14:57:50 +01:00
|
|
|
|
begin
|
|
|
|
|
if Assigned(FHeaders) and (FHeaders.Count > 0) then
|
|
|
|
|
begin
|
|
|
|
|
for s in FHeaders do
|
|
|
|
|
begin
|
|
|
|
|
if s.StartsWith(Value + ':', true) then
|
|
|
|
|
begin
|
|
|
|
|
Exit(s);
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
Result := '';
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2014-03-31 11:25:16 +02:00
|
|
|
|
function TRESTResponse.GetHeaderValue(const Name: string): string;
|
|
|
|
|
var
|
|
|
|
|
s: string;
|
|
|
|
|
arr: TArray<string>;
|
|
|
|
|
begin
|
|
|
|
|
Result := '';
|
|
|
|
|
for s in Self.Headers do
|
|
|
|
|
begin
|
|
|
|
|
arr := s.Split([':'], 2);
|
|
|
|
|
if SameText(arr[0].trim, name) then
|
|
|
|
|
begin
|
|
|
|
|
Result := arr[1].trim;
|
|
|
|
|
Break;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
function TRESTResponse.Headers: TStringlist;
|
|
|
|
|
begin
|
|
|
|
|
Result := FHeaders;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTResponse.ResponseCode: Word;
|
|
|
|
|
begin
|
|
|
|
|
Result := FResponseCode;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TRESTResponse.ResponseText: string;
|
|
|
|
|
begin
|
|
|
|
|
Result := FResponseText;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTResponse.SetHeaders(AHeaders: TStrings);
|
2013-11-05 14:57:50 +01:00
|
|
|
|
var
|
|
|
|
|
CT: TArray<string>;
|
2014-06-27 15:30:39 +02:00
|
|
|
|
C: string;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
FHeaders.Assign(AHeaders);
|
2013-11-05 14:57:50 +01:00
|
|
|
|
|
|
|
|
|
C := GetHeader('content-type');
|
|
|
|
|
|
|
|
|
|
CT := C.Split([':'])[1].Split([';']);
|
2013-11-09 14:22:11 +01:00
|
|
|
|
FContentType := trim(CT[0]);
|
2013-11-05 14:57:50 +01:00
|
|
|
|
FContentEncoding := 'UTF-8'; // default encoding
|
|
|
|
|
if Length(CT) > 1 then
|
|
|
|
|
begin
|
|
|
|
|
if CT[1].trim.StartsWith('charset', true) then
|
|
|
|
|
begin
|
|
|
|
|
FContentEncoding := CT[1].trim.Split(['='])[1].trim;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTResponse.SetResponseCode(AResponseCode: Word);
|
|
|
|
|
begin
|
|
|
|
|
FResponseCode := AResponseCode;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TRESTResponse.SetResponseText(AResponseText: string);
|
|
|
|
|
begin
|
|
|
|
|
FResponseText := AResponseText;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
end.
|