diff --git a/releases/dmvcframework_3_0_0_hydrogen_RC10.zip b/releases/dmvcframework_3_0_0_hydrogen_RC10.zip new file mode 100644 index 00000000..a911a834 Binary files /dev/null and b/releases/dmvcframework_3_0_0_hydrogen_RC10.zip differ diff --git a/samples/articles_crud_server/MainDM.dfm b/samples/articles_crud_server/MainDM.dfm index 7ea4209c..4aa68dfb 100644 --- a/samples/articles_crud_server/MainDM.dfm +++ b/samples/articles_crud_server/MainDM.dfm @@ -9,14 +9,12 @@ object dmMain: TdmMain 'Password=masterkey' 'DriverID=FB') ConnectedStoredUsage = [] - Connected = True LoginPrompt = False BeforeConnect = ConnectionBeforeConnect Left = 64 Top = 48 end object dsArticles: TFDQuery - Active = True Connection = Connection UpdateOptions.AssignedValues = [uvFetchGeneratorsPoint, uvGeneratorName] UpdateOptions.FetchGeneratorsPoint = gpImmediate diff --git a/samples/articles_crud_server/MainDM.pas b/samples/articles_crud_server/MainDM.pas index a0ba8aa5..8c371fe1 100644 --- a/samples/articles_crud_server/MainDM.pas +++ b/samples/articles_crud_server/MainDM.pas @@ -30,8 +30,8 @@ procedure TdmMain.ConnectionBeforeConnect(Sender: TObject); begin // currently, this demo uses firebird 2.5 // if you want to use firebird 2.5, you can use the file ORDERSMANAGER_FB25.FDB - // Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB30.FDB'; - Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB25.FDB'; + Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB30.FDB'; + // Connection.Params.Values['Database'] := '..\..\data\ORDERSMANAGER_FB25.FDB'; end; end. diff --git a/samples/articles_crud_server/WebModuleUnit1.pas b/samples/articles_crud_server/WebModuleUnit1.pas index 8b441e4e..46e2fe02 100644 --- a/samples/articles_crud_server/WebModuleUnit1.pas +++ b/samples/articles_crud_server/WebModuleUnit1.pas @@ -22,7 +22,7 @@ implementation { %CLASSGROUP 'Vcl.Controls.TControl' } -uses Controllers.Articles, MVCFramework.Middleware.CORS; +uses Controllers.Articles, MVCFramework.Middleware.CORS, MVCFramework.Middleware.Compression; {$R *.dfm} @@ -41,6 +41,8 @@ begin FEngine := TMVCEngine.Create(self); FEngine.AddController(TArticlesController); FEngine.AddMiddleware(TCORSMiddleware.Create); + FEngine.AddMiddleware(TCompressionMiddleware.Create); + end; end. diff --git a/samples/spring4dintegration/Controller1U.pas b/samples/spring4dintegration/Controller1U.pas new file mode 100644 index 00000000..fac5a577 --- /dev/null +++ b/samples/spring4dintegration/Controller1U.pas @@ -0,0 +1,40 @@ +unit Controller1U; + +interface + +uses + MVCFramework, MVCFramework.Commons, ServicesInterfaceU, Spring.Container.Common; + +type + + [MVCPath('/controller1')] + TMyController1 = class(TMVCController) + protected + [Inject] + fUsersService: IUsersService; + [Inject] + fCustomersService: ICustomersService; + public + [MVCPath] + [MVCHTTPMethod([httpGET])] + procedure Index; + end; + +implementation + +uses + System.SysUtils, MVCFramework.Logger, System.StrUtils; + +procedure TMyController1.Index; +begin + ContentType := BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591); + ResponseStream.AppendLine('THIS IS A TEST FOR SPRING4D INTEGRATION'); + ResponseStream.AppendLine('==============================================================='); + ResponseStream.AppendLine('fUsersService.GetUserNameByID(1234) => ' + + fUsersService.GetUserNameByID(1234)); + ResponseStream.AppendLine('fCustomersService.GetCustomerNameByID(1234) => ' + + fCustomersService.GetCustomerNameByID(1234)); + RenderResponseStream; +end; + +end. diff --git a/samples/spring4dintegration/Controller2U.pas b/samples/spring4dintegration/Controller2U.pas new file mode 100644 index 00000000..6c21e65b --- /dev/null +++ b/samples/spring4dintegration/Controller2U.pas @@ -0,0 +1,29 @@ +unit Controller2U; + +interface + +uses + MVCFramework, MVCFramework.Commons; + +type + + [MVCPath('/controller2')] + TMyController2 = class(TMVCController) + public + [MVCPath] + [MVCHTTPMethod([httpGET])] + procedure Index; + end; + +implementation + +uses + System.SysUtils, MVCFramework.Logger, System.StrUtils; + +procedure TMyController2.Index; +begin + // use Context property to access to the HTTP request and response + Render('Hello DelphiMVCFramework World'); +end; + +end. diff --git a/samples/spring4dintegration/DIConfiguration.pas b/samples/spring4dintegration/DIConfiguration.pas new file mode 100644 index 00000000..89774f31 --- /dev/null +++ b/samples/spring4dintegration/DIConfiguration.pas @@ -0,0 +1,81 @@ +unit DIConfiguration; + +interface + +uses + Spring, Spring.Container; + +procedure BuildContainer; +function Container: TContainer; + +implementation + +uses Spring.Container.Common, Controller1U, Service1U, Service2U, + ServicesInterfaceU, Controller2U, Service3U; + +var + GContainer: TContainer = nil; + +function Container: TContainer; +begin + Result := GContainer; +end; + +procedure BuildContainer; +begin + Assert(not Assigned(GContainer), 'Container already built'); + GContainer := TContainer.Create; + // Registering controllers + GContainer.RegisterType; + GContainer.RegisterType; + + // Registering Services + GContainer.RegisterType.Implements; + GContainer.RegisterType.Implements; + + // Maybe that the common service must be register as singleton or as singleton per thread + // because must be the same instances between the first and the second service (e.g. DB transaction) + + // Transient registration (default) + // GContainer.RegisterType.Implements; + + // Singleton registration for all thread. WARNING!!! It is shared between HTTP calls. + // GContainer.RegisterType.Implements.AsSingleton(TRefCounting.True); + + // Singleton per thread registration. WARNING!!! (read below) Shared by all services within the same HTTP call. + // GContainer.RegisterType.Implements.AsSingletonPerThread(TRefCounting.True); + + { + About "AsSingletonPerThread" Stefan Glienke said: + It might be confusing as people are assuming that the container magically + knows when a thread ends to destroy a singleton per thread. But that is not the case. + In fact it gets created once per threadid. That means even if your thread has + ended and a new one starts later using the same threadid you get the + same object as before. + If you don't use a threadpool where you have the same threads running all the + time performing tasks it is not a good idea to use singleton per thread. + You might use transient then to always create a new instance or - and this + is imo the better solution - use a threadpool which limits the objects + created (and also reduce the creation of thread objects). + Nevertheless singleton per thread instances will always be destroyed + when the container is getting destroyed, not earlier. + This is also not a strange behavior of our container but also Castle Windsor + or Unity. However there is also advice against using it there. + If you are looking more for something like singleton per request I suggest + using transient and making sure that at the start of the request it gets + resolved from the container and then passed around where ever needed (think + about implementing refcounting to your data module!) and dropping it at the + end of the request which makes it getting destroyed due to ref counting. + } + + // Build the container + GContainer.Build; +end; + +initialization + +finalization + +GContainer.Free; + +end. diff --git a/samples/spring4dintegration/Service1U.pas b/samples/spring4dintegration/Service1U.pas new file mode 100644 index 00000000..e4d9a17f --- /dev/null +++ b/samples/spring4dintegration/Service1U.pas @@ -0,0 +1,28 @@ +unit Service1U; + +interface + +uses ServicesInterfaceU, Spring.Container.Common; + +type + TUsersService = class(TInterfacedObject, IUsersService) + protected + [Inject] + fCommonService: ICommonService; + public + function GetUserNameByID(const ID: Integer): string; + end; + +implementation + +uses + System.SysUtils; + +{ TUsersService } + +function TUsersService.GetUserNameByID(const ID: Integer): string; +begin + Result := Format('User #%d (CommonServiceID = %s)', [ID, fCommonService.GetID]); +end; + +end. diff --git a/samples/spring4dintegration/Service2U.pas b/samples/spring4dintegration/Service2U.pas new file mode 100644 index 00000000..9271e187 --- /dev/null +++ b/samples/spring4dintegration/Service2U.pas @@ -0,0 +1,29 @@ +unit Service2U; + +interface + +uses + ServicesInterfaceU, Spring.Container.Common; + +type + TCustomersService = class(TInterfacedObject, ICustomersService) + protected + [Inject] + fCommonService: ICommonService; + public + function GetCustomerNameByID(const ID: Integer): string; + end; + +implementation + +uses + System.SysUtils; + +{ TCustomersService } + +function TCustomersService.GetCustomerNameByID(const ID: Integer): string; +begin + Result := Format('Customer #%d (CommonServiceID = %s)', [ID, fCommonService.GetID]); +end; + +end. diff --git a/samples/spring4dintegration/Service3U.pas b/samples/spring4dintegration/Service3U.pas new file mode 100644 index 00000000..a0ac02de --- /dev/null +++ b/samples/spring4dintegration/Service3U.pas @@ -0,0 +1,43 @@ +unit Service3U; + +interface + +uses + ServicesInterfaceU; + +type + TCommonService = class(TInterfacedObject, ICommonService) + private + FID: string; + public + constructor Create; + destructor Destroy; override; + function GetID: string; + end; + +implementation + +uses + System.SysUtils, MVCFramework.Logger; + +{ TService3 } + +constructor TCommonService.Create; +begin + inherited; + LogI('creating ' + ClassName); + FID := Random(1000).ToString; +end; + +destructor TCommonService.Destroy; +begin + LogI('destroing ' + ClassName); + inherited; +end; + +function TCommonService.GetID: string; +begin + Result := FID; +end; + +end. diff --git a/samples/spring4dintegration/ServicesInterfaceU.pas b/samples/spring4dintegration/ServicesInterfaceU.pas new file mode 100644 index 00000000..d3136bb6 --- /dev/null +++ b/samples/spring4dintegration/ServicesInterfaceU.pas @@ -0,0 +1,23 @@ +unit ServicesInterfaceU; + +interface + +type + IUsersService = interface + ['{D54AF728-7688-40DE-B10C-E6D63949531E}'] + function GetUserNameByID(const ID: Integer): String; + end; + + ICustomersService = interface + ['{DC94C34E-13A2-4406-8961-6A407B792DD3}'] + function GetCustomerNameByID(const ID: Integer): String; + end; + + ICommonService = interface + ['{EAA26199-4142-4698-9C17-5D241D9984AA}'] + function GetID: String; + end; + +implementation + +end. diff --git a/samples/spring4dintegration/WebModuleU.dfm b/samples/spring4dintegration/WebModuleU.dfm new file mode 100644 index 00000000..018d0670 --- /dev/null +++ b/samples/spring4dintegration/WebModuleU.dfm @@ -0,0 +1,8 @@ +object MyWebModule: TMyWebModule + OldCreateOrder = False + OnCreate = WebModuleCreate + OnDestroy = WebModuleDestroy + Actions = <> + Height = 230 + Width = 415 +end diff --git a/samples/spring4dintegration/WebModuleU.pas b/samples/spring4dintegration/WebModuleU.pas new file mode 100644 index 00000000..5f92ce2c --- /dev/null +++ b/samples/spring4dintegration/WebModuleU.pas @@ -0,0 +1,73 @@ +unit WebModuleU; + +interface + +uses System.SysUtils, + System.Classes, + Web.HTTPApp, + MVCFramework; + +type + TMyWebModule = class(TWebModule) + procedure WebModuleCreate(Sender: TObject); + procedure WebModuleDestroy(Sender: TObject); + private + FMVC: TMVCEngine; + public + { Public declarations } + end; + +var + WebModuleClass: TComponentClass = TMyWebModule; + +implementation + +{$R *.dfm} + +uses System.IOUtils, MVCFramework.Commons, DIConfiguration, Controller1U, + Controller2U; + +procedure TMyWebModule.WebModuleCreate(Sender: TObject); +begin + FMVC := TMVCEngine.Create(Self, + procedure(Config: TMVCConfig) + begin + // enable static files + Config[TMVCConfigKey.DocumentRoot] := TPath.Combine(ExtractFilePath(GetModuleName(HInstance)), 'www'); + // session timeout (0 means session cookie) + Config[TMVCConfigKey.SessionTimeout] := '0'; + // default content-type + Config[TMVCConfigKey.DefaultContentType] := TMVCConstants.DEFAULT_CONTENT_TYPE; + // default content charset + Config[TMVCConfigKey.DefaultContentCharset] := TMVCConstants.DEFAULT_CONTENT_CHARSET; + // unhandled actions are permitted? + Config[TMVCConfigKey.AllowUnhandledAction] := 'false'; + // default view file extension + Config[TMVCConfigKey.DefaultViewFileExtension] := 'html'; + // view path + Config[TMVCConfigKey.ViewPath] := 'templates'; + // Enable Server Signature in response + Config[TMVCConfigKey.ExposeServerSignature] := 'true'; + // Define a default URL for requests that don't map to a route or a file (useful for client side web app) + Config[TMVCConfigKey.FallbackResource] := 'index.html'; + end); + + FMVC.AddController(TMyController1, + function: TMVCController + begin + Result := Container.Resolve; + end); + + FMVC.AddController(TMyController2, + function: TMVCController + begin + Result := Container.Resolve; + end); +end; + +procedure TMyWebModule.WebModuleDestroy(Sender: TObject); +begin + FMVC.Free; +end; + +end. diff --git a/samples/spring4dintegration/spring4dintegration.dpr b/samples/spring4dintegration/spring4dintegration.dpr new file mode 100644 index 00000000..9f62cf3f --- /dev/null +++ b/samples/spring4dintegration/spring4dintegration.dpr @@ -0,0 +1,117 @@ +program spring4dintegration; + +{$APPTYPE CONSOLE} + +uses + System.SysUtils, + MVCFramework.Logger, + MVCFramework.Commons, + MVCFramework.REPLCommandsHandlerU, + Web.ReqMulti, + Web.WebReq, + Web.WebBroker, + IdHTTPWebBrokerBridge, + Controller1U in 'Controller1U.pas', + WebModuleU in 'WebModuleU.pas' {MyWebModule: TWebModule}, + DIConfiguration in 'DIConfiguration.pas', + Controller2U in 'Controller2U.pas', + Service1U in 'Service1U.pas', + Service2U in 'Service2U.pas', + ServicesInterfaceU in 'ServicesInterfaceU.pas', + Service3U in 'Service3U.pas'; + +{$R *.res} + +procedure RunServer(APort: Integer); +var + lServer: TIdHTTPWebBrokerBridge; + lCustomHandler: TMVCCustomREPLCommandsHandler; + lCmd: string; +begin + Writeln('** DMVCFramework Server ** build ' + DMVCFRAMEWORK_VERSION); + if ParamCount >= 1 then + lCmd := ParamStr(1) + else + lCmd := 'start'; + + lCustomHandler := function(const Value: string; const Server: TIdHTTPWebBrokerBridge; out Handled: Boolean): THandleCommandResult + begin + Handled := False; + Result := THandleCommandResult.Unknown; + + // Write here your custom command for the REPL using the following form... + // *** + // Handled := False; + // if (Value = 'apiversion') then + // begin + // REPLEmit('Print my API version number'); + // Result := THandleCommandResult.Continue; + // Handled := True; + // end + // else if (Value = 'datetime') then + // begin + // REPLEmit(DateTimeToStr(Now)); + // Result := THandleCommandResult.Continue; + // Handled := True; + // end; + end; + + LServer := TIdHTTPWebBrokerBridge.Create(nil); + try + LServer.DefaultPort := APort; + + { more info about MaxConnections + http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_MaxConnections.html } + LServer.MaxConnections := 0; + + { more info about ListenQueue + http://www.indyproject.org/docsite/html/frames.html?frmname=topic&frmfile=TIdCustomTCPServer_ListenQueue.html } + LServer.ListenQueue := 200; + + WriteLn('Write "quit" or "exit" to shutdown the server'); + repeat + if lCmd.IsEmpty then + begin + write('-> '); + ReadLn(lCmd) + end; + try + case HandleCommand(lCmd.ToLower, LServer, lCustomHandler) of + THandleCommandResult.Continue: + begin + Continue; + end; + THandleCommandResult.Break: + begin + Break; + end; + THandleCommandResult.Unknown: + begin + REPLEmit('Unknown command: ' + lCmd); + end; + end; + finally + lCmd := ''; + end; + until false; + + finally + LServer.Free; + end; +end; + +begin + ReportMemoryLeaksOnShutdown := True; + IsMultiThread := True; + try + if WebRequestHandler <> nil then + WebRequestHandler.WebModuleClass := WebModuleClass; + WebRequestHandlerProc.MaxConnections := 1024; + BuildContainer; + RunServer(8080); + except + on E: Exception do + Writeln(E.ClassName, ': ', E.Message); + end; + +end. diff --git a/samples/spring4dintegration/spring4dintegration.dproj b/samples/spring4dintegration/spring4dintegration.dproj new file mode 100644 index 00000000..8969d699 --- /dev/null +++ b/samples/spring4dintegration/spring4dintegration.dproj @@ -0,0 +1,582 @@ +ο»Ώ + + {6F8DDB74-BFCE-4A2F-AB59-93DF9153A05A} + 18.2 + None + spring4dintegration.dpr + True + Debug + Win32 + 1 + Console + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + RESTComponents;emsclientfiredac;DataSnapFireDAC;FireDACIBDriver;emsclient;FireDACCommon;RESTBackendComponents;soapserver;CloudService;FireDACCommonDriver;inet;FireDAC;FireDACSqliteDriver;soaprtl;soapmidas;$(DCC_UsePackage) + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + true + $(BDS)\bin\delphi_PROJECTICON.ico + $(BDS)\bin\delphi_PROJECTICNS.icns + $(DMVC);$(DCC_UnitSearchPath) + VCL;$(DCC_Framework) + spring4dintegration + + + DBXSqliteDriver;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage) + android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar + + + DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage) + + + DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage) + + + DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;bindcompfmx;FmxTeeUI;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;ibmonitor;FMXTee;DbxCommonDriver;ibxpress;xmlrtl;DataSnapNativeClient;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage) + + + FireDACADSDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;Spring.Data;inetdb;emsedge;dbexpress;IndyCore;dsnap;DataSnapCommon;DataSnapConnectors;bindengine;FireDACOracleDriver;FireDACMySQLDriver;FireDACCommonODBC;DataSnapClient;IndySystem;FireDACDb2Driver;FireDACInfxDriver;emshosting;FireDACPgDriver;FireDACASADriver;FireDACTDataDriver;DbxCommonDriver;DataSnapServer;xmlrtl;DataSnapNativeClient;rtl;DbxClientDriver;CustomIPTransport;bindcomp;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;dbrtl;IndyProtocols;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) + + + DBXSqliteDriver;fmxase;DBXInterBaseDriver;tethering;FireDACMSSQLDriver;bindcompfmx;DBXOracleDriver;Spring.Data;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;FireDACDBXDriver;dbexpress;IndyCore;dsnap;DataSnapCommon;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;bindcomp;DBXInformixDriver;IndyIPClient;dbxcds;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) + + + DBXSqliteDriver;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;svnui;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;Intraweb;DBXOracleDriver;Spring.Data;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;FixInsight_10_2;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;TelegaPiBot;dsnapcon;DMVC_IDE_Expert_D102Tokyo;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;JSPack_Tokyo;DataSnapServerMidas;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + + + DBXSqliteDriver;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;tethering;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;Intraweb;DBXOracleDriver;Spring.Data;inetdb;FmxTeeUI;emsedge;fmx;fmxdae;vclib;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;DataSnapCommon;DataSnapConnectors;VCLRESTComponents;vclie;bindengine;DBXMySQLDriver;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;DataSnapClient;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;emshosting;FireDACPgDriver;ibmonitor;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;DbxCommonDriver;ibxpress;Tee;DataSnapServer;xmlrtl;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;ibxbindings;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + .\bin + 1033 + (None) + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + + MainSource + + + +
MyWebModule
+ dfm + TWebModule +
+ + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + Console + + + + spring4dintegration.dpr + + + Embarcadero C++Builder Office 2000 Servers Package + Embarcadero C++Builder Office XP Servers Package + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + true + + + + + true + + + + + true + + + + + spring4dintegration.exe + true + + + + + 1 + + + Contents\MacOS + 0 + + + + + classes + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + + + res\values + 1 + + + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + 1 + + + 1 + + + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + False + False + False + False + False + False + True + False + + + 12 + + + + +
diff --git a/sources/MVCFramework.Console.pas b/sources/MVCFramework.Console.pas new file mode 100644 index 00000000..36e30151 --- /dev/null +++ b/sources/MVCFramework.Console.pas @@ -0,0 +1,130 @@ +unit MVCFramework.Console; + +interface + +type + TConsoleMode = (Normal, Bright); + TConsoleColor = ( + Black = 30, + Red = 31, + Green = 32, + Yellow = 33, + Blue = 34, + Magenta = 35, + Cyan = 36, + White = 37); + +procedure ResetConsole; +procedure TextColor(const Color: TConsoleColor); +procedure TextBackground(const Color: TConsoleColor); +procedure SetMode(const ConsoleMode: TConsoleMode); + +implementation + +uses + + {$IFDEF MSWINDOWS} + + WinApi.Windows, + + {$ENDIF} + + System.SysUtils; + +const + ESC = Chr(27); + +var + GForeGround: TConsoleColor; + GBackGround: TConsoleColor; + GMode: TConsoleMode = TConsolemode.Normal; + +function ToBackGround(const ForeGround: Byte): Byte; +begin + if (GMode = TConsoleMode.Bright) and (ForeGround <> Byte(TConsoleColor.Black)) then + begin + Result := ForeGround + 10 + 60; + end + else + begin + Result := ForeGround + 10; + end; +end; + +{$IFDEF LINUX} + +procedure EnableVirtualTerminalProcessing; inline; +begin + // do nothing +end; + +{$ELSE} + +procedure EnableVirtualTerminalProcessing; inline; + +const + ENABLE_VIRTUAL_TERMINAL_PROCESSING = $0004; + +var + hOut: THandle; + dwMode: UInt32; +begin + hOut := GetStdHandle(STD_OUTPUT_HANDLE); + if hOut = INVALID_HANDLE_VALUE then + raise Exception.CreateFmt('GetLastError() = %d', [GetLastError]); + + dwMode := 0; + if (not GetConsoleMode(hOut, &dwMode)) then + raise Exception.CreateFmt('GetLastError() = %d', [GetLastError]); + + dwMode := dwMode or ENABLE_VIRTUAL_TERMINAL_PROCESSING; + if (not SetConsoleMode(hOut, dwMode)) then + raise Exception.CreateFmt('GetLastError() = %d', [GetLastError]); +end; + +{$ENDIF} + +procedure ResetConsole; +begin + write(ESC + '[0m'); +end; + +function GetColorString: string; +begin + if GMode = TConsoleMode.Bright then + Result := Format('[%d;1;%dm', [Byte(GForeGround), ToBackGround(Byte(GBackGround))]) + else + Result := Format('[%d;%dm', [Byte(GForeGround), ToBackGround(Byte(GBackGround))]); +end; + +procedure TextColor(const Color: TConsoleColor); +begin + GForeGround := Color; + write(ESC + GetColorString); +end; + +procedure TextBackground(const Color: TConsoleColor); +begin + GBackGround := Color; + write(ESC + GetColorString); +end; + +procedure SetMode(const ConsoleMode: TConsoleMode); +begin + GMode := ConsoleMode; +end; + +procedure InitDefault; +begin + GForeGround := TConsoleColor.White; + GBackGround := TConsoleColor.Black; +end; + +initialization + +EnableVirtualTerminalProcessing; +InitDefault; + +finalization + +end. diff --git a/sources/MVCFramework.JWT.pas b/sources/MVCFramework.JWT.pas index 4794b803..e7f5ba75 100644 --- a/sources/MVCFramework.JWT.pas +++ b/sources/MVCFramework.JWT.pas @@ -610,6 +610,8 @@ var lIsRegistered: Boolean; lValue: string; begin + lJHeader := nil; + lJPayload := nil; Result := IsValidToken(Token, lJHeader, lJPayload, Error); try if not Result then diff --git a/sources/MVCFramework.Middleware.Compression.pas b/sources/MVCFramework.Middleware.Compression.pas index 52b1d418..1d6cdaca 100644 --- a/sources/MVCFramework.Middleware.Compression.pas +++ b/sources/MVCFramework.Middleware.Compression.pas @@ -27,9 +27,26 @@ procedure TCompressionMiddleware.OnAfterControllerAction(Context: TWebContext; var lMemStream: TMemoryStream; lContentStream: TStream; + lAcceptEncoding: string; + lEncodings: TArray; + lItem: string; + lFound: Boolean; begin - { TODO -oDaniele -cGeneral : It doesn0t work! } - if Context.Request.Headers['Accept-Encoding'].Trim.ToLower <> 'deflate' then + lAcceptEncoding := Context.Request.Headers['Accept-Encoding'].ToLower.Trim; + if lAcceptEncoding.IsEmpty then + Exit; + + lFound := False; + lEncodings := lAcceptEncoding.Split([',']); + for lItem in lEncodings do + begin + if lItem.Trim = 'deflate' then + begin + lFound := True; + Break; + end; + end; + if not lFound then Exit; lContentStream := Context.Response.RawWebResponse.ContentStream; diff --git a/sources/MVCFramework.REPLCommandsHandlerU.pas b/sources/MVCFramework.REPLCommandsHandlerU.pas index c79e6027..9a872e5f 100644 --- a/sources/MVCFramework.REPLCommandsHandlerU.pas +++ b/sources/MVCFramework.REPLCommandsHandlerU.pas @@ -10,26 +10,26 @@ type {$SCOPEDENUMS ON} THandleCommandResult = (Continue, Break, Unknown); - TMVCCustomREPLCommandsHandler = reference to function(const Value: String; const Server: TIdHTTPWebBrokerBridge; out Handled: Boolean): THandleCommandResult; + TMVCCustomREPLCommandsHandler = reference to function(const Value: string; const Server: TIdHTTPWebBrokerBridge; out Handled: Boolean): THandleCommandResult; -function HandleCommand(const Value: String; const Server: TIdHTTPWebBrokerBridge; const CustomCommandsHandler: TMVCCustomREPLCommandsHandler = nil): THandleCommandResult; -procedure REPLEmit(const Value: String); +function HandleCommand(const Value: string; const Server: TIdHTTPWebBrokerBridge; const CustomCommandsHandler: TMVCCustomREPLCommandsHandler = nil): THandleCommandResult; +procedure REPLEmit(const Value: string); implementation uses - System.SysUtils, MVCFramework.Commons; + System.SysUtils, MVCFramework.Commons, MVCFramework.Logger; -procedure REPLEmit(const Value: String); +procedure REPLEmit(const Value: string); begin // TextColor(LightGreen); - Write('#> '); + write('#> '); // TextColor(White); WriteLn(Value); // TextColor(White); end; -function HandleCommand(const Value: String; const Server: TIdHTTPWebBrokerBridge; const CustomCommandsHandler: TMVCCustomREPLCommandsHandler): THandleCommandResult; +function HandleCommand(const Value: string; const Server: TIdHTTPWebBrokerBridge; const CustomCommandsHandler: TMVCCustomREPLCommandsHandler): THandleCommandResult; var lTempCommandResult: THandleCommandResult; lHandled: Boolean; @@ -77,6 +77,7 @@ begin begin REPLEmit(Format('Starting server on port %d...', [Server.Bindings.DefaultPort])); Server.Active := True; + LogI('Server started on port ' + Server.Bindings.DefaultPort.ToString); REPLEmit('done!'); end; Result := THandleCommandResult.Continue; diff --git a/sources/MVCFramework.pas b/sources/MVCFramework.pas index 0adc8df5..00c65ce3 100644 --- a/sources/MVCFramework.pas +++ b/sources/MVCFramework.pas @@ -63,7 +63,7 @@ uses {$ENDIF} - // Delphi XE4 (all update) and XE5 (with no update) dont contains this unit. Look for the bug in QC + // Delphi XE4 (all update) and XE5 (with no update) don't contains this unit. Look for the bug in QC // https://quality.embarcadero.com/browse/RSP-17216 {$IFNDEF VER320} @@ -716,8 +716,6 @@ type property Output: string read FOutput; end; - - function IsShuttingDown: Boolean; procedure EnterInShutdownState; @@ -1610,6 +1608,7 @@ constructor TMVCEngine.Create( begin inherited Create(AWebModule); FWebModule := AWebModule; + FixUpWebModule; FConfig := TMVCConfig.Create; FSerializers := TDictionary.Create; FMiddlewares := TList.Create; @@ -1621,7 +1620,6 @@ begin WebRequestHandler.CacheConnections := True; WebRequestHandler.MaxConnections := 4096; - FixUpWebModule; MVCFramework.Logger.SetDefaultLogger(ACustomLogger); ConfigDefaultValues; @@ -2041,8 +2039,12 @@ end; procedure TMVCEngine.OnBeforeDispatch(ASender: TObject; ARequest: TWebRequest; AResponse: TWebResponse; var AHandled: Boolean); begin AHandled := False; - if Assigned(FSavedOnBeforeDispatch) then - FSavedOnBeforeDispatch(ASender, ARequest, AResponse, AHandled); + { there is a bug in WebBroker Linux on 10.2.1 tokyo } + // if Assigned(FSavedOnBeforeDispatch) then + // begin + // FSavedOnBeforeDispatch(ASender, ARequest, AResponse, AHandled); + // end; + if not AHandled then begin try diff --git a/unittests/general/Several/DMVCFrameworkTests.dproj b/unittests/general/Several/DMVCFrameworkTests.dproj index a9f30d7b..b5e01810 100644 --- a/unittests/general/Several/DMVCFrameworkTests.dproj +++ b/unittests/general/Several/DMVCFrameworkTests.dproj @@ -4,7 +4,7 @@ 18.2 VCL True - Debug + SERVER_ON_LINUX Win32 1 Console @@ -637,6 +637,7 @@ + False 12 diff --git a/unittests/general/Several/DMVCFrameworkTests.res b/unittests/general/Several/DMVCFrameworkTests.res index 2ec493a9..6876088a 100644 Binary files a/unittests/general/Several/DMVCFrameworkTests.res and b/unittests/general/Several/DMVCFrameworkTests.res differ diff --git a/unittests/general/Several/JSONRPCTestsU.pas b/unittests/general/Several/JSONRPCTestsU.pas index 06682bc0..bc99c6f8 100644 --- a/unittests/general/Several/JSONRPCTestsU.pas +++ b/unittests/general/Several/JSONRPCTestsU.pas @@ -75,8 +75,8 @@ begin lReq.Method := 'subtract'; lReq.Params.Add(42); lReq.Params.Add(23); - lReq.ID := 1; - Assert.AreEqual(1, lReq.ID.AsInteger); + lReq.RequestID := 1; + Assert.AreEqual(1, lReq.RequestID.AsInteger); Assert.AreEqual(42, lReq.Params[0].AsInteger); Assert.AreEqual(23, lReq.Params[1].AsInteger); Assert.AreEqual('subtract', lReq.Method); @@ -109,7 +109,7 @@ begin lReq := TJSONRPCRequest.Create; try lReq.AsJSONString := '{"jsonrpc": "2.0", "method": "subtract", "id": 1}'; - Assert.AreEqual(1, lReq.ID.AsInteger); + Assert.AreEqual(1, lReq.RequestID.AsInteger); Assert.AreEqual(0, lReq.Params.Count); Assert.AreEqual('subtract', lReq.Method); Assert.AreEqual(TJSONRPCRequestType.Request, lReq.RequestType); diff --git a/unittests/general/Several/LiveServerTestU.pas b/unittests/general/Several/LiveServerTestU.pas index 78909392..53e91eb9 100644 --- a/unittests/general/Several/LiveServerTestU.pas +++ b/unittests/general/Several/LiveServerTestU.pas @@ -35,7 +35,7 @@ const {$IFDEF LINUX_SERVER} - TEST_SERVER_ADDRESS = '192.168.3.88'; + TEST_SERVER_ADDRESS = '192.168.1.8'; {$ELSE} @@ -891,7 +891,7 @@ var begin res := RESTClient .Accept(TMVCMediaType.TEXT_PLAIN) - .ContentType(CreateContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591)) + .ContentType(BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591)) .doPOST('/testconsumes/textiso8859_1', [], 'ΰθιμςω'); Assert.areEqual(HTTP_STATUS.OK, res.ResponseCode); @@ -901,7 +901,7 @@ begin res := RESTClient .Accept(TMVCMediaType.TEXT_PLAIN) - .ContentType(CreateContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591)) + .ContentType(BuildContentType(TMVCMediaType.TEXT_PLAIN, TMVCCharSet.ISO88591)) .doPOST('/testconsumes/textiso8859_1', [], 'this is an iso8859-1 text'); Assert.areEqual(HTTP_STATUS.OK, res.ResponseCode); @@ -1246,7 +1246,7 @@ var begin lReq := TJSONRPCRequest.Create; try - lReq.ID := 1234; + lReq.RequestID := 1234; lReq.Method := 'subtract'; lReq.Params.Add(18); lReq.Params.Add(8); @@ -1260,7 +1260,7 @@ begin try lResp.AsJSONString := lHttpResp.BodyAsString; Assert.AreEqual(10, lResp.Result.AsInteger); - Assert.AreEqual(1234, lResp.ID.AsInteger); + Assert.AreEqual(1234, lResp.RequestID.AsInteger); finally lResp.Free; end; diff --git a/unittests/general/TestServer/TestServer.dpr b/unittests/general/TestServer/TestServer.dpr index 6c737152..e85dbbe2 100644 --- a/unittests/general/TestServer/TestServer.dpr +++ b/unittests/general/TestServer/TestServer.dpr @@ -7,12 +7,17 @@ uses System.SysUtils, IdHTTPWebBrokerBridge, Web.WebReq, + {$IFNDEF LINUX} + Winapi.Windows, + {$ENDIF } + Web.WebBroker, MVCFramework.Commons, - WebModuleUnit in 'WebModuleUnit.pas' {bas: TWebModule}, + MVCFramework.Console, + WebModuleUnit in 'WebModuleUnit.pas' {bas: TWebModule} , TestServerControllerU in 'TestServerControllerU.pas', TestServerControllerExceptionU in 'TestServerControllerExceptionU.pas', SpeedMiddlewareU in 'SpeedMiddlewareU.pas', @@ -28,13 +33,9 @@ uses procedure Logo; begin - - {$IFNDEF LINUX} - - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED or FOREGROUND_INTENSITY); - - {$ENDIF} - + SetMode(TConsoleMode.Bright); + TextBackground(TConsoleColor.Black); + TextColor(TConsoleColor.Red); WriteLn(' β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—'); WriteLn(' β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β• β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—'); WriteLn(' β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•'); @@ -42,22 +43,9 @@ begin WriteLn(' β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘'); WriteLn(' β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β• β•šβ•β•β•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β• β•šβ•β• β•šβ•β•β•β• β•šβ•β•β•β•β•β•β•β•šβ•β• β•šβ•β•'); WriteLn(' '); - - {$IFNDEF LINUX} - - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY); - - {$ENDIF} - + TextColor(TConsoleColor.Yellow); WriteLn('DMVCFRAMEWORK VERSION: ', DMVCFRAMEWORK_VERSION); - - {$IFNDEF LINUX} - - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE or FOREGROUND_GREEN or - FOREGROUND_RED); - - {$ENDIF} - + TextColor(TConsoleColor.White); end; procedure RunServer(APort: Integer); diff --git a/unittests/general/TestServer/TestServerControllerU.pas b/unittests/general/TestServer/TestServerControllerU.pas index 1b329f3a..9ad45ed4 100644 --- a/unittests/general/TestServer/TestServerControllerU.pas +++ b/unittests/general/TestServer/TestServerControllerU.pas @@ -344,7 +344,7 @@ procedure TTestServerController.TestCharset(ctx: TWebContext); var Obj: TJSONObject; begin - ContentType := CreateContentType(TMVCMediaType.APPLICATION_JSON, TMVCCharset.UTF_8); + ContentType := BuildContentType(TMVCMediaType.APPLICATION_JSON, TMVCCharset.UTF_8); Obj := TJSONObject.Create; Obj.AddPair('name1', 'jψrn'); Obj.AddPair('name2', 'Što je Unicode?');