Wizard uses dotEnv configurations

This commit is contained in:
Daniele Teti 2023-06-06 13:00:21 +02:00
parent 2604c3a52f
commit fd19c463f2
9 changed files with 111 additions and 34 deletions

View File

@ -48,9 +48,9 @@ resourcestring
' System.SysUtils,' + sLineBreak +
' MVCFramework,' + sLineBreak +
' MVCFramework.Logger,' + sLineBreak +
' MVCFramework.DotEnv,' + sLineBreak +
' MVCFramework.Commons,' + sLineBreak +
' MVCFramework.Signal,' + sLineBreak +
// ' MVCFramework.REPLCommandsHandlerU,' + sLineBreak +
{$IF Defined(SeattleOrBetter)}
' Web.ReqMulti, //If you have problem with this unit, see https://quality.embarcadero.com/browse/RSP-17216' + sLineBreak +
' Web.WebReq,' + sLineBreak +
@ -69,24 +69,15 @@ resourcestring
'procedure RunServer(APort: Integer);' + sLineBreak +
'var' + sLineBreak +
' LServer: TIdHTTPWebBrokerBridge;' + sLineBreak +
// ' LCustomHandler: TMVCCustomREPLCommandsHandler;' + sLineBreak +
// ' LCmd: string;' + sLineBreak +
'begin' + sLineBreak +
' Writeln(''** DMVCFramework Server ** build '' + DMVCFRAMEWORK_VERSION);' + sLineBreak +
' LServer := TIdHTTPWebBrokerBridge.Create(nil);' + sLineBreak +
' try' + sLineBreak +
' LServer.OnParseAuthentication := TMVCParseAuthentication.OnParseAuthentication;' + sLineBreak +
' LServer.DefaultPort := APort;' + sLineBreak +
' LServer.KeepAlive := True;' + sLineBreak + sLineBreak +
' { more info about MaxConnections' + sLineBreak +
' http://ww2.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=index.html }' + sLineBreak +
' LServer.MaxConnections := 0;' + sLineBreak +
sLineBreak +
' { more info about ListenQueue' + sLineBreak +
' http://ww2.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=index.html }' + sLineBreak +
' LServer.ListenQueue := 200;' + sLineBreak +
sLineBreak +
// ' WriteLn(''Write "quit" or "exit" to shutdown the server'');' + sLineBreak +
' LServer.KeepAlive := True;' + sLineBreak +
' LServer.MaxConnections := dotEnv.Env(''dmvc.webbroker.max_connections'', 0);' + sLineBreak +
' LServer.ListenQueue := dotEnv.Env(''dmvc.indy.listen_queue'', 500);' + sLineBreak + sLineBreak +
' LServer.Active := True;' + sLineBreak +
' WriteLn(''Listening on port '', APort);' + sLineBreak +
' Write(''CTRL+C to shutdown the server'');' + sLineBreak +
@ -108,8 +99,23 @@ resourcestring
' try' + sLineBreak +
' if WebRequestHandler <> nil then' + sLineBreak +
' WebRequestHandler.WebModuleClass := WebModuleClass;' + sLineBreak +
'' + sLineBreak +
' dotEnv(' + sLineBreak +
' NewDotEnv' + sLineBreak +
' .UseLogger(procedure (LogItem: String)' + sLineBreak +
' begin' + sLineBreak +
' LogW(''dotEnv: '' + LogItem);' + sLineBreak +
' end)' + sLineBreak +
'' + sLineBreak +
' .WithStrategy(TMVCDotEnvPriority.FileThenEnv)' + sLineBreak +
' //if available, by default, loads default environment (.env)' + sLineBreak +
' .UseProfile(''test'') //if available loads the test environment (.env.test)' + sLineBreak +
' .UseProfile(''prod'') //if available loads the prod environment (.env.prod)' + sLineBreak +
' .Build() //uses the executable folder to look for .env* files' + sLineBreak +
' );' + sLineBreak +
'' + sLineBreak +
' WebRequestHandlerProc.MaxConnections := 1024;' + sLineBreak +
' RunServer(%1:d);' + sLineBreak +
' RunServer(dotEnv.Env(''dmvc.server.port'', %1:d));' + sLineBreak +
' except' + sLineBreak +
' on E: Exception do' + sLineBreak +
' Writeln(E.ClassName, '': '', E.Message);' + sLineBreak +
@ -290,30 +296,31 @@ resourcestring
' FMVC := TMVCEngine.Create(Self,' + sLineBreak +
' procedure(Config: TMVCConfig)' + sLineBreak +
' begin' + sLineBreak +
' Config.dotEnv := dotEnv; ' + sLineBreak +
' // session timeout (0 means session cookie)' + sLineBreak +
' Config[TMVCConfigKey.SessionTimeout] := ''0'';' + sLineBreak +
' Config[TMVCConfigKey.SessionTimeout] := dotEnv.Env(''dmvc.session_timeout'', ''0'');' + sLineBreak +
' //default content-type' + sLineBreak +
' Config[TMVCConfigKey.DefaultContentType] := TMVCConstants.DEFAULT_CONTENT_TYPE;' +
' Config[TMVCConfigKey.DefaultContentType] := dotEnv.Env(''dmvc.default.content_type'', TMVCConstants.DEFAULT_CONTENT_TYPE);' +
sLineBreak +
' //default content charset' + sLineBreak +
' Config[TMVCConfigKey.DefaultContentCharset] := TMVCConstants.DEFAULT_CONTENT_CHARSET;' +
' Config[TMVCConfigKey.DefaultContentCharset] := dotEnv.Env(''dmvc.default.content_charset'', TMVCConstants.DEFAULT_CONTENT_CHARSET);' +
sLineBreak +
' //unhandled actions are permitted?' + sLineBreak +
' Config[TMVCConfigKey.AllowUnhandledAction] := ''false'';' + sLineBreak +
' Config[TMVCConfigKey.AllowUnhandledAction] := dotEnv.Env(''dmvc.allow_unhandled_actions'', ''false'');' + sLineBreak +
' //enables or not system controllers loading (available only from localhost requests)' + sLineBreak +
' Config[TMVCConfigKey.LoadSystemControllers] := ''true'';' + sLineBreak +
' Config[TMVCConfigKey.LoadSystemControllers] := dotEnv.Env(''dmvc.load_system_controllers'', ''true'');' + sLineBreak +
' //default view file extension' + sLineBreak +
' Config[TMVCConfigKey.DefaultViewFileExtension] := ''html'';' + sLineBreak +
' Config[TMVCConfigKey.DefaultViewFileExtension] := dotEnv.Env(''dmvc.default.view_file_extension'', ''html'');' + sLineBreak +
' //view path' + sLineBreak +
' Config[TMVCConfigKey.ViewPath] := ''templates'';' + sLineBreak +
' Config[TMVCConfigKey.ViewPath] := dotEnv.Env(''dmvc.view_path'', ''templates'');' + sLineBreak +
' //Max Record Count for automatic Entities CRUD' + sLineBreak +
' Config[TMVCConfigKey.MaxEntitiesRecordCount] := ''20'';' + sLineBreak +
' Config[TMVCConfigKey.MaxEntitiesRecordCount] := dotEnv.Env(''dmvc.max_entities_record_count'', IntToStr(TMVCConstants.MAX_RECORD_COUNT));' + sLineBreak +
' //Enable Server Signature in response' + sLineBreak +
' Config[TMVCConfigKey.ExposeServerSignature] := ''true'';' + sLineBreak +
' Config[TMVCConfigKey.ExposeServerSignature] := dotEnv.Env(''dmvc.expose_server_signature'', ''false'');' + sLineBreak +
' //Enable X-Powered-By Header in response' + sLineBreak +
' Config[TMVCConfigKey.ExposeXPoweredBy] := ''true'';' + sLineBreak +
' Config[TMVCConfigKey.ExposeXPoweredBy] := dotEnv.Env(''dmvc.expose_x_powered_by'', ''true'');' + sLineBreak +
' // Max request size in bytes' + sLineBreak +
' Config[TMVCConfigKey.MaxRequestSize] := IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE);' + sLineBreak +
' Config[TMVCConfigKey.MaxRequestSize] := dotEnv.Env(''dmvc.max_request_size'', IntToStr(TMVCConstants.DEFAULT_MAX_REQUEST_SIZE));' + sLineBreak +
' end);' + sLineBreak +
' FMVC.AddController(%3:s);' + sLineBreak + sLineBreak +
' %4:s ' + sLineBreak +

View File

@ -218,7 +218,10 @@ const
M_COMPRESSION = 'FMVC.AddMiddleware(TMVCCompressionMiddleware.Create);';
M_ETAG = 'FMVC.AddMiddleware(TMVCETagMiddleware.Create);';
M_CORS = 'FMVC.AddMiddleware(TMVCCORSMiddleware.Create);';
M_ACTIVERECORD = 'FMVC.AddMiddleware(TMVCActiveRecordMiddleware.Create(''%s'',''%s''));';
M_ACTIVERECORD = 'FMVC.AddMiddleware(TMVCActiveRecordMiddleware.Create(' + sLineBreak +
' dotEnv.Env(''firedac.connection_definition_name'', ''%s''), ' + sLineBreak +
' dotEnv.Env(''firedac.connection_definitions_filename'', ''%s'')' + sLineBreak +
' ));';
function GetText(const Edit: TCustomEdit): String;
begin
@ -233,7 +236,7 @@ const
end;
begin
Result := [];
Result := Result + ['', '// Analytics middleware generates a csv log, useful to do trafic analysis'];
Result := Result + ['', '// Analytics middleware generates a csv log, useful to do traffic analysis'];
Result := Result + [ifthen(not chkAnalyticsMiddleware.Checked, '//') + M_ANALYTICS];
Result := Result + ['', '// The folder mapped as documentroot for TMVCStaticFilesMiddleware must exists!'];
Result := Result + [ifthen(not chkStaticFiles.Checked, '//') + M_STATICFILES];

View File

@ -111,7 +111,9 @@ contains
MVCFramework.RESTClient.Intf in '..\..\sources\MVCFramework.RESTClient.Intf.pas',
MVCFramework.RESTClient in '..\..\sources\MVCFramework.RESTClient.pas',
MVCFramework.Utils in '..\..\sources\MVCFramework.Utils.pas',
JsonDataObjects in '..\..\sources\JsonDataObjects.pas';
JsonDataObjects in '..\..\sources\JsonDataObjects.pas',
MVCFramework.DotEnv.Parser in '..\..\sources\MVCFramework.DotEnv.Parser.pas',
MVCFramework.DotEnv in '..\..\sources\MVCFramework.DotEnv.pas';
end.

View File

@ -194,6 +194,8 @@
<DCCReference Include="..\..\sources\MVCFramework.RESTClient.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.Utils.pas"/>
<DCCReference Include="..\..\sources\JsonDataObjects.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.DotEnv.Parser.pas"/>
<DCCReference Include="..\..\sources\MVCFramework.DotEnv.pas"/>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>

View File

@ -41,7 +41,7 @@ begin
// session timeout (0 means session cookie)
Config[TMVCConfigKey.SessionTimeout] := Config.dotEnv.Env('dmvc.session_timeout', '0');
//default content-type
Config[TMVCConfigKey.DefaultContentType] := Config.dotEnv.Env('dmvc.defaults.content_type', TMVCConstants.DEFAULT_CONTENT_TYPE);
Config[TMVCConfigKey.DefaultContentType] := Config.dotEnv.Env('dmvc.default.content_type', TMVCConstants.DEFAULT_CONTENT_TYPE);
//default content charset
Config[TMVCConfigKey.DefaultContentCharset] := Config.dotEnv.Env('dmvc.default.content_charset', TMVCConstants.DEFAULT_CONTENT_CHARSET);
//unhandled actions are permitted?

View File

@ -4,6 +4,7 @@ program concurrency_speed_test;
uses
RDPMM64,
System.SysUtils,
MVCFramework,
MVCFramework.Logger,

View File

@ -6,8 +6,8 @@
<MainSource>concurrency_speed_test.dpr</MainSource>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>1</TargetedPlatforms>
<Platform Condition="'$(Platform)'==''">Win64</Platform>
<TargetedPlatforms>3</TargetedPlatforms>
<AppType>Console</AppType>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
@ -49,6 +49,12 @@
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''">
<Cfg_1_Win64>true</Cfg_1_Win64>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
@ -111,6 +117,13 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;emsclientfiredac;tethering;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;DBXOracleDriver;Spring.Data;inetdb;FmxTeeUI;emsedge;fmx;FireDACIBDriver;fmxdae;RadiantShapesFmx;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;ibxbindings;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;RadiantShapesFmx_Design;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
<DCC_ExeOutput>.\bin</DCC_ExeOutput>
<Manifest_File>(None)</Manifest_File>
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
@ -129,6 +142,10 @@
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
<DCC_Define>PROFILE;$(DCC_Define)</DCC_Define>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
<Manifest_File>(None)</Manifest_File>
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
@ -145,7 +162,6 @@
<DCCReference Include="MainControllerU.pas"/>
<DCCReference Include="WebModuleU.pas">
<Form>MyWebModule</Form>
<FormType>dfm</FormType>
<DesignClass>TWebModule</DesignClass>
</DCCReference>
<BuildConfiguration Include="Base">
@ -924,7 +940,7 @@
<Platform value="Android64">False</Platform>
<Platform value="Linux64">False</Platform>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
<Platform value="Win64">True</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>

View File

@ -0,0 +1,16 @@
from locust import HttpUser, task, between
class APITest(HttpUser):
#wait_time = between(0.5, 3.0)
def on_start(self):
""" on_start is called when a Locust start before any task is scheduled """
pass
def on_stop(self):
""" on_stop is called when the TaskSet is stopping """
pass
@task(1)
def index(self):
self.client.get("/api")

View File

@ -26,7 +26,8 @@ unit MVCFramework.DotEnv;
interface
uses System.SysUtils, System.Generics.Collections, MVCFramework.DotEnv.Parser;
uses
System.SysUtils, System.Generics.Collections, MVCFramework.DotEnv.Parser;
type
{$SCOPEDENUMS ON}
@ -48,6 +49,7 @@ type
IMVCDotEnvBuilder = interface
['{1A5EDD44-7226-40BC-A8EE-789E27522392}']
function WithStrategy(const Strategy: TMVCDotEnvPriority = TMVCDotEnvPriority.EnvThenFile): IMVCDotEnvBuilder;
function UseLogger( const Logger: TProc<String>): IMVCDotEnvBuilder;
function UseProfile(const ProfileName: String): IMVCDotEnvBuilder;
function ClearProfiles: IMVCDotEnvBuilder;
function Build(const DotEnvPath: string = ''): IMVCDotEnv; overload;
@ -76,7 +78,9 @@ type
fPriority: TMVCDotEnvPriority;
fEnvPath: string;
fEnvDict: TMVCDotEnvDictionary;
fLoggerProc: TProc<String>;
fProfiles: TList<String>;
procedure DoLog(const Value: String);
procedure ReadEnvFile;
function GetDotEnvVar(const key: string): string;
function ExplodePlaceholders(const Value: string): string;
@ -86,6 +90,7 @@ type
strict protected
function WithStrategy(const Priority: TMVCDotEnvPriority = TMVCDotEnvPriority.EnvThenFile): IMVCDotEnvBuilder; overload;
function UseProfile(const ProfileName: String): IMVCDotEnvBuilder;
function UseLogger(const LoggerProc: TProc<String>): IMVCDotEnvBuilder;
function ClearProfiles: IMVCDotEnvBuilder;
function Build(const DotEnvDirectory: string = ''): IMVCDotEnv; overload;
function Env(const Name: string): string; overload;
@ -157,6 +162,17 @@ begin
end;
end;
function TMVCDotEnv.UseLogger(
const LoggerProc: TProc<String>): IMVCDotEnvBuilder;
begin
if Assigned(fLoggerProc) then
begin
raise EMVCDotEnv.Create('Logger already set');
end;
fLoggerProc := LoggerProc;
Result := Self;
end;
function TMVCDotEnv.UseProfile(const ProfileName: String): IMVCDotEnvBuilder;
begin
CheckAlreadyBuilt;
@ -172,6 +188,8 @@ begin
end;
function TMVCDotEnv.Build(const DotEnvDirectory: string): IMVCDotEnv;
var
lAllProfiles: TArray<String>;
begin
if fState <> TdotEnvEngineState.created then
begin
@ -185,6 +203,8 @@ begin
fEnvPath := TPath.Combine(fEnvPath, DotEnvDirectory);
end;
fEnvDict.Clear;
lAllProfiles := ['default'] + fProfiles.ToArray();
DoLog('Active profile/s priority = [' + String.Join(',', lAllProfiles) + ']');
ReadEnvFile;
ExplodeReferences;
fState := TdotEnvEngineState.built;
@ -222,6 +242,14 @@ begin
inherited;
end;
procedure TMVCDotEnv.DoLog(const Value: String);
begin
if Assigned(fLoggerProc) then
begin
fLoggerProc(Value);
end;
end;
function TMVCDotEnv.Env(const Name, DefaultValue: String): string;
begin
Result := Env(Name);
@ -325,6 +353,7 @@ var
begin
if not TFile.Exists(EnvFilePath) then
begin
DoLog('Missed dotEnv file ' + EnvFilePath);
Exit;
end;
@ -332,6 +361,7 @@ begin
lParser := TMVCDotEnvParser.Create;
try
lParser.Parse(fEnvDict, lDotEnvCode);
DoLog('Applied dotEnv file ' + EnvFilePath);
finally
lParser.Free;
end;