From fd07c111af00369a393aef9219994cb22a6ecfeb Mon Sep 17 00:00:00 2001 From: Vinicius Sanchez Date: Tue, 30 May 2023 15:18:00 -0300 Subject: [PATCH] #131 --- README.md | 12 +- boss-lock.json | 13 +- boss.json | 4 +- samples/client/delphi/Samples.dproj | 6 + samples/client/delphi/src/Samples.Main.dfm | 11 + samples/client/delphi/src/Samples.Main.pas | 1 + .../mercado-libre/delphi/mercadolibre.dproj | 583 ++++-------------- ...RESTRequest4D.Request.Adapter.Contract.pas | 13 + src/RESTRequest4D.Request.Client.pas | 49 +- src/RESTRequest4D.Request.Contract.pas | 11 +- src/RESTRequest4D.Request.FPHTTPClient.pas | 45 +- src/RESTRequest4D.Request.Indy.pas | 51 +- src/RESTRequest4D.Request.NetHTTP.pas | 47 +- src/RESTRequest4D.Request.Synapse.pas | 49 +- src/RESTRequest4D.Utils.pas | 36 -- src/RESTRequest4D.pas | 3 +- 16 files changed, 316 insertions(+), 618 deletions(-) create mode 100644 src/RESTRequest4D.Request.Adapter.Contract.pas diff --git a/README.md b/README.md index 5948352..60f6da3 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,6 @@ ## ⚙️ Installation -*Prerequisites*: [**DataSet-Serialize**](https://github.com/viniciussanchez/dataset-serialize) - This is a DataSet serializer for Delphi - * **Manual installation**: Add the following folders to your project, in *Project > Options > Resource Compiler > Directories and Conditionals > Include file search path* ``` @@ -34,6 +32,10 @@ By default, the components **TRESTRequest**, **TRESTResponse** and **TRESTClient **Note**: for Lazarus, the **fphttpclient** engine is the default. But you can switch to **Indy** setting `RR4D_INDY` directive or to [**Synapse**](http://www.ararat.cz/synapse/doku.php/download) setting `RR4D_SYNAPSE` directive. +## 🔌 Adapters +Adapters allow you to extend the functionality of RESTREquest4Delphi without changing the core of the project. See the list of adapters available by the community: +* [**DataSet-Serialize**](https://github.com/viniciussanchez/dataset-serialize-adapter-restrequest4delphi) - Adapter to load a DataSet using the DataSet-Serialize library at the time of the request; + ## ⚡️ Quickstart You need to use RESTRequest4D @@ -58,13 +60,13 @@ begin end; ``` -* **GET AS DATASET** +* **GET AS DATASET USING ADAPTERS** ```pascal begin TRequest.New.BaseURL('http://localhost:8888/users') + .Adapters(TDataSetSerializeAdapter.New(FDMemTable)) .Accept('application/json') - .DataSetAdapter(FDMemTable) .Get; end; ``` @@ -141,4 +143,4 @@ node server.js ## ⚠️ License -`RESTRequest4Delphi` is free and open-source software licensed under the [MIT License](https://github.com/viniciussanchez/RESTRequest4Delphi/blob/master/LICENSE). +`RESTRequest4Delphi` is free and open-source software licensed under the [MIT License](https://github.com/viniciussanchez/RESTRequest4Delphi/blob/master/LICENSE). \ No newline at end of file diff --git a/boss-lock.json b/boss-lock.json index 12e8f14..29d7740 100644 --- a/boss-lock.json +++ b/boss-lock.json @@ -1,14 +1,5 @@ { "hash": "cdbb70a8679a51d4358a9e31e1ef566a", - "updated": "2021-03-24T15:27:46.0150426-03:00", - "installedModules": { - "github.com/viniciussanchez/dataset-serialize": { - "name": "dataset-serialize", - "version": "v2.4.9", - "hash": "0df5fa71a508ce66a50ef649231af9c9", - "artifacts": {}, - "failed": false, - "changed": false - } - } + "updated": "2023-05-30T14:30:59.2446954-03:00", + "installedModules": {} } \ No newline at end of file diff --git a/boss.json b/boss.json index a9d00ca..c78de76 100644 --- a/boss.json +++ b/boss.json @@ -5,7 +5,5 @@ "homepage": "", "mainsrc": "src", "projects": [], - "dependencies": { - "github.com/viniciussanchez/dataset-serialize": "^v2.2.9" - } + "dependencies": {} } \ No newline at end of file diff --git a/samples/client/delphi/Samples.dproj b/samples/client/delphi/Samples.dproj index a85ea27..22c71f4 100644 --- a/samples/client/delphi/Samples.dproj +++ b/samples/client/delphi/Samples.dproj @@ -133,6 +133,12 @@ + + + Samples.exe + true + + 1 diff --git a/samples/client/delphi/src/Samples.Main.dfm b/samples/client/delphi/src/Samples.Main.dfm index 84eb521..6f89071 100644 --- a/samples/client/delphi/src/Samples.Main.dfm +++ b/samples/client/delphi/src/Samples.Main.dfm @@ -10809,4 +10809,15 @@ object FrmMain: TFrmMain end end end + object FDMemTable1: TFDMemTable + FetchOptions.AssignedValues = [evMode] + FetchOptions.Mode = fmAll + ResourceOptions.AssignedValues = [rvSilentMode] + ResourceOptions.SilentMode = True + UpdateOptions.AssignedValues = [uvCheckRequired, uvAutoCommitUpdates] + UpdateOptions.CheckRequired = False + UpdateOptions.AutoCommitUpdates = True + Left = 464 + Top = 392 + end end diff --git a/samples/client/delphi/src/Samples.Main.pas b/samples/client/delphi/src/Samples.Main.pas index 94a616c..891b2c2 100644 --- a/samples/client/delphi/src/Samples.Main.pas +++ b/samples/client/delphi/src/Samples.Main.pas @@ -49,6 +49,7 @@ TFrmMain = class(TForm) Panel8: TPanel; lblRESTRequest4DelphiComponent: TLabel; btnMultipartFormDataPut: TButton; + FDMemTable1: TFDMemTable; procedure btnGETClick(Sender: TObject); procedure btnPOSTClick(Sender: TObject); procedure btnPUTClick(Sender: TObject); diff --git a/samples/mercado-libre/delphi/mercadolibre.dproj b/samples/mercado-libre/delphi/mercadolibre.dproj index 55f2951..697b99f 100644 --- a/samples/mercado-libre/delphi/mercadolibre.dproj +++ b/samples/mercado-libre/delphi/mercadolibre.dproj @@ -1,7 +1,7 @@  {5B251B59-DC18-46B7-9FAB-3DD0ED9A8ADB} - 19.4 + 19.5 VCL mercadolibre.dpr True @@ -136,19 +136,9 @@ Microsoft Office XP Sample Automation Server Wrapper Components - - - - mercadolibre.exe - true - - - - - mercadolibre.exe - true - - + + + 1 @@ -171,12 +161,6 @@ 64 - - - classes - 1 - - res\xml @@ -486,7 +470,7 @@ 1 .dylib - + 1 .dylib @@ -519,7 +503,7 @@ 1 .dylib - + 1 .dylib @@ -556,7 +540,7 @@ 0 - + 0 @@ -575,352 +559,294 @@ 0 - - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset - 1 - - - - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + + 1 - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 - - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - - + + + ..\ 1 - + + ..\ 1 - + + ..\ 1 - - + + + Contents 1 - + + Contents 1 - + + Contents 1 - - + + + Contents\Resources 1 - + + Contents\Resources 1 - + + Contents\Resources 1 - - - 1 - - + + + library\lib\armeabi-v7a 1 - + + library\lib\arm64-v8a 1 - - 1 1 - - 1 - - - - + 1 - + 1 - + + Contents\MacOS 1 - - - + + Contents\MacOS 1 - + + Contents\MacOS 1 - - 1 + + 0 - - - 1 - - - 1 - - + + + library\lib\armeabi-v7a 1 - - - 1 - - + + 1 - + 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\ 1 + ..\ 1 - + + ..\ 1 - + 1 1 - + 1 - - - ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset - 1 - - - ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset - 1 - - - - - 1 - + - 1 + ..\$(PROJECTNAME).launchscreen + 64 - - 1 + + ..\$(PROJECTNAME).launchscreen + 64 - + 1 1 - - 1 - - - - - ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset - 1 - - - ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 - - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + + + Assets 1 - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + + Assets 1 - - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + + + Assets 1 - - ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + + Assets 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 @@ -929,82 +855,27 @@ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - - - 1 - - - 1 - - ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - - - - 1 - - - 1 - - - 1 - - ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 @@ -1014,7 +885,7 @@ ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 @@ -1024,7 +895,7 @@ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 @@ -1034,7 +905,7 @@ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 @@ -1044,7 +915,7 @@ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 @@ -1054,7 +925,7 @@ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 @@ -1064,7 +935,7 @@ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 @@ -1074,206 +945,16 @@ ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - - - 1 - - - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - - - 1 - - - 1 - - - - - ..\ - 1 - - - ..\ - 1 - - - - - 1 - - - 1 - - - 1 - - - - - ..\$(PROJECTNAME).launchscreen - 64 - - - ..\$(PROJECTNAME).launchscreen - 64 - - - - - 1 - - - 1 - - - 1 - - - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - - - - - ..\ - 1 - - - ..\ - 1 - - - ..\ - 1 - - - - - Contents - 1 - - - Contents - 1 - - - Contents - 1 - - - - - Contents\Resources - 1 - - - Contents\Resources - 1 - - - Contents\Resources - 1 - - - - - library\lib\armeabi-v7a - 1 - - - library\lib\arm64-v8a - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - Contents\MacOS - 1 - - - Contents\MacOS - 1 - - - Contents\MacOS - 1 - - - 0 - - - - - library\lib\armeabi-v7a - 1 - - - - - 1 - - - 1 - - - - - Assets - 1 - - - Assets - 1 - - - - - Assets - 1 - - - Assets - 1 - - + diff --git a/src/RESTRequest4D.Request.Adapter.Contract.pas b/src/RESTRequest4D.Request.Adapter.Contract.pas new file mode 100644 index 0000000..3d87f30 --- /dev/null +++ b/src/RESTRequest4D.Request.Adapter.Contract.pas @@ -0,0 +1,13 @@ +unit RESTRequest4D.Request.Adapter.Contract; + +interface + +type + IRequestAdapter = interface + ['{27D970B3-9234-4CBF-90C9-74DC4F54A53D}'] + procedure Execute(const AContent: string); + end; + +implementation + +end. diff --git a/src/RESTRequest4D.Request.Client.pas b/src/RESTRequest4D.Request.Client.pas index 74ce034..921c882 100644 --- a/src/RESTRequest4D.Request.Client.pas +++ b/src/RESTRequest4D.Request.Client.pas @@ -4,7 +4,8 @@ interface uses RESTRequest4D.Request.Contract, Data.DB, REST.Client, REST.Response.Adapter, REST.Types, System.SysUtils, System.Classes, RESTRequest4D.Response.Contract, System.JSON{$IF COMPILERVERSION >= 33.0}, System.Net.HttpClient{$ENDIF}, - REST.Authenticator.Basic {$IF COMPILERVERSION <= 32.0}, IPPeerClient, IPPeerCommon{$ENDIF}; + REST.Authenticator.Basic {$IF COMPILERVERSION <= 32.0}, IPPeerClient, IPPeerCommon{$ENDIF}, + RESTRequest4D.Request.Adapter.Contract; type TRequestClient = class(TInterfacedObject, IRequest) @@ -14,7 +15,7 @@ TRequestClient = class(TInterfacedObject, IRequest) FHeaders: TStrings; FHTTPBasicAuthenticator: THTTPBasicAuthenticator; FRESTRequest: TRESTRequest; - FDataSetAdapter: TDataSet; + FAdapters: TArray; FRESTResponse: TRESTResponse; FRESTClient: TRESTClient; FRetries: Integer; @@ -27,8 +28,9 @@ TRequestClient = class(TInterfacedObject, IRequest) function AcceptCharset(const AAcceptCharset: string): IRequest; overload; function Accept: string; overload; function Accept(const AAccept: string): IRequest; overload; - function DataSetAdapter(const ADataSet: TDataSet): IRequest; overload; - function DataSetAdapter: TDataSet; overload; + function Adapters(const AAdapter: IRequestAdapter): IRequest; overload; + function Adapters(const AAdapters: TArray): IRequest; overload; + function Adapters: TArray; overload; function BaseURL(const ABaseURL: string): IRequest; overload; function BaseURL: string; overload; function Resource(const AResource: string): IRequest; overload; @@ -82,8 +84,7 @@ TRequestClient = class(TInterfacedObject, IRequest) implementation -uses DataSet.Serialize, System.Generics.Collections, FireDAC.Comp.DataSet, FireDAC.Comp.Client, RESTRequest4D.Response.Client, - RESTRequest4D.Utils; +uses System.Generics.Collections, FireDAC.Comp.DataSet, FireDAC.Comp.Client, RESTRequest4D.Response.Client; function TRequestClient.AddBody(const AContent: string; const AContentType: TRESTContentType): IRequest; begin @@ -327,12 +328,11 @@ destructor TRequestClient.Destroy; end; procedure TRequestClient.DoAfterExecute(Sender: TCustomRESTRequest); +var + LAdapter: IRequestAdapter; begin - if not Assigned(FDataSetAdapter) then - Exit; - TRESTRequest4DelphiUtils.ActiveCachedUpdates(FDataSetAdapter, False); - FDataSetAdapter.LoadFromJSON(FRESTResponse.Content); - TRESTRequest4DelphiUtils.ActiveCachedUpdates(FDataSetAdapter); + for LAdapter in FAdapters do + LAdapter.Execute(FRESTResponse.Content); end; procedure TRequestClient.DoBeforeExecute(Sender: TCustomRESTRequest); @@ -399,11 +399,6 @@ function TRequestClient.BaseURL: string; Result := FRESTClient.BaseURL; end; -function TRequestClient.DataSetAdapter: TDataSet; -begin - Result := FDataSetAdapter; -end; - function TRequestClient.FallbackCharsetEncoding(const AFallbackCharsetEncoding: string): IRequest; begin Result := Self; @@ -523,12 +518,6 @@ function TRequestClient.BaseURL(const ABaseURL: string): IRequest; FRESTClient.BaseURL := PrepareUrlSegments(ABaseURL); end; -function TRequestClient.DataSetAdapter(const ADataSet: TDataSet): IRequest; -begin - Result := Self; - FDataSetAdapter := ADataSet; -end; - function TRequestClient.RaiseExceptionOn500: Boolean; begin Result := FRESTClient.RaiseExceptionOn500; @@ -579,6 +568,22 @@ function TRequestClient.TokenBearer(const AToken: string): IRequest; Self.Token('Bearer ' + AToken); end; +function TRequestClient.Adapters(const AAdapter: IRequestAdapter): IRequest; +begin + Result := Adapters([AAdapter]); +end; + +function TRequestClient.Adapters(const AAdapters: TArray): IRequest; +begin + FAdapters := AAdapters; + Result := Self; +end; + +function TRequestClient.Adapters: TArray; +begin + Result := FAdapters; +end; + function TRequestClient.AddBody(const AContent: TStream; const AOwns: Boolean): IRequest; begin Result := Self; diff --git a/src/RESTRequest4D.Request.Contract.pas b/src/RESTRequest4D.Request.Contract.pas index e3ab997..fe43b1c 100644 --- a/src/RESTRequest4D.Request.Contract.pas +++ b/src/RESTRequest4D.Request.Contract.pas @@ -1,8 +1,12 @@ unit RESTRequest4D.Request.Contract; +{$IFDEF FPC} + {$mode delphi} +{$ENDIF} + interface -uses RESTRequest4D.Response.Contract, +uses RESTRequest4D.Response.Contract, RESTRequest4D.Request.Adapter.Contract, {$IF NOT (DEFINED(RR4D_INDY) or DEFINED(FPC) or DEFINED(RR4D_NETHTTP))} REST.Types, {$ENDIF} @@ -30,8 +34,9 @@ interface {$ENDIF} function Timeout: Integer; overload; function Timeout(const ATimeout: Integer): IRequest; overload; - function DataSetAdapter(const ADataSet: TDataSet): IRequest; overload; - function DataSetAdapter: TDataSet; overload; + function Adapters(const AAdapter: IRequestAdapter): IRequest; overload; + function Adapters(const AAdapters: TArray): IRequest; overload; + function Adapters: TArray; overload; function BaseURL(const ABaseURL: string): IRequest; overload; function BaseURL: string; overload; function Resource(const AResource: string): IRequest; overload; diff --git a/src/RESTRequest4D.Request.FPHTTPClient.pas b/src/RESTRequest4D.Request.FPHTTPClient.pas index a4f56c7..bc6c6a8 100644 --- a/src/RESTRequest4D.Request.FPHTTPClient.pas +++ b/src/RESTRequest4D.Request.FPHTTPClient.pas @@ -7,8 +7,8 @@ interface uses Classes, SysUtils, DB, RESTRequest4D.Request.Contract, RESTRequest4D.Response.Contract, - RESTRequest4D.Utils, DataSet.Serialize, FPHTTPClient, openssl, opensslsockets, fpjson, fpjsonrtti, - Generics.Collections; + RESTRequest4D.Utils, FPHTTPClient, openssl, opensslsockets, fpjson, fpjsonrtti, + RESTRequest4D.Request.Adapter.Contract, Generics.Collections; type TFile = class @@ -32,7 +32,7 @@ TRequestFPHTTPClient = class(TInterfacedObject, IRequest) FBaseURL: string; FResource: string; FResourceSuffix: string; - FDataSetAdapter: TDataSet; + FAdapters: TArray; FResponse: IResponse; FStreamSend: TStream; FRetries: Integer; @@ -45,8 +45,9 @@ TRequestFPHTTPClient = class(TInterfacedObject, IRequest) function Accept(const AAccept: string): IRequest; overload; function Timeout: Integer; overload; function Timeout(const ATimeout: Integer): IRequest; overload; - function DataSetAdapter(const ADataSet: TDataSet): IRequest; overload; - function DataSetAdapter: TDataSet; overload; + function Adapters(const AAdapter: IRequestAdapter): IRequest; overload; + function Adapters(const AAdapters: TArray): IRequest; overload; + function Adapters: TArray; overload; function BaseURL(const ABaseURL: string): IRequest; overload; function BaseURL: string; overload; function Resource(const AResource: string): IRequest; overload; @@ -234,17 +235,6 @@ function TRequestFPHTTPClient.Timeout(const ATimeout: Integer): IRequest; FFPHTTPClient.ConnectTimeout := ATimeout; end; -function TRequestFPHTTPClient.DataSetAdapter(const ADataSet: TDataSet): IRequest; -begin - Result := Self; - FDataSetAdapter := ADataSet; -end; - -function TRequestFPHTTPClient.DataSetAdapter: TDataSet; -begin - Result := FDataSetAdapter; -end; - function TRequestFPHTTPClient.BaseURL(const ABaseURL: string): IRequest; begin Result := Self; @@ -576,11 +566,28 @@ function TRequestFPHTTPClient.DeactivateProxy: IRequest; FFPHTTPClient.Proxy.Port := 0; end; +function TRequestFPHTTPClient.Adapters(const AAdapter: IRequestAdapter): IRequest; +begin + Result := Adapters([AAdapter]); +end; + +function TRequestFPHTTPClient.Adapters(const AAdapters: TArray): IRequest; +begin + FAdapters := AAdapters; + Result := Self; +end; + +function TRequestFPHTTPClient.Adapters: TArray; +begin + Result := FAdapters; +end; + procedure TRequestFPHTTPClient.DoAfterExecute(const Sender: TObject; const AResponse: IResponse); +var + LAdapter: IRequestAdapter; begin - if not Assigned(FDataSetAdapter) then - Exit; - FDataSetAdapter.LoadFromJSON(FResponse.Content); + for LAdapter in FAdapters do + LAdapter.Execute(FResponse.Content); end; procedure TRequestFPHTTPClient.DoBeforeExecute(const Sender: TFPHTTPClient); diff --git a/src/RESTRequest4D.Request.Indy.pas b/src/RESTRequest4D.Request.Indy.pas index 011ed42..7786ee3 100644 --- a/src/RESTRequest4D.Request.Indy.pas +++ b/src/RESTRequest4D.Request.Indy.pas @@ -7,7 +7,7 @@ interface uses RESTRequest4D.Request.Contract, RESTRequest4D.Response.Contract, IdHTTP, IdSSLOpenSSL, IdCTypes, IdSSLOpenSSLHeaders, - RESTRequest4D.Utils, IdMultipartFormData, + RESTRequest4D.Utils, RESTRequest4D.Request.Adapter.Contract, IdMultipartFormData, {$IFDEF FPC} DB, Classes, fpjson, jsonparser, fpjsonrtti, SysUtils; {$ELSE} @@ -26,7 +26,7 @@ TRequestIndy = class(TInterfacedObject, IRequest) FBaseURL: string; FResource: string; FResourceSuffix: string; - FDataSetAdapter: TDataSet; + FAdapters: TArray; FResponse: IResponse; FStreamSend: TStream; FStreamResult: TStringStream; @@ -40,8 +40,9 @@ TRequestIndy = class(TInterfacedObject, IRequest) function Accept(const AAccept: string): IRequest; overload; function Timeout: Integer; overload; function Timeout(const ATimeout: Integer): IRequest; overload; - function DataSetAdapter(const ADataSet: TDataSet): IRequest; overload; - function DataSetAdapter: TDataSet; overload; + function Adapters(const AAdapter: IRequestAdapter): IRequest; overload; + function Adapters(const AAdapters: TArray): IRequest; overload; + function Adapters: TArray; overload; function BaseURL(const ABaseURL: string): IRequest; overload; function BaseURL: string; overload; function Resource(const AResource: string): IRequest; overload; @@ -94,7 +95,7 @@ TRequestIndy = class(TInterfacedObject, IRequest) implementation -uses RESTRequest4D.Response.Indy, IdURI, DataSet.Serialize, IdCookieManager; +uses RESTRequest4D.Response.Indy, IdURI, IdCookieManager; function TRequestIndy.AddField(const AFieldName: string; const AValue: string): IRequest; begin @@ -193,17 +194,28 @@ function TRequestIndy.RaiseExceptionOn500(const ARaiseException: Boolean): IRequ FIdHTTP.HTTPOptions := FIdHTTP.HTTPOptions + [hoNoProtocolErrorException]; end; +function TRequestIndy.Adapters(const AAdapter: IRequestAdapter): IRequest; +begin + Result := Adapters([AAdapter]); +end; + +function TRequestIndy.Adapters(const AAdapters: TArray): IRequest; +begin + FAdapters := AAdapters; + Result := Self; +end; + +function TRequestIndy.Adapters: TArray; +begin + Result := FAdapters; +end; + procedure TRequestIndy.DoAfterExecute; +var + LAdapter: IRequestAdapter; begin - if not Assigned(FDataSetAdapter) then - Exit; - {$IF DEFINED(FPC)} - FDataSetAdapter.LoadFromJSON(FResponse.Content); - {$ELSE} - TRESTRequest4DelphiUtils.ActiveCachedUpdates(FDataSetAdapter, False); - FDataSetAdapter.LoadFromJSON(FResponse.Content); - TRESTRequest4DelphiUtils.ActiveCachedUpdates(FDataSetAdapter); - {$ENDIF} + for LAdapter in FAdapters do + LAdapter.Execute(FResponse.Content); end; procedure TRequestIndy.ExecuteRequest(const AMethod: TMethodRequest); @@ -501,17 +513,6 @@ function TRequestIndy.AddBody(const AContent: TJSONObject; const AOwns: Boolean) end; end; -function TRequestIndy.DataSetAdapter(const ADataSet: TDataSet): IRequest; -begin - Result := Self; - FDataSetAdapter := ADataSet; -end; - -function TRequestIndy.DataSetAdapter: TDataSet; -begin - Result := FDataSetAdapter; -end; - function TRequestIndy.ClearHeaders: IRequest; var I: Integer; diff --git a/src/RESTRequest4D.Request.NetHTTP.pas b/src/RESTRequest4D.Request.NetHTTP.pas index 2dd5dc0..6c6c22f 100644 --- a/src/RESTRequest4D.Request.NetHTTP.pas +++ b/src/RESTRequest4D.Request.NetHTTP.pas @@ -3,8 +3,8 @@ interface uses System.Net.Mime, System.Net.HttpClientComponent, System.Net.HttpClient, RESTRequest4D.Request.Contract, System.Classes, - Data.DB, System.JSON, System.SysUtils, REST.Json, IdURI, System.NetEncoding, RESTRequest4D.Utils, DataSet.Serialize, - RESTRequest4D.Response.NetHTTP, RESTRequest4D.Response.Contract, System.Net.URLClient; + Data.DB, System.JSON, System.SysUtils, REST.Json, IdURI, System.NetEncoding, RESTRequest4D.Utils, System.Net.URLClient, + RESTRequest4D.Response.NetHTTP, RESTRequest4D.Request.Adapter.Contract, RESTRequest4D.Response.Contract; type TRequestNetHTTP = class(TInterfacedObject, IRequest) @@ -17,7 +17,7 @@ TRequestNetHTTP = class(TInterfacedObject, IRequest) FBaseURL: string; FResource: string; FResourceSuffix: string; - FDataSetAdapter: TDataSet; + FAdapters: TArray; FResponse: IResponse; FStreamSend: TStream; FStreamResult: TStringStream; @@ -31,8 +31,9 @@ TRequestNetHTTP = class(TInterfacedObject, IRequest) function Accept(const AAccept: string): IRequest; overload; function Timeout: Integer; overload; function Timeout(const ATimeout: Integer): IRequest; overload; - function DataSetAdapter(const ADataSet: TDataSet): IRequest; overload; - function DataSetAdapter: TDataSet; overload; + function Adapters(const AAdapter: IRequestAdapter): IRequest; overload; + function Adapters(const AAdapters: TArray): IRequest; overload; + function Adapters: TArray; overload; function BaseURL(const ABaseURL: string): IRequest; overload; function BaseURL: string; overload; function Resource(const AResource: string): IRequest; overload; @@ -383,17 +384,6 @@ constructor TRequestNetHTTP.Create; FUseMultipartFormData := False; end; -function TRequestNetHTTP.DataSetAdapter: TDataSet; -begin - Result := FDataSetAdapter; -end; - -function TRequestNetHTTP.DataSetAdapter(const ADataSet: TDataSet): IRequest; -begin - Result := Self; - FDataSetAdapter := ADataSet; -end; - function TRequestNetHTTP.DeactivateProxy: IRequest; begin Result := Self; @@ -424,13 +414,28 @@ destructor TRequestNetHTTP.Destroy; inherited; end; +function TRequestNetHTTP.Adapters(const AAdapter: IRequestAdapter): IRequest; +begin + Result := Adapters([AAdapter]); +end; + +function TRequestNetHTTP.Adapters(const AAdapters: TArray): IRequest; +begin + FAdapters := AAdapters; + Result := Self; +end; + +function TRequestNetHTTP.Adapters: TArray; +begin + Result := FAdapters; +end; + procedure TRequestNetHTTP.DoAfterExecute(const Sender: TObject; const AResponse: IHTTPResponse); +var + LAdapter: IRequestAdapter; begin - if not Assigned(FDataSetAdapter) then - Exit; - TRESTRequest4DelphiUtils.ActiveCachedUpdates(FDataSetAdapter, False); - FDataSetAdapter.LoadFromJSON(FResponse.Content); - TRESTRequest4DelphiUtils.ActiveCachedUpdates(FDataSetAdapter); + for LAdapter in FAdapters do + LAdapter.Execute(FResponse.Content); end; procedure TRequestNetHTTP.DoBeforeExecute(const Sender: TNetHTTPClient); diff --git a/src/RESTRequest4D.Request.Synapse.pas b/src/RESTRequest4D.Request.Synapse.pas index 9bc9853..d0aa4d9 100644 --- a/src/RESTRequest4D.Request.Synapse.pas +++ b/src/RESTRequest4D.Request.Synapse.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, DB, RESTRequest4D.Request.Contract, RESTRequest4D.Response.Contract, RESTRequest4D.Utils, - DataSet.Serialize, httpsend, ssl_openssl, Generics.Collections, + httpsend, ssl_openssl, Generics.Collections, RESTRequest4D.Request.Adapter.Contract, {$IFDEF FPC} fpjson, fpjsonrtti, base64; {$ELSE} @@ -38,7 +38,7 @@ TRequestSynapse = class(TInterfacedObject, IRequest) FBaseURL: string; FResource: string; FResourceSuffix: string; - FDataSetAdapter: TDataSet; + FAdapters: TArray; FResponse: IResponse; FStreamSend: TStream; FRetries: Integer; @@ -47,14 +47,15 @@ TRequestSynapse = class(TInterfacedObject, IRequest) function AcceptEncoding(const AAcceptEncoding: string): IRequest; overload; function AcceptCharset: string; overload; function AcceptCharset(const AAcceptCharset: string): IRequest; overload; + function Adapters(const AAdapter: IRequestAdapter): IRequest; overload; + function Adapters(const AAdapters: TArray): IRequest; overload; + function Adapters: TArray; overload; function Accept: string; overload; function Accept(const AAccept: string): IRequest; overload; function MimeType: string; overload; function MimeType(const AMimeType: string): IRequest; overload; function Timeout: Integer; overload; function Timeout(const ATimeout: Integer): IRequest; overload; - function DataSetAdapter(const ADataSet: TDataSet): IRequest; overload; - function DataSetAdapter: TDataSet; overload; function BaseURL(const ABaseURL: string): IRequest; overload; function BaseURL: string; overload; function Resource(const AResource: string): IRequest; overload; @@ -145,7 +146,7 @@ procedure TRequestSynapse.ExecuteRequest(const AMethod: TMethodRequest); LContent := sLineBreak + '--' + LBound + sLineBreak + 'Content-Disposition: form-data; name=' + AnsiQuotedStr(LFieldName, '"') + sLineBreak + sLineBreak + FFields.Items[LFieldName]+ sLineBreak + sLineBreak; - LStream.Write(PAnsiChar(LContent)^, Length(LContent)); + LStream.Write(PAnsiChar(AnsiString(LContent))^, Length(LContent)); end; for LFieldName in FFiles.Keys do @@ -156,13 +157,13 @@ procedure TRequestSynapse.ExecuteRequest(const AMethod: TMethodRequest); 'Content-Disposition: form-data; name=' + AnsiQuotedStr(LFieldName, '"') +';' + sLineBreak + #9'filename=' + AnsiQuotedStr(LFile.FFileName, '"') + sLineBreak + 'Content-Type: '+AnsiQuotedStr(LFile.FContentType, '"') + sLineBreak + sLineBreak; - LStream.Write(PAnsiChar(LContent)^, Length(LContent)); + LStream.Write(PAnsiChar(AnsiString(LContent))^, Length(LContent)); LFile.FFileStream.Position := 0; LStream.Write(LFile.FFileStream, LFile.FFileStream.Size); end; LBound := '--' +LBound+ '--' +sLineBreak; - LStream.Write(PAnsiChar(LBound)^, Length(LBound)); + LStream.Write(PAnsiChar(AnsiString(LBound))^, Length(LBound)); LStream.Position := 0; FHTTPSend.Document.LoadFromStream(LStream); end @@ -248,17 +249,6 @@ function TRequestSynapse.Timeout(const ATimeout: Integer): IRequest; FHTTPSend.Timeout := ATimeout; end; -function TRequestSynapse.DataSetAdapter(const ADataSet: TDataSet): IRequest; -begin - Result := Self; - FDataSetAdapter := ADataSet; -end; - -function TRequestSynapse.DataSetAdapter: TDataSet; -begin - Result := FDataSetAdapter; -end; - function TRequestSynapse.BaseURL(const ABaseURL: string): IRequest; begin Result := Self; @@ -444,6 +434,22 @@ function TRequestSynapse.AddBody(const AContent: TObject; const AOwns: Boolean): end; end; +function TRequestSynapse.Adapters(const AAdapter: IRequestAdapter): IRequest; +begin + Result := Adapters([AAdapter]); +end; + +function TRequestSynapse.Adapters(const AAdapters: TArray): IRequest; +begin + FAdapters := AAdapters; + Result := Self; +end; + +function TRequestSynapse.Adapters: TArray; +begin + Result := FAdapters; +end; + function TRequestSynapse.AddBody(const AContent: TStream; const AOwns: Boolean): IRequest; begin Result := Self; @@ -635,10 +641,11 @@ function TRequestSynapse.DeactivateProxy: IRequest; end; procedure TRequestSynapse.DoAfterExecute(const Sender: TObject; const AResponse: IResponse); +var + LAdapter: IRequestAdapter; begin - if not Assigned(FDataSetAdapter) then - Exit; - FDataSetAdapter.LoadFromJSON(FResponse.Content); + for LAdapter in FAdapters do + LAdapter.Execute(FResponse.Content); end; procedure TRequestSynapse.DoBeforeExecute(const Sender: THTTPSend); diff --git a/src/RESTRequest4D.Utils.pas b/src/RESTRequest4D.Utils.pas index cdd246f..612c366 100644 --- a/src/RESTRequest4D.Utils.pas +++ b/src/RESTRequest4D.Utils.pas @@ -2,45 +2,9 @@ interface -{$IFNDEF FPC} -uses DB; -{$ENDIF} - type TMethodRequest = (mrGET, mrPOST, mrPUT, mrPATCH, mrDELETE); - TRESTRequest4DelphiUtils = class - public - {$IFNDEF FPC} - class procedure ActiveCachedUpdates(const ADataSet: TDataSet; const AActive: Boolean = True); - {$ENDIF} - end; - implementation -{$IFNDEF FPC} -uses System.Generics.Collections, FireDAC.Comp.Client; - -class procedure TRESTRequest4DelphiUtils.ActiveCachedUpdates(const ADataSet: TDataSet; const AActive: Boolean); -var - LDataSet: TDataSet; - LDataSetDetails: TList; -begin - LDataSetDetails := TList.Create; - try - if not AActive then - ADataSet.Close; - if ADataSet is TFDMemTable then - TFDMemTable(ADataSet).CachedUpdates := AActive; - if AActive and (not ADataSet.Active) and (ADataSet.FieldCount > 0) then - ADataSet.Open; - ADataSet.GetDetailDataSets(LDataSetDetails); - for LDataSet in LDataSetDetails do - ActiveCachedUpdates(LDataSet, AActive); - finally - LDataSetDetails.Free; - end; -end; -{$ENDIF} - end. diff --git a/src/RESTRequest4D.pas b/src/RESTRequest4D.pas index 8eed955..1a18c93 100644 --- a/src/RESTRequest4D.pas +++ b/src/RESTRequest4D.pas @@ -6,10 +6,11 @@ interface {$IF NOT (DEFINED(RR4D_INDY) or DEFINED(FPC) or DEFINED(RR4D_NETHTTP))} REST.Types, {$ENDIF} - RESTRequest4D.Request.Contract, RESTRequest4D.Response.Contract; + RESTRequest4D.Request.Contract, RESTRequest4D.Response.Contract, RESTRequest4D.Request.Adapter.Contract; type IRequest = RESTRequest4D.Request.Contract.IRequest; + IRequestAdapter = RESTRequest4D.Request.Adapter.Contract.IRequestAdapter; IResponse = RESTRequest4D.Response.Contract.IResponse; TRequest = class