Working with Application
IWebApplication interface
In Fano Framework, application must implements IWebApplication
interface.
Currently, it does not provide any method except inherit run()
method from
IRunnable
interface which is its parent.
View IWebApplication source code.
Built-in Implementation
Fano Framework provides built-in implementations of IWebApplication
,
TCgiWebApplication
, CGI web application that implement CGI protocol. It is basically just shell application which run and then terminate after completing its job.TDaemonWebApplication
, is web application that run forever and listen for request until it is terminated manually. This is used mostly for FastCGI, SCGI and uwsgi web application.
IAppServiceProvider interface
TCgiWebApplication
depends on instance of IAppServiceProvider
interface while TDaemonWebApplication
depends on IDaemonAppServiceProvider
. They provide essential services for application. Following code is declaration of this interface.
type
IAppServiceProvider = interface(IServiceProvider)
['{41032A70-F31D-45A6-AE26-574888BE4D07}']
function getContainer() : IDependencyContainer;
property container : IDependencyContainer read getContainer;
function getErrorHandler() : IErrorHandler;
property errorHandler : IErrorHandler read getErrorHandler;
function getDispatcher() : IDispatcher;
property dispatcher : IDispatcher read getDispatcher;
function getEnvironment() : ICGIEnvironment;
property env : ICGIEnvironment read getEnvironment;
function getRouter() : IRouter;
property router : IRouter read getRouter;
function getStdIn() : IStdIn;
property stdIn : IStdIn read getStdIn;
end;
IDaemonAppServiceProvider = interface(IAppServiceProvider)
['{4FF6129E-171F-429C-BE5B-7A8B941D3626}']
function getServer() : IRunnableWithDataNotif;
property server : IRunnableWithDataNotif read getServer;
function getProtocol() : IProtocolProcessor;
property protocol : IProtocolProcessor read getProtocol;
function getOutputBuffer() : IOutputBuffer;
property outputBuffer : IOutputBuffer read getOutputBuffer;
function getStdOut() : IStdOut;
property stdOut : IStdOut read getStdOut;
end;
Fano Framework provides several built-in implementation of this interface that you can use or extend.
-
TBasicAppServiceProvider
, abstract class that implementsIAppServiceProvider
interface. Most of methods already has implementation, except itsregister()
method which you must implement to register your application specific dependencies. For CGI web application, this class is what you need to use. -
TDaemonAppServiceProvider
, abstract class inherits fromTBasicAppServiceProvider
class that implementsIDaemonAppServiceProvider
interface. Most of methods already has implementation, except itsregister()
method which you must implement to register your application specific dependencies. For daemon web application, this class is what you need to use. -
TServerAppServiceProvider
, class which provides worker server for daemon web application. -
TFastCgiAppServiceProvider
, class which provides essentials service for FastCGI web application. -
TScgiAppServiceProvider
, class which provides essentials service for SCGI web application. -
TUwsgiAppServiceProvider
, class which provides essentials service for uwsgi web application. -
TMhdAppServiceProvider
, class which provides essentials service for libmicrohttpd web application.
IRouteBuilder interface
When creating application instance, you need also to implement IRouteBuilder
interface which responsible to setup application routes. Please read Route Builder section documentation for more information.
CGI Application
TCgiWebApplication
is built-in class that implements CGI protocol. Its task is basically to read CGI environment variables that web server send and call appropriate request handler.
Its constructor method expects two parameter, instance of IAppServiceProvider
and IRouteBuilder
interface. The first parameter must provide essentials services that is required by application and also register any application dependencies.
For CGI application, Fano Framework provides abstract class TBasicAppServiceProvider
which you need to extend to register you application dependencies. You must implements its register()
method.
The last parameter is instance of class responsible to build application routes. Fano Framework provides base abstract class TRouteBuilder
which you need to extend. You must implements its buildRoutes()
. Please note that, you do not required to inherit from TRouteBuilder
class. You can use any class as long as it implements IRouteBuilder
interface.
appInstance := TCgiWebApplication.create(
TAppServiceProvider.create(),
TAppRoutes.create()
);
Where TAppServiceProvider
is declared as follow,
TAppServiceProvider = class(TBasicAppServiceProvider)
public
procedure register(const container : IDependencyContainer); override;
end;
...
procedure TAppServiceProvider.register(const container : IDependencyContainer);
begin
//register all application required service here
end;
TAppRoutes = class(TRouteBuilder)
public
procedure buildRoutes(
const container : IDependencyContainer;
const router : IRouter
); override;
end;
...
procedure TAppRoutes.buildRoutes(
const container : IDependencyContainer;
const router : IRouter
);
begin
//register all routes here
end;
View TCgiWebApplication source code.
Daemon web application
Web application that runs forever in background must setup service provider that inherit from TDaemonAppServiceProvider
such as web application that utilize FastCGI, SCGI or uwsgi protocol because application depends on IDaemonAppServiceProvider
interface.
TAppServiceProvider = class(TDaemonAppServiceProvider)
public
procedure register(const container : IDependencyContainer); override;
end;
FastCGI Application
To create web application that support FastCGI protocol, create application service provider which use TFastCgiAppServiceProvider
as shown in following code,
appInstance := TDaemonWebApplication.create(
TFastCgiAppServiceProvider.create(
TServerAppServiceProvider.create(
TAppServiceProvider.create(),
(TInetSvrFactory.create(host, port) as ISocketSvrFactory).build()
)
),
TAppRoutes.create()
);
See fano-fastcgi example demo application.
You can replace TInetSvrFactory
with TUnixSvrFactory
class if you want to use Unix Domain Socket file instead of TCP port. See fano-fcgi-unix example demo application.
You can replace TInetSvrFactory
with TBoundSvrFactory
if you want to create FastCGI application which run and managed by web server, for example Apache with mod_fcgid
module. See
fano-fcgid example demo application.
TInetSvrFactory
, TUnixSvrFactory
and TBoundSvrFactory
use select to monitor if socket is ready for I/O operation. To use epoll, replace with TEpollInetSvrFactory
, TEpollUnixSvrFactory
and TEpollBoundSvrFactory
. If you use FreeBSD, to use kqueue, replace with TKqueueInetSvrFactory
, TKqueueUnixSvrFactory
and TKqueueBoundSvrFactory
. You need to add conditional compilation define $DEFINE USE_KQUEUE
or add -dUSE_KQUEUE
line in build.cfg
file.
See Deploy as FastCGI application for information how to deploy FastCGI application on various web servers.
You may want to read Scaffolding FastCGI project directory structure for information how to scaffolding FastCGI web application with Fano CLI.
SCGI Application
To create web application that support SCGI (Simple Common Gateway Interface) protocol, create application service provider which use TScgiAppServiceProvider
as shown in following code,
appInstance := TDaemonWebApplication.create(
TScgiAppServiceProvider.create(
TServerAppServiceProvider.create(
TAppServiceProvider.create(),
(TInetSvrFactory.create(host, port) as ISocketSvrFactory).build()
)
),
TAppRoutes.create()
);
See fano-scgi example demo application.
See Deploy as SCGI application for information how to deploy SCGI application on various web servers.
You may want to read Scaffolding SCGI project directory structure for information how to scaffolding SCGI web application easily.
Uwsgi Application
To create web application that support uwsgi protocol, create application service provider which use TUwsgiAppServiceProvider
as shown in following code,
appInstance := TDaemonWebApplication.create(
TUwsgiAppServiceProvider.create(
TServerAppServiceProvider.create(
TAppServiceProvider.create(),
(TInetSvrFactory.create(host, port) as ISocketSvrFactory).build()
)
),
TAppRoutes.create()
);
See fano-uwsgi example demo application.
See Deploy as uwsgi application for information how to deploy uwsgi application on various web servers.
You may want to read Scaffolding uwsgi project directory structure for information how to scaffolding uwsgi web application easily.
Http Application
To create web application that support http protocol using libmicrohttpd, create application service provider which use TMhdAppServiceProvider
also fill web server configuration as shown in following code,
var
svrConfig : TMhdSvrConfig;
...
svrConfig.host := 'example.fano';
svrConfig.port := 8080;
svrConfig.documentRoot := getCurrentDir() + '/public';
svrConfig.serverName := 'example.fano';
svrConfig.serverAdmin := 'admin@example.fano';
svrConfig.serverSoftware := 'Fano Framework Web App';
svrConfig.timeout := 120; //connection timeout in sec
appInstance := TDaemonWebApplication.create(
TMhdAppServiceProvider.create(
TAppServiceProvider.create(),
svrConfig
),
TAppRoutes.create()
);
See fano-http example demo application.
See Deploy as standalone web server for information how to deploy http application as stand alone web server or through various reverse proxy web servers.
You may want to read Scaffolding libmicrohttpd project directory structure for information how to scaffolding libmicrohttpd web application easily.
Use IPv6 address
If you want to create web application server which binds to IPv6 address, replace TInetSvrFactory
, TEpollInetSvrFactory
, TKqueueInetSvrFactory
with TInet6SvrFactory
, TEpollInet6SvrFactory
, TKqueueInet6SvrFactory
class respectively.
You may need to replace server address in proxy module of web server. For example for SCGI application using Apache mod_proxy_scgi
module, you need to change virtual host configuration as shown in following example.
# IPv4 address
# ProxyPassMatch ^/(.*)$ "scgi://127.0.0.1:20477"
# IPv6 address
ProxyPassMatch ^/(.*)$ "scgi://[::1]:20477"
Please note that the IPv6 address needs to be inside square brackets.
See fano-ipv6 example demo application which use IPv6.
For libmicrohttpd-based web application, you can add support to IPv6 address by setting
field useIPv6
of TMhdSvrConfig
record to true
. If you need both IPv4 and IPv6, set field dualStack
of TMhdSvrConfig
to true
.
var svrConfig : TMhdSvrConfig;
...
svrConfig.useIPv6 :=true;
svrConfig.dualStack := false; //IPv6 only
See fano-mhdipv6 example demo http application which use IPv6.
How to choose IWebApplication implementation?
CGI Application
Pros
- Easy to setup especially on shared-hosting where you do not posses server administrive privilege.
Cons
- Not very performant compared to FastCGI or SCGI application due to how CGI protocol works.
FastCGI Application
Pros
- Performance is good compared to CGI application.
Cons
- Requires server administrative privilege to setup. You can not deploy application on shared-hosting easily.
SCGI Application
Pros
- Performance is good compared to CGI application and maybe slightly better than FastCGI due to simpler protocol specification.
Cons
- Requires server administrative privilege to setup. You can not deploy application on shared-hosting easily.
uwsgi Application
Pros
- Performance is comparable to SCGI protocol but less network bandwidth requirement due to use of binary protocol.
Cons
- Requires server administrative privilege to setup. You can not deploy application on shared-hosting easily.