mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 07:45:54 +01:00
Improvements to the JSON-RPC layer, added MAX_REQUEST_SIZE check and config key. UPdated IDE Expert to add the new config key in the generated code.
This commit is contained in:
parent
2ec82ee373
commit
f64eebff6a
@ -69,6 +69,7 @@
|
|||||||
- Refactored ISAPI sample
|
- Refactored ISAPI sample
|
||||||
- Speed improvement! Removed enhanced visibility for action methods. Now only public and published methods can be used as actions.
|
- Speed improvement! Removed enhanced visibility for action methods. Now only public and published methods can be used as actions.
|
||||||
- `TMVCController.Create` is `virtual`! Now on your base controllers can be even more powerful!
|
- `TMVCController.Create` is `virtual`! Now on your base controllers can be even more powerful!
|
||||||
|
- New! Added `MAX_REQUEST_SIZE` for limiting the size of the incoming HTTP requests. IDE Expert is updated too!
|
||||||
- New! Added method `TMVCJsonDataObjectsSerializer.ListToJsonArray`
|
- New! Added method `TMVCJsonDataObjectsSerializer.ListToJsonArray`
|
||||||
- New! `TMVCResponse` for handle generic (non error) response
|
- New! `TMVCResponse` for handle generic (non error) response
|
||||||
- New! `TMVCErrorResponse` for handle generic error response
|
- New! `TMVCErrorResponse` for handle generic error response
|
||||||
@ -87,6 +88,7 @@
|
|||||||
- Sending wrongly formatted JSON now returns a more correctly `400 Bad Request` and not `500 Internal Server Error` as in the previous versions
|
- Sending wrongly formatted JSON now returns a more correctly `400 Bad Request` and not `500 Internal Server Error` as in the previous versions
|
||||||
- New! Support for Spring4d nullable types (check `samples\renders_spring4d_nullables`)
|
- New! Support for Spring4d nullable types (check `samples\renders_spring4d_nullables`)
|
||||||
- New! `TMVCJSONRPCPublisher` allows to easily expose plain Delphi objects (and even datamodules) through a JSON-RPC 2.0 interface!
|
- New! `TMVCJSONRPCPublisher` allows to easily expose plain Delphi objects (and even datamodules) through a JSON-RPC 2.0 interface!
|
||||||
|
- *Breaking Change!* The JSON RPC Client layer is now interface based.
|
||||||
|
|
||||||
|
|
||||||
## How to correctly get the source
|
## How to correctly get the source
|
||||||
|
@ -330,6 +330,8 @@ resourcestring
|
|||||||
' Config[TMVCConfigKey.ExposeServerSignature] := ''true'';' + sLineBreak +
|
' Config[TMVCConfigKey.ExposeServerSignature] := ''true'';' + sLineBreak +
|
||||||
' // Define a default URL for requests that don''t map to a route or a file (useful for client side web app)' + sLineBreak +
|
' // Define a default URL for requests that don''t map to a route or a file (useful for client side web app)' + sLineBreak +
|
||||||
' Config[TMVCConfigKey.FallbackResource] := ''index.html'';' + sLineBreak +
|
' Config[TMVCConfigKey.FallbackResource] := ''index.html'';' + sLineBreak +
|
||||||
|
' // Max request size in bytes' + sLineBreak +
|
||||||
|
' Config[TMVCConfigKey.MaxRequestSize] := IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE);' + sLineBreak +
|
||||||
' end);' + sLineBreak +
|
' end);' + sLineBreak +
|
||||||
' FMVC.AddController(%3:s);' + sLineBreak +
|
' FMVC.AddController(%3:s);' + sLineBreak +
|
||||||
' // To enable compression (deflate, gzip) just add this middleware as the last one ' + sLineBreak +
|
' // To enable compression (deflate, gzip) just add this middleware as the last one ' + sLineBreak +
|
||||||
|
@ -4,7 +4,6 @@ program activerecord_crud;
|
|||||||
|
|
||||||
|
|
||||||
uses
|
uses
|
||||||
// FastMM4,
|
|
||||||
FireDAC.Phys.FB,
|
FireDAC.Phys.FB,
|
||||||
System.SysUtils,
|
System.SysUtils,
|
||||||
MVCFramework.Logger,
|
MVCFramework.Logger,
|
||||||
@ -14,14 +13,16 @@ uses
|
|||||||
Web.WebReq,
|
Web.WebReq,
|
||||||
Web.WebBroker,
|
Web.WebBroker,
|
||||||
IdHTTPWebBrokerBridge,
|
IdHTTPWebBrokerBridge,
|
||||||
WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule} ,
|
WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule},
|
||||||
Entities in 'Entities.pas',
|
Entities in 'Entities.pas',
|
||||||
FDConnectionConfigU in 'FDConnectionConfigU.pas',
|
FDConnectionConfigU in 'FDConnectionConfigU.pas',
|
||||||
MVCFramework.ActiveRecordController in '..\..\sources\MVCFramework.ActiveRecordController.pas',
|
MVCFramework.ActiveRecordController in '..\..\sources\MVCFramework.ActiveRecordController.pas',
|
||||||
MVCFramework.ActiveRecord in '..\..\sources\MVCFramework.ActiveRecord.pas',
|
MVCFramework.ActiveRecord in '..\..\sources\MVCFramework.ActiveRecord.pas',
|
||||||
MVCFramework.RQL.AST2MySQL in '..\..\sources\MVCFramework.RQL.AST2MySQL.pas',
|
MVCFramework.RQL.AST2MySQL in '..\..\sources\MVCFramework.RQL.AST2MySQL.pas',
|
||||||
MVCFramework.RQL.AST2FirebirdSQL in '..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas',
|
MVCFramework.RQL.AST2FirebirdSQL in '..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas',
|
||||||
EntitiesProcessors in 'EntitiesProcessors.pas';
|
EntitiesProcessors in 'EntitiesProcessors.pas',
|
||||||
|
MVCFramework.RQL.AST2InterbaseSQL in '..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas',
|
||||||
|
MVCFramework.RQL.AST2PostgreSQL in '..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas';
|
||||||
|
|
||||||
{$R *.res}
|
{$R *.res}
|
||||||
|
|
||||||
|
@ -125,6 +125,8 @@
|
|||||||
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2MySQL.pas"/>
|
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2MySQL.pas"/>
|
||||||
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas"/>
|
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2FirebirdSQL.pas"/>
|
||||||
<DCCReference Include="EntitiesProcessors.pas"/>
|
<DCCReference Include="EntitiesProcessors.pas"/>
|
||||||
|
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2InterbaseSQL.pas"/>
|
||||||
|
<DCCReference Include="..\..\sources\MVCFramework.RQL.AST2PostgreSQL.pas"/>
|
||||||
<BuildConfiguration Include="Release">
|
<BuildConfiguration Include="Release">
|
||||||
<Key>Cfg_2</Key>
|
<Key>Cfg_2</Key>
|
||||||
<CfgParent>Base</CfgParent>
|
<CfgParent>Base</CfgParent>
|
||||||
@ -173,7 +175,7 @@
|
|||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployFile>
|
</DeployFile>
|
||||||
<DeployFile LocalName="Win32\Debug\activerecord_crud.exe" Configuration="Debug" Class="ProjectOutput">
|
<DeployFile LocalName="D:\CORSI\ITDEVCON9 Testing Delphi With Python\samples\SUT\bin\activerecord_crud.exe" Configuration="Debug" Class="ProjectOutput">
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<RemoteName>activerecord_crud.exe</RemoteName>
|
<RemoteName>activerecord_crud.exe</RemoteName>
|
||||||
<Overwrite>true</Overwrite>
|
<Overwrite>true</Overwrite>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ProjectGuid>{F8576ED6-649F-4E28-B364-1F60687C75F2}</ProjectGuid>
|
<ProjectGuid>{F8576ED6-649F-4E28-B364-1F60687C75F2}</ProjectGuid>
|
||||||
<ProjectVersion>18.4</ProjectVersion>
|
<ProjectVersion>18.5</ProjectVersion>
|
||||||
<FrameworkType>VCL</FrameworkType>
|
<FrameworkType>VCL</FrameworkType>
|
||||||
<MainSource>activerecord_showcase.dpr</MainSource>
|
<MainSource>activerecord_showcase.dpr</MainSource>
|
||||||
<Base>True</Base>
|
<Base>True</Base>
|
||||||
@ -84,9 +84,9 @@
|
|||||||
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
|
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
|
||||||
<DCC_RemoteDebug>false</DCC_RemoteDebug>
|
<DCC_RemoteDebug>false</DCC_RemoteDebug>
|
||||||
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
|
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
|
||||||
<AppEnableHighDPI>true</AppEnableHighDPI>
|
|
||||||
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
|
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
|
||||||
<VerInfo_Locale>1033</VerInfo_Locale>
|
<VerInfo_Locale>1033</VerInfo_Locale>
|
||||||
|
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
<PropertyGroup Condition="'$(Cfg_2)'!=''">
|
||||||
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
|
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
|
||||||
@ -96,7 +96,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
|
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
|
||||||
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
|
<AppEnableRuntimeThemes>true</AppEnableRuntimeThemes>
|
||||||
<AppEnableHighDPI>true</AppEnableHighDPI>
|
<AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<DelphiCompile Include="$(MainSource)">
|
<DelphiCompile Include="$(MainSource)">
|
||||||
@ -156,7 +156,6 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<RemoteDir>Contents\MacOS</RemoteDir>
|
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
@ -166,6 +165,12 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidFileProvider">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\xml</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
<DeployClass Name="AndroidGDBServer">
|
<DeployClass Name="AndroidGDBServer">
|
||||||
<Platform Name="Android">
|
<Platform Name="Android">
|
||||||
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
|
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
|
||||||
@ -202,6 +207,12 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
|
<DeployClass Name="AndroidSplashStylesV21">
|
||||||
|
<Platform Name="Android">
|
||||||
|
<RemoteDir>res\values-v21</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
<DeployClass Name="Android_DefaultAppIcon">
|
<DeployClass Name="Android_DefaultAppIcon">
|
||||||
<Platform Name="Android">
|
<Platform Name="Android">
|
||||||
<RemoteDir>res\drawable</RemoteDir>
|
<RemoteDir>res\drawable</RemoteDir>
|
||||||
@ -280,6 +291,11 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
<Extensions>.framework</Extensions>
|
<Extensions>.framework</Extensions>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>Contents\MacOS</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.framework</Extensions>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
@ -302,6 +318,11 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
<Extensions>.dylib</Extensions>
|
<Extensions>.dylib</Extensions>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>Contents\MacOS</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
<Extensions>.dll;.bpl</Extensions>
|
<Extensions>.dll;.bpl</Extensions>
|
||||||
@ -325,6 +346,11 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
<Extensions>.dylib</Extensions>
|
<Extensions>.dylib</Extensions>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>Contents\MacOS</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
<Extensions>.dylib</Extensions>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
<Extensions>.bpl</Extensions>
|
<Extensions>.bpl</Extensions>
|
||||||
@ -347,6 +373,10 @@
|
|||||||
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
|
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
|
||||||
|
<Operation>0</Operation>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
@ -483,23 +513,41 @@
|
|||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
|
<DeployClass Name="ProjectOSXDebug">
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
|
</DeployClass>
|
||||||
<DeployClass Name="ProjectOSXEntitlements">
|
<DeployClass Name="ProjectOSXEntitlements">
|
||||||
<Platform Name="OSX32">
|
<Platform Name="OSX32">
|
||||||
<RemoteDir>..\</RemoteDir>
|
<RemoteDir>..\</RemoteDir>
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>..\</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
<DeployClass Name="ProjectOSXInfoPList">
|
<DeployClass Name="ProjectOSXInfoPList">
|
||||||
<Platform Name="OSX32">
|
<Platform Name="OSX32">
|
||||||
<RemoteDir>Contents</RemoteDir>
|
<RemoteDir>Contents</RemoteDir>
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>Contents</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
<DeployClass Name="ProjectOSXResource">
|
<DeployClass Name="ProjectOSXResource">
|
||||||
<Platform Name="OSX32">
|
<Platform Name="OSX32">
|
||||||
<RemoteDir>Contents\Resources</RemoteDir>
|
<RemoteDir>Contents\Resources</RemoteDir>
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>Contents\Resources</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
</DeployClass>
|
</DeployClass>
|
||||||
<DeployClass Required="true" Name="ProjectOutput">
|
<DeployClass Required="true" Name="ProjectOutput">
|
||||||
<Platform Name="Android">
|
<Platform Name="Android">
|
||||||
@ -522,6 +570,10 @@
|
|||||||
<RemoteDir>Contents\MacOS</RemoteDir>
|
<RemoteDir>Contents\MacOS</RemoteDir>
|
||||||
<Operation>1</Operation>
|
<Operation>1</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
|
<Platform Name="OSX64">
|
||||||
|
<RemoteDir>Contents\MacOS</RemoteDir>
|
||||||
|
<Operation>1</Operation>
|
||||||
|
</Platform>
|
||||||
<Platform Name="Win32">
|
<Platform Name="Win32">
|
||||||
<Operation>0</Operation>
|
<Operation>0</Operation>
|
||||||
</Platform>
|
</Platform>
|
||||||
@ -561,6 +613,7 @@
|
|||||||
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
|
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
|
||||||
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
|
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
|
||||||
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
|
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
|
||||||
|
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
|
||||||
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
|
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>
|
||||||
</Deployment>
|
</Deployment>
|
||||||
<Platforms>
|
<Platforms>
|
||||||
|
@ -26,8 +26,6 @@ unit MVCFramework.ActiveRecord;
|
|||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uses
|
uses
|
||||||
System.Generics.Defaults,
|
System.Generics.Defaults,
|
||||||
System.Generics.Collections,
|
System.Generics.Collections,
|
||||||
@ -113,7 +111,6 @@ type
|
|||||||
constructor Create; virtual;
|
constructor Create; virtual;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
TMVCActiveRecord = class
|
TMVCActiveRecord = class
|
||||||
private
|
private
|
||||||
fConn: TFDConnection;
|
fConn: TFDConnection;
|
||||||
@ -221,8 +218,8 @@ type
|
|||||||
function GetPK: TValue;
|
function GetPK: TValue;
|
||||||
class function GetByPK<T: TMVCActiveRecord, constructor>(const aValue: int64): T; overload;
|
class function GetByPK<T: TMVCActiveRecord, constructor>(const aValue: int64): T; overload;
|
||||||
class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: int64): TMVCActiveRecord; overload;
|
class function GetByPK(const aClass: TMVCActiveRecordClass; const aValue: int64): TMVCActiveRecord; overload;
|
||||||
class function Select<T: TMVCActiveRecord, constructor>(const SQL: string; const Params: array of Variant; const Options: TMVCActiveRecordLoadOptions = [])
|
class function Select<T: TMVCActiveRecord, constructor>(const SQL: string; const Params: array of Variant;
|
||||||
: TObjectList<T>; overload;
|
const Options: TMVCActiveRecordLoadOptions = []): TObjectList<T>; overload;
|
||||||
class function Select(const aClass: TMVCActiveRecordClass; const SQL: string; const Params: array of Variant)
|
class function Select(const aClass: TMVCActiveRecordClass; const SQL: string; const Params: array of Variant)
|
||||||
: TMVCActiveRecordList; overload;
|
: TMVCActiveRecordList; overload;
|
||||||
class function Select(const aClass: TMVCActiveRecordClass; const SQL: string; const Params: array of Variant;
|
class function Select(const aClass: TMVCActiveRecordClass; const SQL: string; const Params: array of Variant;
|
||||||
@ -970,6 +967,10 @@ begin
|
|||||||
begin
|
begin
|
||||||
aRTTIField.SetValue(Self, aField.AsLongWord);
|
aRTTIField.SetValue(Self, aField.AsLongWord);
|
||||||
end;
|
end;
|
||||||
|
ftFMTBcd:
|
||||||
|
begin
|
||||||
|
aRTTIField.SetValue(Self, BCDtoCurrency(aField.AsBCD));
|
||||||
|
end;
|
||||||
ftDate:
|
ftDate:
|
||||||
begin
|
begin
|
||||||
aRTTIField.SetValue(Self, Trunc(aField.AsDateTime));
|
aRTTIField.SetValue(Self, Trunc(aField.AsDateTime));
|
||||||
@ -1267,7 +1268,8 @@ begin
|
|||||||
if TMVCActiveRecordLoadOption.loIgnoreNotExistentFields in aOptions then
|
if TMVCActiveRecordLoadOption.loIgnoreNotExistentFields in aOptions then
|
||||||
continue
|
continue
|
||||||
else
|
else
|
||||||
raise EMVCActiveRecord.CreateFmt('Field [%s] not found in dataset. [HINT] If you dont need it, use loIgnoreNotExistentFields', [lItem.Value]);
|
raise EMVCActiveRecord.CreateFmt
|
||||||
|
('Field [%s] not found in dataset. [HINT] If you dont need it, use loIgnoreNotExistentFields', [lItem.value]);
|
||||||
end;
|
end;
|
||||||
MapColumnToTValue(lItem.value, lField, lItem.Key);
|
MapColumnToTValue(lItem.value, lField, lItem.Key);
|
||||||
end;
|
end;
|
||||||
@ -1387,7 +1389,8 @@ begin
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TMVCActiveRecord.Select<T>(const SQL: string; const Params: array of Variant; const Options: TMVCActiveRecordLoadOptions): TObjectList<T>;
|
class function TMVCActiveRecord.Select<T>(const SQL: string; const Params: array of Variant;
|
||||||
|
const Options: TMVCActiveRecordLoadOptions): TObjectList<T>;
|
||||||
var
|
var
|
||||||
lDataSet: TDataSet;
|
lDataSet: TDataSet;
|
||||||
lAR: TMVCActiveRecord;
|
lAR: TMVCActiveRecord;
|
||||||
@ -1546,13 +1549,13 @@ var
|
|||||||
begin
|
begin
|
||||||
lAR := T.Create;
|
lAR := T.Create;
|
||||||
try
|
try
|
||||||
if not SQLWhere.Trim.IsEmpty then
|
if SQLWhere.Trim.IsEmpty() or SQLWhere.Trim.StartsWith('/*limit*/') or SQLWhere.Trim.StartsWith('/*sort*/') then
|
||||||
begin
|
begin
|
||||||
Result := Select<T>(lAR.GenerateSelectSQL + ' WHERE ' + SQLWhere, Params);
|
Result := Select<T>(lAR.GenerateSelectSQL + SQLWhere, Params);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
Result := Select<T>(lAR.GenerateSelectSQL, Params);
|
Result := Select<T>(lAR.GenerateSelectSQL + ' WHERE ' + SQLWhere, Params);
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
lAR.Free;
|
lAR.Free;
|
||||||
|
@ -108,6 +108,9 @@ type
|
|||||||
SSE_RETRY_DEFAULT = 100;
|
SSE_RETRY_DEFAULT = 100;
|
||||||
SSE_LAST_EVENT_ID = 'Last-Event-ID';
|
SSE_LAST_EVENT_ID = 'Last-Event-ID';
|
||||||
URL_MAPPED_PARAMS_ALLOWED_CHARS = ' àèéùòì@\[\]\{\}\(\)\=;&#\.\_\,%\w\d\x2D\x3A';
|
URL_MAPPED_PARAMS_ALLOWED_CHARS = ' àèéùòì@\[\]\{\}\(\)\=;&#\.\_\,%\w\d\x2D\x3A';
|
||||||
|
OneMiB = 1048576;
|
||||||
|
OneKiB = 1024;
|
||||||
|
DEFAULT_MAX_REQUEST_SIZE = OneMiB * 5; //5 MiB
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TMVCConfigKey = record
|
TMVCConfigKey = record
|
||||||
@ -127,6 +130,7 @@ type
|
|||||||
SessionType = 'session_type';
|
SessionType = 'session_type';
|
||||||
FallbackResource = 'fallback_resource';
|
FallbackResource = 'fallback_resource';
|
||||||
MaxEntitiesRecordCount = 'max_entities_record_count';
|
MaxEntitiesRecordCount = 'max_entities_record_count';
|
||||||
|
MaxRequestSize = 'max_request_size'; //bytes
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||||
|
@ -57,7 +57,7 @@ type
|
|||||||
AFieldNamePolicy: TFieldNamePolicy = TFieldNamePolicy.fpLowerCase); overload;
|
AFieldNamePolicy: TFieldNamePolicy = TFieldNamePolicy.fpLowerCase); overload;
|
||||||
procedure LoadFromJSONArrayString(AJSONArrayString: string;
|
procedure LoadFromJSONArrayString(AJSONArrayString: string;
|
||||||
AFieldNamePolicy: TFieldNamePolicy = TFieldNamePolicy.fpLowerCase); overload;
|
AFieldNamePolicy: TFieldNamePolicy = TFieldNamePolicy.fpLowerCase); overload;
|
||||||
procedure LoadFromJSONArray(AJSONArray: TJSONArray; AIgnoredFields: TArray<string>;
|
procedure LoadFromJSONArray(AJSONArray: TJSONArray;
|
||||||
AFieldNamePolicy: TFieldNamePolicy = TFieldNamePolicy.fpLowerCase); overload;
|
AFieldNamePolicy: TFieldNamePolicy = TFieldNamePolicy.fpLowerCase); overload;
|
||||||
procedure LoadFromJSONObjectString(AJSONObjectString: string); overload;
|
procedure LoadFromJSONObjectString(AJSONObjectString: string); overload;
|
||||||
procedure LoadFromJSONObjectString(AJSONObjectString: string; AIgnoredFields: TArray<string>); overload;
|
procedure LoadFromJSONObjectString(AJSONObjectString: string; AIgnoredFields: TArray<string>); overload;
|
||||||
@ -196,23 +196,33 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDataSetHelper.LoadFromJSONArray(AJSONArray: TJSONArray; AIgnoredFields: TArray<string>;
|
|
||||||
AFieldNamePolicy: TFieldNamePolicy);
|
|
||||||
begin
|
|
||||||
Self.DisableControls;
|
|
||||||
try
|
|
||||||
raise Exception.Create('Not Implemented');
|
|
||||||
finally
|
|
||||||
Self.EnableControls;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TDataSetHelper.LoadFromJSONArrayString(AJSONArrayString: string; AIgnoredFields: TArray<string>;
|
procedure TDataSetHelper.LoadFromJSONArrayString(AJSONArrayString: string; AIgnoredFields: TArray<string>;
|
||||||
AFieldNamePolicy: TFieldNamePolicy);
|
AFieldNamePolicy: TFieldNamePolicy);
|
||||||
begin
|
begin
|
||||||
AppendFromJSONArrayString(AJSONArrayString, AIgnoredFields, AFieldNamePolicy);
|
AppendFromJSONArrayString(AJSONArrayString, AIgnoredFields, AFieldNamePolicy);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TDataSetHelper.LoadFromJSONArray(AJSONArray: TJSONArray; AFieldNamePolicy: TFieldNamePolicy);
|
||||||
|
var
|
||||||
|
lSerializer: TMVCJsonDataObjectsSerializer;
|
||||||
|
lBookmark: TArray<Byte>;
|
||||||
|
begin
|
||||||
|
lBookmark := Self.Bookmark;
|
||||||
|
Self.DisableControls;
|
||||||
|
try
|
||||||
|
lSerializer := TMVCJsonDataObjectsSerializer.Create;
|
||||||
|
try
|
||||||
|
lSerializer.JsonArrayToDataSet(AJSONArray, Self, nil, ncAsIs);
|
||||||
|
finally
|
||||||
|
lSerializer.Free;
|
||||||
|
end;
|
||||||
|
if Self.BookmarkValid(lBookmark) then
|
||||||
|
Self.GotoBookmark(lBookmark);
|
||||||
|
finally
|
||||||
|
Self.EnableControls;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TDataSetHelper.LoadFromJSONArrayString(AJSONArrayString: string; AFieldNamePolicy: TFieldNamePolicy);
|
procedure TDataSetHelper.LoadFromJSONArrayString(AJSONArrayString: string; AFieldNamePolicy: TFieldNamePolicy);
|
||||||
begin
|
begin
|
||||||
AppendFromJSONArrayString(AJSONArrayString, TArray<string>.Create(), AFieldNamePolicy);
|
AppendFromJSONArrayString(AJSONArrayString, TArray<string>.Create(), AFieldNamePolicy);
|
||||||
@ -243,17 +253,6 @@ var
|
|||||||
begin
|
begin
|
||||||
lSerializer := TMVCJsonDataObjectsSerializer.Create;
|
lSerializer := TMVCJsonDataObjectsSerializer.Create;
|
||||||
lSerializer.DeserializeDataSetRecord(AJSONObjectString, Self, nil, ncAsIs);
|
lSerializer.DeserializeDataSetRecord(AJSONObjectString, Self, nil, ncAsIs);
|
||||||
|
|
||||||
// JV := TJSONObject.ParseJSONValue(AJSONObjectString);
|
|
||||||
// try
|
|
||||||
// if JV is TJSONObject then
|
|
||||||
// LoadFromJSONObject(TJSONObject(JV), AIgnoredFields)
|
|
||||||
// else
|
|
||||||
// raise EMapperException.Create
|
|
||||||
// ('Extected JSONObject in LoadFromJSONObjectString');
|
|
||||||
// finally
|
|
||||||
// JV.Free;
|
|
||||||
// end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDataSetHelper.LoadFromJSONObject(AJSONObject: TJSONObject; AFieldNamePolicy: TFieldNamePolicy);
|
procedure TDataSetHelper.LoadFromJSONObject(AJSONObject: TJSONObject; AFieldNamePolicy: TFieldNamePolicy);
|
||||||
@ -409,4 +408,3 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ uses
|
|||||||
type
|
type
|
||||||
IMVCJSONRPCExecutor = interface
|
IMVCJSONRPCExecutor = interface
|
||||||
['{55415094-9D28-4707-AEC5-5FCF925E82BC}']
|
['{55415094-9D28-4707-AEC5-5FCF925E82BC}']
|
||||||
function ExecuteRequest(const aJSONRPCRequest: TJSONRPCRequest): TJSONRPCResponse;
|
function ExecuteRequest(const aJSONRPCRequest: IJSONRPCRequest): IJSONRPCResponse;
|
||||||
procedure ExecuteNotification(const aJSONRPCNotification: TJSONRPCNotification);
|
procedure ExecuteNotification(const aJSONRPCNotification: IJSONRPCNotification);
|
||||||
// Http headers handling
|
// Http headers handling
|
||||||
procedure AddHTTPHeader(const aNetHeader: TNetHeader);
|
procedure AddHTTPHeader(const aNetHeader: TNetHeader);
|
||||||
procedure ClearHTTPHeaders;
|
procedure ClearHTTPHeaders;
|
||||||
@ -51,12 +51,12 @@ type
|
|||||||
FHTTPRequestHeaders: TList<TNetHeader>;
|
FHTTPRequestHeaders: TList<TNetHeader>;
|
||||||
function GetHTTPRequestHeaders: TList<TNetHeader>;
|
function GetHTTPRequestHeaders: TList<TNetHeader>;
|
||||||
protected
|
protected
|
||||||
function InternalExecute(const aJSONRPCObject: TJSONRPCObject): TJSONRPCResponse;
|
function InternalExecute(const aJSONRPCObject: IJSONRPCObject): IJSONRPCResponse;
|
||||||
public
|
public
|
||||||
constructor Create(const aURL: string; const aRaiseExceptionOnError: Boolean = True); virtual;
|
constructor Create(const aURL: string; const aRaiseExceptionOnError: Boolean = True); virtual;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function ExecuteRequest(const aJSONRPCRequest: TJSONRPCRequest): TJSONRPCResponse;
|
function ExecuteRequest(const aJSONRPCRequest: IJSONRPCRequest): IJSONRPCResponse;
|
||||||
procedure ExecuteNotification(const aJSONRPCNotification: TJSONRPCNotification);
|
procedure ExecuteNotification(const aJSONRPCNotification: IJSONRPCNotification);
|
||||||
// Http headers handling
|
// Http headers handling
|
||||||
procedure AddHTTPHeader(const aNetHeader: TNetHeader);
|
procedure AddHTTPHeader(const aNetHeader: TNetHeader);
|
||||||
procedure ClearHTTPHeaders;
|
procedure ClearHTTPHeaders;
|
||||||
@ -69,7 +69,7 @@ uses
|
|||||||
System.Classes,
|
System.Classes,
|
||||||
System.SysUtils;
|
System.SysUtils;
|
||||||
|
|
||||||
procedure JSONRPCExec(const aJSONRPCURL: string; const aJSONRPCRequest: TJSONRPCRequest; out aJSONRPCResponse: TJSONRPCResponse);
|
procedure JSONRPCExec(const aJSONRPCURL: string; const aJSONRPCRequest: IJSONRPCRequest; out aJSONRPCResponse: IJSONRPCResponse);
|
||||||
var
|
var
|
||||||
lSS: TStringStream;
|
lSS: TStringStream;
|
||||||
lHttpResp: IHTTPResponse;
|
lHttpResp: IHTTPResponse;
|
||||||
@ -85,14 +85,9 @@ begin
|
|||||||
if (lHttpResp.StatusCode <> 204) then
|
if (lHttpResp.StatusCode <> 204) then
|
||||||
begin
|
begin
|
||||||
aJSONRPCResponse := TJSONRPCResponse.Create;
|
aJSONRPCResponse := TJSONRPCResponse.Create;
|
||||||
try
|
aJSONRPCResponse.AsJSONString := lHttpResp.ContentAsString;
|
||||||
aJSONRPCResponse.AsJSONString := lHttpResp.ContentAsString;
|
if Assigned(aJSONRPCResponse.Error) then
|
||||||
if Assigned(aJSONRPCResponse.Error) then
|
raise Exception.CreateFmt('Error [%d]: %s', [aJSONRPCResponse.Error.Code, aJSONRPCResponse.Error.ErrMessage]);
|
||||||
raise Exception.CreateFmt('Error [%d]: %s', [aJSONRPCResponse.Error.Code, aJSONRPCResponse.Error.ErrMessage]);
|
|
||||||
except
|
|
||||||
aJSONRPCResponse.Free;
|
|
||||||
raise;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
lHTTP.Free;
|
lHTTP.Free;
|
||||||
@ -133,13 +128,13 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMVCJSONRPCExecutor.ExecuteNotification(const aJSONRPCNotification: TJSONRPCNotification);
|
procedure TMVCJSONRPCExecutor.ExecuteNotification(const aJSONRPCNotification: IJSONRPCNotification);
|
||||||
begin
|
begin
|
||||||
if InternalExecute(aJSONRPCNotification as TJSONRPCObject) <> nil then
|
if InternalExecute(aJSONRPCNotification as TJSONRPCObject) <> nil then
|
||||||
raise EMVCJSONRPCException.Create('A "notification" cannot returns a response. Use ExecuteRequest instead.');
|
raise EMVCJSONRPCException.Create('A "notification" cannot returns a response. Use ExecuteRequest instead.');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCJSONRPCExecutor.ExecuteRequest(const aJSONRPCRequest: TJSONRPCRequest): TJSONRPCResponse;
|
function TMVCJSONRPCExecutor.ExecuteRequest(const aJSONRPCRequest: IJSONRPCRequest): IJSONRPCResponse;
|
||||||
begin
|
begin
|
||||||
Result := InternalExecute(aJSONRPCRequest);
|
Result := InternalExecute(aJSONRPCRequest);
|
||||||
end;
|
end;
|
||||||
@ -165,11 +160,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCJSONRPCExecutor.InternalExecute(const aJSONRPCObject: TJSONRPCObject): TJSONRPCResponse;
|
function TMVCJSONRPCExecutor.InternalExecute(const aJSONRPCObject: IJSONRPCObject): IJSONRPCResponse;
|
||||||
var
|
var
|
||||||
lSS: TStringStream;
|
lSS: TStringStream;
|
||||||
lHttpResp: IHTTPResponse;
|
lHttpResp: IHTTPResponse;
|
||||||
lJSONRPCResponse: TJSONRPCResponse;
|
lJSONRPCResponse: IJSONRPCResponse;
|
||||||
lCustomHeaders: TNetHeaders;
|
lCustomHeaders: TNetHeaders;
|
||||||
begin
|
begin
|
||||||
lCustomHeaders := [];
|
lCustomHeaders := [];
|
||||||
@ -187,15 +182,10 @@ begin
|
|||||||
if (lHttpResp.StatusCode <> HTTP_STATUS.NoContent) then
|
if (lHttpResp.StatusCode <> HTTP_STATUS.NoContent) then
|
||||||
begin
|
begin
|
||||||
lJSONRPCResponse := TJSONRPCResponse.Create;
|
lJSONRPCResponse := TJSONRPCResponse.Create;
|
||||||
try
|
lJSONRPCResponse.AsJSONString := lHttpResp.ContentAsString;
|
||||||
lJSONRPCResponse.AsJSONString := lHttpResp.ContentAsString;
|
if Assigned(lJSONRPCResponse.Error) and FRaiseExceptionOnError then
|
||||||
if Assigned(lJSONRPCResponse.Error) and FRaiseExceptionOnError then
|
raise Exception.CreateFmt('Error [%d]: %s', [lJSONRPCResponse.Error.Code, lJSONRPCResponse.Error.ErrMessage]);
|
||||||
raise Exception.CreateFmt('Error [%d]: %s', [lJSONRPCResponse.Error.Code, lJSONRPCResponse.Error.ErrMessage]);
|
Result := lJSONRPCResponse;
|
||||||
Result := lJSONRPCResponse;
|
|
||||||
except
|
|
||||||
lJSONRPCResponse.Free;
|
|
||||||
raise;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
lSS.Free;
|
lSS.Free;
|
||||||
|
@ -72,85 +72,139 @@ type
|
|||||||
procedure Build(const aJSON: TJsonObject); virtual; abstract;
|
procedure Build(const aJSON: TJsonObject); virtual; abstract;
|
||||||
{ IMVCJSONRPCMessage }
|
{ IMVCJSONRPCMessage }
|
||||||
function AsJSONRPCMessage: string;
|
function AsJSONRPCMessage: string;
|
||||||
public
|
|
||||||
function AsJSON: TJsonObject; virtual;
|
function AsJSON: TJsonObject; virtual;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TJSONRPCObject = class(TObject)
|
IJSONRPCObject = interface
|
||||||
|
['{98E161EE-B106-4023-8722-3C2CB1B4CE87}']
|
||||||
|
procedure SetJsonString(const Value: string);
|
||||||
|
function GetJSONString: string;
|
||||||
|
function GetJSON: TJsonObject;
|
||||||
|
procedure SetJSON(const Value: TJsonObject);
|
||||||
|
property AsJSON: TJsonObject read GetJSON write SetJSON;
|
||||||
|
property AsJSONString: string read GetJSONString write SetJsonString;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TJSONRPCObject = class(TInterfacedObject, IJSONRPCObject)
|
||||||
protected
|
protected
|
||||||
procedure SetJsonString(const Value: string); virtual;
|
procedure SetJsonString(const Value: string); virtual;
|
||||||
function GetJSONString: string; virtual;
|
function GetJSONString: string; virtual;
|
||||||
function GetJSON: TJsonObject; virtual;
|
function GetJSON: TJsonObject; virtual;
|
||||||
procedure SetJSON(const Value: TJsonObject); virtual;
|
procedure SetJSON(const Value: TJsonObject); virtual;
|
||||||
public
|
|
||||||
constructor Create; virtual;
|
|
||||||
property AsJSON: TJsonObject read GetJSON write SetJSON;
|
property AsJSON: TJsonObject read GetJSON write SetJSON;
|
||||||
property AsJSONString: string read GetJSONString write SetJsonString;
|
property AsJSONString: string read GetJSONString write SetJsonString;
|
||||||
|
public
|
||||||
|
constructor Create; virtual;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TJSONRPCNotification = class(TJSONRPCObject)
|
TJSONRPCRequestParams = TList<TValue>;
|
||||||
protected type
|
|
||||||
TJSONRPCRequestParams = TList<TValue>;
|
IJSONRPCNotification = interface(IJSONRPCObject)
|
||||||
|
['{FAA65A29-3305-4303-833E-825BDBD3FF7F}']
|
||||||
|
procedure SetMethod(const Value: string);
|
||||||
|
function GetMethod: string;
|
||||||
|
function GetParams: TJSONRPCRequestParams;
|
||||||
|
property Method: string read GetMethod write SetMethod;
|
||||||
|
property Params: TJSONRPCRequestParams read GetParams;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TJSONRPCNotification = class(TJSONRPCObject, IJSONRPCObject, IJSONRPCNotification)
|
||||||
protected
|
protected
|
||||||
FMethod: string;
|
FMethod: string;
|
||||||
FParams: TJSONRPCRequestParams;
|
FParams: TJSONRPCRequestParams;
|
||||||
procedure SetMethod(const Value: string);
|
procedure SetMethod(const Value: string);
|
||||||
protected
|
function GetMethod: string;
|
||||||
|
function GetParams: TJSONRPCRequestParams;
|
||||||
function GetJSON: TJsonObject; override;
|
function GetJSON: TJsonObject; override;
|
||||||
|
property Method: string read GetMethod write SetMethod;
|
||||||
|
property Params: TJSONRPCRequestParams read GetParams;
|
||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; overload; override;
|
||||||
|
constructor Create(const aMethod: String); reintroduce; overload;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
property Method: string read FMethod write SetMethod;
|
|
||||||
property Params: TJSONRPCRequestParams read FParams;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$SCOPEDENUMS ON}
|
{$SCOPEDENUMS ON}
|
||||||
|
|
||||||
TJSONRPCRequestType = (Request, Notification);
|
TJSONRPCRequestType = (Request, Notification);
|
||||||
|
|
||||||
TJSONRPCRequest = class(TJSONRPCNotification)
|
IJSONRPCRequest = interface(IJSONRPCNotification)
|
||||||
|
['{D8318032-0261-4273-B99D-121899AD52FB}']
|
||||||
|
function GetRequestType: TJSONRPCRequestType;
|
||||||
|
function GetID: TValue;
|
||||||
|
procedure SetID(const Value: TValue);
|
||||||
|
property RequestType: TJSONRPCRequestType read GetRequestType;
|
||||||
|
property RequestID: TValue read GetID write SetID;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TJSONRPCRequest = class(TJSONRPCNotification, IJSONRPCRequest)
|
||||||
private
|
private
|
||||||
FID: TValue;
|
FID: TValue;
|
||||||
function GetRequestType: TJSONRPCRequestType;
|
function GetRequestType: TJSONRPCRequestType;
|
||||||
|
function GetID: TValue;
|
||||||
protected
|
protected
|
||||||
procedure SetJSON(const JSON: TJsonObject); override;
|
procedure SetJSON(const JSON: TJsonObject); override;
|
||||||
function GetJSON: TJsonObject; override;
|
function GetJSON: TJsonObject; override;
|
||||||
procedure SetID(const Value: TValue);
|
procedure SetID(const Value: TValue);
|
||||||
public
|
|
||||||
constructor Create; override;
|
|
||||||
destructor Destroy; override;
|
|
||||||
property RequestType: TJSONRPCRequestType read GetRequestType;
|
property RequestType: TJSONRPCRequestType read GetRequestType;
|
||||||
property RequestID: TValue read FID write SetID;
|
property RequestID: TValue read GetID write SetID;
|
||||||
|
public
|
||||||
|
constructor Create(const aID: TValue; const aMethod: String); overload; virtual;
|
||||||
|
constructor Create(const aID: TValue); overload; virtual;
|
||||||
|
constructor Create; reintroduce; overload; virtual;
|
||||||
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TJSONRPCResponse = class(TJSONRPCObject)
|
TJSONRPCResponseError = class
|
||||||
private type
|
private
|
||||||
TJSONRPCResponseError = class
|
FCode: Integer;
|
||||||
private
|
FMessage: string;
|
||||||
FCode: Integer;
|
procedure SetCode(const Value: Integer);
|
||||||
FMessage: string;
|
procedure SetMessage(const Value: string);
|
||||||
procedure SetCode(const Value: Integer);
|
public
|
||||||
procedure SetMessage(const Value: string);
|
property Code: Integer read FCode write SetCode;
|
||||||
public
|
property ErrMessage: string read FMessage write SetMessage;
|
||||||
property Code: Integer read FCode write SetCode;
|
end;
|
||||||
property ErrMessage: string read FMessage write SetMessage;
|
|
||||||
end;
|
IJSONRPCResponse = interface(IJSONRPCObject)
|
||||||
|
['{69B43409-14DC-4A36-9E12-425A1626FF3C}']
|
||||||
|
function GetID: TValue;
|
||||||
|
procedure SetID(const Value: TValue);
|
||||||
|
function GetResult: TValue;
|
||||||
|
procedure SetResult(const Value: TValue);
|
||||||
|
function GetError: TJSONRPCResponseError;
|
||||||
|
procedure SetError(const Value: TJSONRPCResponseError);
|
||||||
|
function IsError: Boolean;
|
||||||
|
function ResultAsJSONObject: TJsonObject;
|
||||||
|
function ResultAsJSONArray: TJsonArray;
|
||||||
|
property Result: TValue read GetResult write SetResult;
|
||||||
|
property Error: TJSONRPCResponseError read GetError write SetError;
|
||||||
|
property RequestID: TValue read GetID write SetID;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TJSONRPCResponse = class(TJSONRPCObject, IJSONRPCResponse)
|
||||||
private
|
private
|
||||||
FResult: TValue;
|
FResult: TValue;
|
||||||
FError: TJSONRPCResponseError;
|
FError: TJSONRPCResponseError;
|
||||||
FID: TValue;
|
FID: TValue;
|
||||||
procedure SetID(const Value: TValue);
|
function GetResult: TValue;
|
||||||
procedure SetResult(const Value: TValue);
|
|
||||||
procedure SetError(const Value: TJSONRPCResponseError);
|
|
||||||
protected
|
protected
|
||||||
function GetJSON: TJsonObject; override;
|
function GetJSON: TJsonObject; override;
|
||||||
procedure SetJSON(const JSON: TJsonObject); override;
|
procedure SetJSON(const JSON: TJsonObject); override;
|
||||||
|
procedure SetID(const Value: TValue);
|
||||||
|
procedure SetResult(const Value: TValue);
|
||||||
|
procedure SetError(const Value: TJSONRPCResponseError);
|
||||||
|
function GetError: TJSONRPCResponseError;
|
||||||
|
function GetID: TValue;
|
||||||
|
function ResultAsJSONObject: TJsonObject;
|
||||||
|
function ResultAsJSONArray: TJsonArray;
|
||||||
|
function IsError: Boolean;
|
||||||
|
property Result: TValue read GetResult write SetResult;
|
||||||
|
property Error: TJSONRPCResponseError read GetError write SetError;
|
||||||
|
property RequestID: TValue read GetID write SetID;
|
||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
property Result: TValue read FResult write SetResult;
|
|
||||||
property Error: TJSONRPCResponseError read FError write SetError;
|
|
||||||
property RequestID: TValue read FID write SetID;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
EMVCJSONRPCInvalidVersion = class(Exception)
|
EMVCJSONRPCInvalidVersion = class(Exception)
|
||||||
@ -220,6 +274,11 @@ type
|
|||||||
[MVCConsumes(TMVCMediaType.APPLICATION_JSON)]
|
[MVCConsumes(TMVCMediaType.APPLICATION_JSON)]
|
||||||
[MVCProduces(TMVCMediaType.APPLICATION_JSON)]
|
[MVCProduces(TMVCMediaType.APPLICATION_JSON)]
|
||||||
procedure Index; virtual;
|
procedure Index; virtual;
|
||||||
|
|
||||||
|
[MVCPath]
|
||||||
|
[MVCHTTPMethods([httpGET])]
|
||||||
|
[MVCProduces(TMVCMediaType.TEXT_PLAIN)]
|
||||||
|
procedure GetProxyCode; virtual;
|
||||||
constructor Create; overload; override;
|
constructor Create; overload; override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
end;
|
end;
|
||||||
@ -229,15 +288,31 @@ type
|
|||||||
constructor Create(const RPCInstance: TObject; const Owns: Boolean = True); reintroduce; overload;
|
constructor Create(const RPCInstance: TObject; const Owns: Boolean = True); reintroduce; overload;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TJSONRPCProxyGenerator = class abstract
|
||||||
|
public
|
||||||
|
constructor Create; virtual;
|
||||||
|
procedure StartGeneration; virtual;
|
||||||
|
procedure EndGeneration; virtual;
|
||||||
|
procedure VisitMethod(const aRTTIMethod: TRttiMethod); virtual; abstract;
|
||||||
|
function GetCode: String; virtual; abstract;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TJSONRPCProxyGeneratorClass = class of TJSONRPCProxyGenerator;
|
||||||
|
|
||||||
|
procedure RegisterJSONRPCProxyGenerator(const aLanguage: String; const aClass: TJSONRPCProxyGeneratorClass);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
MVCFramework.Serializer.Intf, MVCFramework.Logger,
|
MVCFramework.Serializer.Intf, MVCFramework.Logger,
|
||||||
System.TypInfo, MVCFramework.DuckTyping,
|
System.TypInfo, MVCFramework.DuckTyping,
|
||||||
MVCFramework.Serializer.JsonDataObjects.CustomTypes;
|
MVCFramework.Serializer.jsondataobjects.CustomTypes;
|
||||||
|
|
||||||
const
|
const
|
||||||
CALL_TYPE: array[mkProcedure..mkFunction] of string = ('PROCEDURE','FUNCTION');
|
CALL_TYPE: array [mkProcedure .. mkFunction] of string = ('PROCEDURE', 'FUNCTION');
|
||||||
|
|
||||||
|
var
|
||||||
|
GProxyGeneratorsRegister: TDictionary<String, TJSONRPCProxyGeneratorClass>;
|
||||||
|
|
||||||
function JSONDataValueToTValue(const JSONDataValue: TJsonDataValueHelper): TValue;
|
function JSONDataValueToTValue(const JSONDataValue: TJsonDataValueHelper): TValue;
|
||||||
begin
|
begin
|
||||||
@ -260,6 +335,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
jdtObject:
|
jdtObject:
|
||||||
begin
|
begin
|
||||||
|
{ TODO -oDanieleT -cGeneral : Can be deserialized in a PODO? }
|
||||||
Result := TJsonObject.Parse(JSONDataValue.ObjectValue.ToJSON) as TJsonObject;
|
Result := TJsonObject.Parse(JSONDataValue.ObjectValue.ToJSON) as TJsonObject;
|
||||||
end;
|
end;
|
||||||
jdtInt:
|
jdtInt:
|
||||||
@ -343,14 +419,15 @@ begin
|
|||||||
fOwsRPCInstance := False;
|
fOwsRPCInstance := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMVCJSONRPCController.CreateError(const RequestID: TValue; const ErrorCode: Integer; const message: string): TJsonObject;
|
function TMVCJSONRPCController.CreateError(const RequestID: TValue; const ErrorCode: Integer; const message: string)
|
||||||
|
: TJsonObject;
|
||||||
var
|
var
|
||||||
lErrResp: TJSONRPCResponse;
|
lErrResp: TJSONRPCResponse;
|
||||||
begin
|
begin
|
||||||
lErrResp := TJSONRPCResponse.Create;
|
lErrResp := TJSONRPCResponse.Create;
|
||||||
try
|
try
|
||||||
lErrResp.RequestID := RequestID;
|
lErrResp.RequestID := RequestID;
|
||||||
lErrResp.Error := TJSONRPCResponse.TJSONRPCResponseError.Create;
|
lErrResp.Error := TJSONRPCResponseError.Create;
|
||||||
lErrResp.Error.Code := ErrorCode;
|
lErrResp.Error.Code := ErrorCode;
|
||||||
lErrResp.Error.ErrMessage := message;
|
lErrResp.Error.ErrMessage := message;
|
||||||
Result := lErrResp.AsJSON;
|
Result := lErrResp.AsJSON;
|
||||||
@ -363,21 +440,23 @@ function TMVCJSONRPCController.CreateRequest(const JSON: TJsonObject): TJSONRPCR
|
|||||||
var
|
var
|
||||||
I: Integer;
|
I: Integer;
|
||||||
lParams: TJsonArray;
|
lParams: TJsonArray;
|
||||||
|
lReqID: TValue;
|
||||||
|
lMethodName: String;
|
||||||
begin
|
begin
|
||||||
try
|
try
|
||||||
Result := TJSONRPCRequest.Create;
|
|
||||||
if JSON.Types[JSONRPC_ID] = jdtString then
|
if JSON.Types[JSONRPC_ID] = jdtString then
|
||||||
Result.RequestID := JSON.S[JSONRPC_ID]
|
lReqID := JSON.S[JSONRPC_ID]
|
||||||
else if JSON.Types[JSONRPC_ID] = jdtInt then
|
else if JSON.Types[JSONRPC_ID] = jdtInt then
|
||||||
Result.RequestID := JSON.I[JSONRPC_ID]
|
lReqID := JSON.I[JSONRPC_ID]
|
||||||
else if JSON.Types[JSONRPC_ID] = jdtLong then
|
else if JSON.Types[JSONRPC_ID] = jdtLong then
|
||||||
Result.RequestID := JSON.L[JSONRPC_ID]
|
lReqID := JSON.L[JSONRPC_ID]
|
||||||
else if JSON.Types[JSONRPC_ID] = jdtULong then
|
else if JSON.Types[JSONRPC_ID] = jdtULong then
|
||||||
Result.RequestID := JSON.U[JSONRPC_ID]
|
lReqID := JSON.U[JSONRPC_ID]
|
||||||
else
|
else
|
||||||
Result.RequestID := TValue.Empty;
|
lReqID := TValue.Empty;
|
||||||
|
|
||||||
Result.Method := JSON.S[JSONRPC_METHOD];
|
lMethodName := JSON.S[JSONRPC_METHOD];
|
||||||
|
Result := TJSONRPCRequest.Create(lReqID, lMethodName);
|
||||||
|
|
||||||
if JSON.Types[JSONRPC_PARAMS] = jdtArray then
|
if JSON.Types[JSONRPC_PARAMS] = jdtArray then
|
||||||
begin
|
begin
|
||||||
@ -431,6 +510,54 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMVCJSONRPCController.GetProxyCode;
|
||||||
|
var
|
||||||
|
lLanguage: string;
|
||||||
|
lClass: TJSONRPCProxyGeneratorClass;
|
||||||
|
lGenerator: TJSONRPCProxyGenerator;
|
||||||
|
lRTTI: TRTTIContext;
|
||||||
|
lRTTIType: TRttiType;
|
||||||
|
lMethod: TRttiMethod;
|
||||||
|
begin
|
||||||
|
if not Context.Request.QueryStringParamExists('language') then
|
||||||
|
begin
|
||||||
|
raise EMVCJSONRPCException.Create('Query string parameter "language" is required');
|
||||||
|
end;
|
||||||
|
|
||||||
|
lLanguage := Context.Request.Params['language'].ToLower;
|
||||||
|
|
||||||
|
if not Assigned(GProxyGeneratorsRegister) then
|
||||||
|
begin
|
||||||
|
raise EMVCJSONRPCException.Create
|
||||||
|
('No Proxy Generators have been registered. [HINT] Use RegisterJSONRPCProxyGenerator function');
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not GProxyGeneratorsRegister.TryGetValue(lLanguage, lClass) then
|
||||||
|
begin
|
||||||
|
raise EMVCJSONRPCException.CreateFmt('Unknown language [%s]', [lLanguage]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
lGenerator := lClass.Create;
|
||||||
|
try
|
||||||
|
lRTTI := TRTTIContext.Create;
|
||||||
|
try
|
||||||
|
lRTTIType := lRTTI.GetType(fRPCInstance.ClassType);
|
||||||
|
lGenerator.StartGeneration();
|
||||||
|
for lMethod in lRTTIType.GetMethods do
|
||||||
|
begin
|
||||||
|
lGenerator.VisitMethod(lMethod);
|
||||||
|
end;
|
||||||
|
lGenerator.EndGeneration();
|
||||||
|
Context.Response.ContentType := 'text/plain';
|
||||||
|
Render(lGenerator.GetCode);
|
||||||
|
finally
|
||||||
|
lRTTI.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
lGenerator.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TMVCJSONRPCController.GetSerializer: TMVCJsonDataObjectsSerializer;
|
function TMVCJSONRPCController.GetSerializer: TMVCJsonDataObjectsSerializer;
|
||||||
begin
|
begin
|
||||||
if not Assigned(fSerializer) then
|
if not Assigned(fSerializer) then
|
||||||
@ -474,20 +601,24 @@ begin
|
|||||||
lRTTIMethod := lRTTIType.GetMethod(lMethod);
|
lRTTIMethod := lRTTIType.GetMethod(lMethod);
|
||||||
if Assigned(lRTTIMethod) then
|
if Assigned(lRTTIMethod) then
|
||||||
begin
|
begin
|
||||||
if (lRTTIMethod.Visibility <> mvPublic) or (not (lRTTIMethod.MethodKind in [mkProcedure, mkFunction])) then
|
if (lRTTIMethod.Visibility <> mvPublic) or (not(lRTTIMethod.MethodKind in [mkProcedure, mkFunction])) then
|
||||||
begin
|
begin
|
||||||
LogW(Format('Method "%s" cannot be called. Only public functions or procedures can be called. ', [lMethod]));
|
LogW(Format('Method "%s" cannot be called. Only public functions or procedures can be called. ',
|
||||||
|
[lMethod]));
|
||||||
raise EMVCJSONRPCMethodNotFound.Create(lMethod);
|
raise EMVCJSONRPCMethodNotFound.Create(lMethod);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (lJSONRPCReq.RequestType = TJSONRPCRequestType.Request) and (lRTTIMethod.MethodKind <> mkFunction) then
|
if (lJSONRPCReq.RequestType = TJSONRPCRequestType.Request) and (lRTTIMethod.MethodKind <> mkFunction) then
|
||||||
begin
|
begin
|
||||||
raise EMVCJSONRPCInvalidParams.Create('Cannot call a procedure using a JSON-RPC request. [HINT] Use requests for functions and notifications for procedures');
|
raise EMVCJSONRPCInvalidParams.Create
|
||||||
|
('Cannot call a procedure using a JSON-RPC request. [HINT] Use requests for functions and notifications for procedures');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (lJSONRPCReq.RequestType = TJSONRPCRequestType.Notification) and (lRTTIMethod.MethodKind <> mkProcedure) then
|
if (lJSONRPCReq.RequestType = TJSONRPCRequestType.Notification) and (lRTTIMethod.MethodKind <> mkProcedure)
|
||||||
|
then
|
||||||
begin
|
begin
|
||||||
raise EMVCJSONRPCInvalidParams.Create('Cannot call a function using a JSON-RPC notification. [HINT] Use requests for functions and notifications for procedures');
|
raise EMVCJSONRPCInvalidParams.Create
|
||||||
|
('Cannot call a function using a JSON-RPC notification. [HINT] Use requests for functions and notifications for procedures');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
InjectParams(lJSONRPCReq, lRTTIMethod);
|
InjectParams(lJSONRPCReq, lRTTIMethod);
|
||||||
@ -524,7 +655,8 @@ begin
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
LogW(Format('Method "%s" has not be found in %s. Only public methods can be invoked.', [lMethod, fRPCInstance.QualifiedClassName]));
|
LogW(Format('Method "%s" has not be found in %s. Only public methods can be invoked.',
|
||||||
|
[lMethod, fRPCInstance.QualifiedClassName]));
|
||||||
raise EMVCJSONRPCMethodNotFound.Create(lMethod);
|
raise EMVCJSONRPCMethodNotFound.Create(lMethod);
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
@ -561,12 +693,12 @@ begin
|
|||||||
ResponseStatus(500);
|
ResponseStatus(500);
|
||||||
end;
|
end;
|
||||||
Render(CreateError(lReqID, E.JSONRPCErrorCode, E.message), True);
|
Render(CreateError(lReqID, E.JSONRPCErrorCode, E.message), True);
|
||||||
LogE(Format('[JSON-RPC][CLS %s][ERR %d][MSG "%s"]',[E.ClassName, E.JSONRPCErrorCode,E.Message]));
|
LogE(Format('[JSON-RPC][CLS %s][ERR %d][MSG "%s"]', [E.ClassName, E.JSONRPCErrorCode, E.message]));
|
||||||
end;
|
end;
|
||||||
on E: Exception do
|
on E: Exception do
|
||||||
begin
|
begin
|
||||||
Render(CreateError(lReqID, 0, E.message), True);
|
Render(CreateError(lReqID, 0, E.message), True);
|
||||||
LogE(Format('[JSON-RPC][CLS %s][MSG "%s"]',[E.ClassName, E.Message]));
|
LogE(Format('[JSON-RPC][CLS %s][MSG "%s"]', [E.ClassName, E.message]));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -586,7 +718,8 @@ end;
|
|||||||
|
|
||||||
constructor EMVCJSONRPCParseError.Create;
|
constructor EMVCJSONRPCParseError.Create;
|
||||||
begin
|
begin
|
||||||
inherited Create('Parse error. Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text');
|
inherited Create
|
||||||
|
('Parse error. Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text');
|
||||||
FJSONRPCErrorCode := -32700;
|
FJSONRPCErrorCode := -32700;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -633,6 +766,18 @@ end;
|
|||||||
|
|
||||||
{ TJSONRPCRequest }
|
{ TJSONRPCRequest }
|
||||||
|
|
||||||
|
constructor TJSONRPCRequest.Create(const aID: TValue; const aMethod: String);
|
||||||
|
begin
|
||||||
|
inherited Create(aMethod);
|
||||||
|
SetID(aID);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TJSONRPCRequest.Create(const aID: TValue);
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
SetID(aID);
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TJSONRPCRequest.Create;
|
constructor TJSONRPCRequest.Create;
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
@ -683,6 +828,12 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
constructor TJSONRPCNotification.Create(const aMethod: String);
|
||||||
|
begin
|
||||||
|
Create;
|
||||||
|
Method := aMethod;
|
||||||
|
end;
|
||||||
|
|
||||||
destructor TJSONRPCNotification.Destroy;
|
destructor TJSONRPCNotification.Destroy;
|
||||||
var
|
var
|
||||||
lValue: TValue;
|
lValue: TValue;
|
||||||
@ -713,6 +864,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TJSONRPCNotification.GetMethod: string;
|
||||||
|
begin
|
||||||
|
Result := FMethod;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJSONRPCNotification.GetParams: TJSONRPCRequestParams;
|
||||||
|
begin
|
||||||
|
Result := FParams;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TJSONRPCNotification.SetMethod(const Value: string);
|
procedure TJSONRPCNotification.SetMethod(const Value: string);
|
||||||
begin
|
begin
|
||||||
FMethod := Value;
|
FMethod := Value;
|
||||||
@ -734,6 +895,16 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TJSONRPCResponse.GetError: TJSONRPCResponseError;
|
||||||
|
begin
|
||||||
|
Result := FError;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJSONRPCResponse.GetID: TValue;
|
||||||
|
begin
|
||||||
|
Result := FID;
|
||||||
|
end;
|
||||||
|
|
||||||
function TJSONRPCResponse.GetJSON: TJsonObject;
|
function TJSONRPCResponse.GetJSON: TJsonObject;
|
||||||
begin
|
begin
|
||||||
Result := inherited;
|
Result := inherited;
|
||||||
@ -775,6 +946,26 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TJSONRPCResponse.GetResult: TValue;
|
||||||
|
begin
|
||||||
|
Result := FResult;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJSONRPCResponse.IsError: Boolean;
|
||||||
|
begin
|
||||||
|
Result := Assigned(FError);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJSONRPCResponse.ResultAsJSONArray: TJsonArray;
|
||||||
|
begin
|
||||||
|
Result := Self.Result.AsObject as TJsonArray;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TJSONRPCResponse.ResultAsJSONObject: TJsonObject;
|
||||||
|
begin
|
||||||
|
Result := Self.Result.AsObject as TJsonObject;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TJSONRPCResponse.SetError(const Value: TJSONRPCResponseError);
|
procedure TJSONRPCResponse.SetError(const Value: TJSONRPCResponseError);
|
||||||
begin
|
begin
|
||||||
FError := Value;
|
FError := Value;
|
||||||
@ -882,18 +1073,23 @@ end;
|
|||||||
|
|
||||||
{ TJSONRPCResponseError }
|
{ TJSONRPCResponseError }
|
||||||
|
|
||||||
procedure TJSONRPCResponse.TJSONRPCResponseError.SetCode(const Value: Integer);
|
procedure TJSONRPCResponseError.SetCode(const Value: Integer);
|
||||||
begin
|
begin
|
||||||
FCode := Value;
|
FCode := Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TJSONRPCResponse.TJSONRPCResponseError.SetMessage(const Value: string);
|
procedure TJSONRPCResponseError.SetMessage(const Value: string);
|
||||||
begin
|
begin
|
||||||
FMessage := Value;
|
FMessage := Value;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TJSONRPCMessage }
|
{ TJSONRPCMessage }
|
||||||
|
|
||||||
|
function TJSONRPCRequest.GetID: TValue;
|
||||||
|
begin
|
||||||
|
Result := FID;
|
||||||
|
end;
|
||||||
|
|
||||||
function TJSONRPCRequest.GetJSON: TJsonObject;
|
function TJSONRPCRequest.GetJSON: TJsonObject;
|
||||||
begin
|
begin
|
||||||
Result := inherited GetJSON;
|
Result := inherited GetJSON;
|
||||||
@ -917,4 +1113,36 @@ begin
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TJSONRPCProxyGenerator }
|
||||||
|
|
||||||
|
constructor TJSONRPCProxyGenerator.Create;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure RegisterJSONRPCProxyGenerator(const aLanguage: String; const aClass: TJSONRPCProxyGeneratorClass);
|
||||||
|
begin
|
||||||
|
if not Assigned(GProxyGeneratorsRegister) then
|
||||||
|
begin
|
||||||
|
GProxyGeneratorsRegister := TDictionary<String, TJSONRPCProxyGeneratorClass>.Create();
|
||||||
|
end;
|
||||||
|
GProxyGeneratorsRegister.AddOrSetValue(aLanguage.ToLower, aClass);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TJSONRPCProxyGenerator.EndGeneration;
|
||||||
|
begin
|
||||||
|
// do nothing
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TJSONRPCProxyGenerator.StartGeneration;
|
||||||
|
begin
|
||||||
|
// do nothing
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
|
||||||
|
finalization
|
||||||
|
|
||||||
|
FreeAndNil(GProxyGeneratorsRegister);
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -119,7 +119,7 @@ end;
|
|||||||
function TRQLFirebirdCompiler.RQLLimitToSQL(const aRQLLimit: TRQLLimit): string;
|
function TRQLFirebirdCompiler.RQLLimitToSQL(const aRQLLimit: TRQLLimit): string;
|
||||||
begin
|
begin
|
||||||
// firebird ROWS requires Start > 0. Limit function is 0 based, so we have to add 1 to start.
|
// firebird ROWS requires Start > 0. Limit function is 0 based, so we have to add 1 to start.
|
||||||
Result := Format(' ROWS %d to %d', [aRQLLimit.Start + 1, aRQLLimit.Start + aRQLLimit.Count]);
|
Result := Format(' /*limit*/ ROWS %d to %d', [aRQLLimit.Start + 1, aRQLLimit.Start + aRQLLimit.Count]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRQLFirebirdCompiler.RQLLogicOperatorToSQL(const aRQLFIlter: TRQLLogicOperator): string;
|
function TRQLFirebirdCompiler.RQLLogicOperatorToSQL(const aRQLFIlter: TRQLLogicOperator): string;
|
||||||
@ -159,7 +159,7 @@ function TRQLFirebirdCompiler.RQLSortToSQL(const aRQLSort: TRQLSort): string;
|
|||||||
var
|
var
|
||||||
I: Integer;
|
I: Integer;
|
||||||
begin
|
begin
|
||||||
Result := ' ORDER BY';
|
Result := ' /*sort*/ ORDER BY';
|
||||||
for I := 0 to aRQLSort.Fields.Count - 1 do
|
for I := 0 to aRQLSort.Fields.Count - 1 do
|
||||||
begin
|
begin
|
||||||
if I > 0 then
|
if I > 0 then
|
||||||
|
@ -109,6 +109,7 @@ type
|
|||||||
procedure TValueToJsonElement(const Value: TValue; const JSON: TJsonObject; const KeyName: string);
|
procedure TValueToJsonElement(const Value: TValue; const JSON: TJsonObject; const KeyName: string);
|
||||||
procedure AppendTValueToJsonArray(const Value: TValue; const JSONArr: TJsonArray);
|
procedure AppendTValueToJsonArray(const Value: TValue; const JSONArr: TJsonArray);
|
||||||
function StringToJSON(const aValue: string): TJsonObject;
|
function StringToJSON(const aValue: string): TJsonObject;
|
||||||
|
procedure JsonObjectToObject(const AJsonObject: TJsonObject; const AObject: TObject; const AType: TMVCSerializationType; const AIgnoredAttributes: TMVCIgnoredList);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -1221,5 +1222,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure JsonObjectToObject(const AJsonObject: TJsonObject; const AObject: TObject; const AType: TMVCSerializationType; const AIgnoredAttributes: TMVCIgnoredList);
|
||||||
|
var
|
||||||
|
lSer: TMVCJsonDataObjectsSerializer;
|
||||||
|
begin
|
||||||
|
lSer := TMVCJsonDataObjectsSerializer.Create;
|
||||||
|
try
|
||||||
|
lSer.JsonObjectToObject(AJsonObject, AObject, AType, AIgnoredAttributes);
|
||||||
|
finally
|
||||||
|
lSer.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -605,6 +605,7 @@ type
|
|||||||
FViewEngineClass: TMVCViewEngineClass;
|
FViewEngineClass: TMVCViewEngineClass;
|
||||||
FWebModule: TWebModule;
|
FWebModule: TWebModule;
|
||||||
FConfig: TMVCConfig;
|
FConfig: TMVCConfig;
|
||||||
|
FConfigCache_MaxRequestSize: Int64;
|
||||||
FSerializers: TDictionary<string, IMVCSerializer>;
|
FSerializers: TDictionary<string, IMVCSerializer>;
|
||||||
FMiddlewares: TList<IMVCMiddleware>;
|
FMiddlewares: TList<IMVCMiddleware>;
|
||||||
FControllers: TObjectList<TMVCControllerDelegate>;
|
FControllers: TObjectList<TMVCControllerDelegate>;
|
||||||
@ -619,6 +620,7 @@ type
|
|||||||
function GetViewEngineClass: TMVCViewEngineClass;
|
function GetViewEngineClass: TMVCViewEngineClass;
|
||||||
protected
|
protected
|
||||||
procedure ConfigDefaultValues; virtual;
|
procedure ConfigDefaultValues; virtual;
|
||||||
|
procedure SaveCacheConfigValues;
|
||||||
procedure LoadSystemControllers; virtual;
|
procedure LoadSystemControllers; virtual;
|
||||||
procedure FixUpWebModule;
|
procedure FixUpWebModule;
|
||||||
procedure ExecuteBeforeRoutingMiddleware(const AContext: TWebContext; var AHandled: Boolean);
|
procedure ExecuteBeforeRoutingMiddleware(const AContext: TWebContext; var AHandled: Boolean);
|
||||||
@ -1587,6 +1589,7 @@ begin
|
|||||||
Config[TMVCConfigKey.SessionType] := 'memory';
|
Config[TMVCConfigKey.SessionType] := 'memory';
|
||||||
Config[TMVCConfigKey.IndexDocument] := 'index.html';
|
Config[TMVCConfigKey.IndexDocument] := 'index.html';
|
||||||
Config[TMVCConfigKey.MaxEntitiesRecordCount] := '20';
|
Config[TMVCConfigKey.MaxEntitiesRecordCount] := '20';
|
||||||
|
Config[TMVCConfigKey.MaxRequestSize] := IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE);
|
||||||
|
|
||||||
FMediaTypes.Add('.html', TMVCMediaType.TEXT_HTML);
|
FMediaTypes.Add('.html', TMVCMediaType.TEXT_HTML);
|
||||||
FMediaTypes.Add('.htm', TMVCMediaType.TEXT_HTML);
|
FMediaTypes.Add('.htm', TMVCMediaType.TEXT_HTML);
|
||||||
@ -1626,7 +1629,7 @@ begin
|
|||||||
AConfigAction(FConfig);
|
AConfigAction(FConfig);
|
||||||
LogExitMethod('Custom configuration method');
|
LogExitMethod('Custom configuration method');
|
||||||
end;
|
end;
|
||||||
|
SaveCacheConfigValues;
|
||||||
RegisterDefaultsSerializers;
|
RegisterDefaultsSerializers;
|
||||||
LoadSystemControllers;
|
LoadSystemControllers;
|
||||||
end;
|
end;
|
||||||
@ -1663,6 +1666,12 @@ var
|
|||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
|
|
||||||
|
ARequest.ReadTotalContent;
|
||||||
|
if ARequest.ContentLength > fConfigCache_MaxRequestSize then
|
||||||
|
begin
|
||||||
|
raise EMVCException.CreateFmt('Request size exceeded the max allowed size [%d KiB]', [(FConfigCache_MaxRequestSize div 1024)]);
|
||||||
|
end;
|
||||||
|
|
||||||
LParamsTable := TMVCRequestParamsTable.Create;
|
LParamsTable := TMVCRequestParamsTable.Create;
|
||||||
try
|
try
|
||||||
LContext := TWebContext.Create(ARequest, AResponse, FConfig, FSerializers);
|
LContext := TWebContext.Create(ARequest, AResponse, FConfig, FSerializers);
|
||||||
@ -2127,6 +2136,11 @@ begin
|
|||||||
Result := SendSessionCookie(AContext, SId);
|
Result := SendSessionCookie(AContext, SId);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMVCEngine.SaveCacheConfigValues;
|
||||||
|
begin
|
||||||
|
FConfigCache_MaxRequestSize := StrToInt64Def(Config[TMVCConfigKey.MaxRequestSize], TMVCConstants.DEFAULT_MAX_REQUEST_SIZE);
|
||||||
|
end;
|
||||||
|
|
||||||
class function TMVCEngine.SendSessionCookie(const AContext: TWebContext; const ASessionId: string): string;
|
class function TMVCEngine.SendSessionCookie(const AContext: TWebContext; const ASessionId: string): string;
|
||||||
var
|
var
|
||||||
Cookie: TCookie;
|
Cookie: TCookie;
|
||||||
@ -2904,3 +2918,4 @@ finalization
|
|||||||
FreeAndNil(_MVCGlobalActionParamsCache);
|
FreeAndNil(_MVCGlobalActionParamsCache);
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user