Getting Started

Following document explains minimum steps required to setup a working Fano web application on development machine.

Requirement

Create application

Make sure all requirements above are met. Run

$ fanocli --project-http=Hello
$ cd Hello
$ fanocli --controller=Home --route=/
$ ./build.sh
$ ./bin/app.cgi

Run it from browser

Open web browser and go to http://localhost:20477. You should see Home controller text is printed in browser. Congratulations, your application is working.

Following video shows step by step creating HTTP web application project.

Getting Started with Fano Framework video

Command walkthrough

Let us take a look at each command above to understand what it does.

Following command tells Fano CLI to create http web application project in Hello directory. Directory must not exist. Read Creating Project with Fano CLI for creating different web application project (CGI, FastCGI, SCGI, uwsgi or http).

$ fanocli --project-http=Hello

We change active directory to newly created Hello directory.

$ cd Hello

Create controller name HomeController.pas that will handle request to route /. For more information regarding route, read Working with Router.

$ fanocli --controller=Home --route=/

Without --route=/, by default, Fano CLI will create route same as lower case of controller’s name, i.e, /home. If you omit --route=/ then you can only access HomeController using URL http://localhost:20477/home instead of http://localhost:20477.

Compile application

$ ./build.sh

Run application

$ ./bin/app.cgi

By default, generated executable will have name app.cgi inside bin directory.

Project directory walkthrough

Fano Framework has no opinion about your project directory structure. You can structure your project directories and files the way you like. However, Fano CLI creates several files and directories that follows certain assumptions.

Directories

  • src, application project source code directory
  • bin, compiled binaries output directory,
  • config, application configuration directory
  • resources, application resources directory, such as HTML templates, SCSS, etc.
  • storages, application runtime-generated files directory, such as session files, logs etc.
  • tools, helper shell scripts directory, such as scripts to clean compiled binaries.
  • public, application document root directory where public resources resides such as images, cascade stylesheets, JavaScripts files.

Files

  • Main program source code is src/app.pas.
  • Main unit src/bootstrap.pas glues all modules.
  • Home controller HomeController.pas in src/App/Home/Controllers is code that prints Home controller text.
  • Include file src/Routes/Home/route.inc associates default URL / with home controller.
  • Include file controllers.dependencies.inc in src/Dependencies directory, registers factory class for home controller.

src/app.pas

This is typical main program source code of web application which is generated by Fano CLI (comments are omitted for brevity).

program app;

uses

    {$IFDEF UNIX}
    cthreads,
    {$ENDIF}
    sysutils,
    fano,
    bootstrap;

var
    appInstance : IWebApplication;
    cliParams : ICliParams;
    svrConfig : TFpwebSvrConfig;

begin
    cliParams := (TGetOptsParams.create() as ICliParamsFactory)
        .addOption('host', 1)
        .addOption('port', 1)
        .build();
    svrConfig.host := cliParams.getOption('host', '127.0.0.1');
    svrConfig.port := cliParams.getOption('port', 20477);
    writeln('Starting application at ', svrConfig.host, ':', svrConfig.port);

    svrConfig.documentRoot := getCurrentDir() + '/public';
    svrConfig.serverName := 'http.fano';
    svrConfig.serverAdmin := 'admin@http.fano';
    svrConfig.serverSoftware := 'Fano Framework Web App';
    svrConfig.timeout := 120;

    //uncomment following lines support https
    //svrConfig.useTLS := true;
    //svrConfig.tlsKey := '/path/to/ssl/cert/key';
    //svrConfig.tlsCert := '/path/to/ssl/cert/cert';

    appInstance := TDaemonWebApplication.create(
        TFpwebAppServiceProvider.create(
            TAppServiceProvider.create(),
            svrConfig
        ),
        TAppRoutes.create()
    );
    appInstance.run();
end.

Main program creates web application instance and service provider instances to build all services that your application required and then run it.

TDaemonWebApplication and TFpWebAppServiceProvider are built-in classes provided by Fano Framework to support creation of long-running http web application that uses Free Pascal Fpweb http server library.

Depending on parameter you use for creating project with Fano CLI, it may end up using TIndyAppServiceProvider, TMhdAppServiceProvider, TFastCgiAppServiceProvider, TScgiAppServiceProvider, TUwsgiAppServiceProvider for http web application based on Indy http server, libmicrohttpd http server, FastCGI, SCGI, uwsgi web application respectively.

TAppServiceProvider and TAppRoutes are two classes that specific to your application which are responsible for creating all services and routes required by your application. Both are declared in unit bootstrap.pas

src/bootstrap.pas

This typical file is generated by Fano CLI (comments are omitted for brevity) to allow application to initialize all services and routes it requires.

unit bootstrap;

interface

uses

    fano;

type

    TAppServiceProvider = class(TDaemonAppServiceProvider)
    protected

    public
        procedure register(const container : IDependencyContainer); override;
    end;

    TAppRoutes = class(TRouteBuilder)
    public
        procedure buildRoutes(
            const container : IDependencyContainer;
            const router : IRouter
        ); override;
    end;

implementation

uses
    sysutils,
    HomeControllerFactory;



    procedure TAppServiceProvider.register(const container : IDependencyContainer);
    begin
        {$INCLUDE Dependencies/dependencies.inc}
    end;

    procedure TAppRoutes.buildRoutes(
        const container : IDependencyContainer;
        const router : IRouter
    );
    begin
        {$INCLUDE Routes/routes.inc}
    end;
end.

TAppServiceProvider is class implements IServiceProvider interface which has one method name register(). It will be invoked by Fano Framework during intialization and will receive instance of dependency container. In this method, you initialize all services required by your application. TAppServiceProvider inherits from TDaemonAppServiceProvider which setups common services for long-running web application.

TAppRoutes is class implements IRouteBuilder interface which has one method buildRoutes() to implements. It inherits from TRouteBuilder, an abstract class implements this interface. Application builds routes in buildRoutes() method.

To simplify creating this file, Fano CLI uses two main include files dependencies.inc and routes.inc.

src/Dependencies/dependencies.inc

Following snippets shows typical content of this file (comments are ommited for brevity). Each lines are include files specific for certain purpose.

{$INCLUDE main.dependencies.inc}
{$INCLUDE middlewares.dependencies.inc}
{$INCLUDE models.dependencies.inc}
{$INCLUDE views.dependencies.inc}
{$INCLUDE controllers.dependencies.inc}

For example in controllers.dependencies.inc you may have following code

container.add('homeController', THomeControllerFactory.create());

which register factory class for home controller using key homeController.

src/Routes/routes.inc

This is typical routes file generated by Fano CLI as shown below.

{$INCLUDE Home/routes.inc}

Which in turns include other files. For example src/Routes/Home/routes.inc may have following code.

router.get('/', container.get('homeController') as IRequestHandler);

Above code registers route / with GET method to instance of home controller.

src/App/Home/Controllers/HomeController.pas

This typical controller code generated by Fano CLI (comments are omitted for brevity). It inherits from TAbstractController which is an abstract class implements IRequestHandler interface that has one method handleRequest().

unit HomeController;

interface

{$MODE OBJFPC}
{$H+}

uses

    fano;

type

    THomeController = class(TAbstractController)
    public
        function handleRequest(
            const request : IRequest;
            const response : IResponse;
            const args : IRouteArgsReader
        ) : IResponse; override;
    end;

implementation

    function THomeController.handleRequest(
        const request : IRequest;
        const response : IResponse;
        const args : IRouteArgsReader
    ) : IResponse;
    begin
        response.body().write('Home controller');
        result := response;
    end;

end.

When Internet browser request routes /, handleRequest() method is invoked which prints Home controller in browser.

handleRequest() method receives request, response and route argument instance you can use, for example, to read query string parameter.

Explore more