Habari Web Components 2.12 released

Habari Web Components is a web application framework for small to medium size HTTP services, based on the popular open source TCP/IP library for Delphi and Free Pascal, Internet Direct (Indy).

Continue reading “Habari Web Components 2.12 released”

Advertisements

Habari Web Components 2.11 released

Habari Web Components is a web application framework for small to medium size HTTP services, based on the popular open source TCP/IP library for Delphi and Free Pascal, Internet Direct (Indy).

Online demo:  the online demo on https://secure.habariwebcomponents.de/demo/index.html runs on a Ubuntu Linux system (please note that Linux is not officially supported).

Demo download: The demo download contains documentation, tutorial project sources and the “Flightplan” executable demo which uses jQuery mobile.

Mobile app demo

 

Habari Web Components

A RESTful CRUD demo application with Delphi

Habari Web Components is a web application framework for small to medium size HTTP services, based on the Internet Direct (Indy) library.

A new demo application – included with full source code in demo/restful-crud – exposes a RESTful API which supports HTTP GET / POST / DELETE commands to read, create and delete data.

The source code below shows the configuration code for the RESTful API. Every request handler is bound to a resource address, document type (MIME type), and HTTP method.

Note that PUT is not yet implemented in the API because web browsers do not support HTTP PUT in HTML forms. For HTTP DELETE, the web interface uses a Javascript-based workaround to delete a resource.


procedure TMyRestfulComponent.Init(const Config:
            IWebComponentConfig);
begin
  inherited; // always call inherited.Init

  // GET http://localhost/rest/persons
  // list all persons
  &Path('persons');
  Produces('text/html');
  GET(procedure(Request: TRequest; Response: TResponse)
  begin
    Response.ContentText := CRUDModule.GetPersons;
    Response.CharSet := 'UTF-8';
  end);

  // POST http://localhost/rest/persons
  // add new person
  &Path('persons');
  Produces('text/html');
  POST(procedure(Request: TRequest; Response: TResponse)
  var
    Name: string;
    Person: TPerson;
  begin
    Name := UTF8Decode(Request.Params.Values['name']);
    Person := TPerson.Create(CRUDModule.NextID, Name);
    CRUDModule.SavePerson(Person);
    Response.Redirect(Request.Document);
  end);

  // PUT http://localhost/rest/persons/{id}
  // update person
  &Path('persons/{id}');
  Produces('text/html');
  PUT(procedure(Request: TRequest; Response: TResponse)
  var
    ID: string;
  begin
    ID := Request.Params.Values['id'];
    // TODO
  end);

  // DELETE http://localhost/rest/persons/{id}
  // delete person
  &Path('persons/{id}');
  Produces('text/html');
  DELETE(procedure(Request: TRequest; Response: TResponse)
  var
    ID: string;
  begin
    ID := Request.Params.Values['id'];
    CRUDModule.DeletePerson(StrToInt(ID));
  end);

  // GET http://localhost/rest/persons/{id}
  // get person information
  &Path('persons/{id}');
  Produces('text/html');
  GET(procedure(Request: TRequest; Response: TResponse)
  var
    ID: string;
  begin
    ID := Request.Params.Values['id'];
    Response.ContentText := CRUDModule.GetPerson(StrToInt(ID));
    Response.CharSet := 'UTF-8';
  end);
end;

Habari Web Components

Habari Web Components 2.7b1 – RFC 5789 and RESTful web applications

Habari Web Components is a web application framework for small to medium size HTTP services, based on the popular open source TCP/IP library for Delphi and Free Pascal, Internet Direct (Indy).

Changes in 2.7(beta1):

TdjRestfulComponent
The demo folder /restful contains the TdjRestfulComponent, a small example implementation of a RESTful framework which integrates with Habari Web Components (requires Indy 10.6 rev 50880 or newer)
HTTP PATCH (RFC 5789) support
PATCH is a new HTTP method to support partial resource updates in RESTful applications, it is defined in RFC 5789. Custom web components can now implement OnPATCH methods in addition to the existing request handlers OnGET, OnPOST etc. (TdjRestfulComponent also allows to register a PATCH resource handler)

Changes in version 2.6

Online demo:  the “Kitchen Sink” online demo on http://www.habariwebcomponents.de/demo/index.html runs on a Ubuntu Linux system and shows examples, which are also included in the demo download (note that Linux is not officially supported yet).

Habari Web Components

Habari Web Components 2.6 released

Habari Web Components is a web application framework for small to medium size HTTP services, based on the popular open source TCP/IP library for Delphi and Free Pascal, Internet Direct (Indy).

Changes in 2.6:

DataModule per session
New demo application which shows how a TDataModule instance can be stored in a session
Form based authentication
New example for HTML form based authentication
On-demand sessions
Helper method GetSession moved from class TdjWebComponentContextHandler to class TdjHandlerWrapper to make it more widely available
Statistics handler
Statistics handler demo class uses atomic (thread safe) variables
NCSA logging example
Improved NCSA logging handler example class

Stand-alone demo applications included in demo download: Kitchen sink, Flight Plan (jQuery mobile), Datamodule.

Online demo:  the “Kitchen Sink” online demo on http://www.habariwebcomponents.de/demo/index.html runs on a Ubuntu Linux system and shows many examples, which are also included in the demo download (Linux is not officially supported yet).

Save 40 €: the new price for the Single Developer License includes one year free updates, source code, a non-exclusive life-time license, free redistribution with your product and a 60 day money back guarantee.

Habari Web Components

Habari Web Components: TDatamodule per Session

This program for Habari Web Components demonstrates how the internal Indy HTTP server instance can be used to hold custom data objects in memory for the duration of a HTTP session. Update: the code and a compiled application is now included in the demo download.

It also shows how the datamodule instance can be removed automatically when its session ends.

When run, the demo application will display a list of names (populated with some example values) and a HTML form which allows to enter another name and send it to the server.

HTML page

For every client session, the server will create and use a separate instance of the datamodule. You can verify this with different browsers, or with private mode browser windows.

The executable and the project source are available at http://cc.embarcadero.com/Item/28784

The Datamodule class

The Datamodule in this example acts as a container for people names stored in a TStrings object. This people list is accessible as a property with public visibility.

unit DemoDataMod;

  ...

  TDemoDataModule = class(TDataModule)
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
  private
    FPeople: TStrings;
  public
    property People: TStrings read FPeople;
  end;

TDemoDataModule.DataModuleCreate creates an instance of TStringList, assigns it to the internal FPeople field, and adds some example data.
TDemoDataModule.DataModuleDestroy frees the TStringList instance. (Note that the datamodule has to be destroyed also when its owning session ends, this will be shown in the next section).

procedure TDemoDataModule.DataModuleCreate(Sender: TObject);
begin
  FPeople := TStringlist.Create;

  People.Add('Alice');
  People.Add('Bob');
  People.Add('Homer');
end;

procedure TDemoDataModule.DataModuleDestroy(Sender: TObject);
begin
  People.Free;
end;

The Web Component class

The Web Component interface uses the handlers for HTTP GET and POST requests, to route them to our own “catch-all” handler OnHandleRequest. This handler will process both the initial GET request (when the client navigates to the page) and all POST requests when the client submits the HTML form.

unit DataFormCmp;

  ...

  TDataFormPage = class(TdjWebComponent)
  private
    procedure OnHandleRequest(Request: TIdHTTPRequestInfo;
      Response: TIdHTTPResponseInfo);
  public
    procedure OnGet(Request: TIdHTTPRequestInfo; Response:
      TIdHTTPResponseInfo); override;
    procedure OnPost(Request: TIdHTTPRequestInfo; Response:
      TIdHTTPResponseInfo); override;
  end;

  ...

procedure TDataFormPage.OnGet(Request: TIdHTTPRequestInfo;
  Response: TIdHTTPResponseInfo);
begin
  OnHandleRequest(Request, Response);
end;

procedure TDataFormPage.OnPost(Request: TIdHTTPRequestInfo;
  Response: TIdHTTPResponseInfo);
begin
  OnHandleRequest(Request, Response);
end;

In OnHandleRequest, the datamodule either will be created and stored in the session if it does not exist or it will be retrieved from the session:

procedure TDataFormPage.OnHandleRequest(Request:
  TIdHTTPRequestInfo; Response: TIdHTTPResponseInfo);
const
  KEY = 'datamodule';
var
  Pos: Integer;
  DM: TDemoDataModule;
  Tmp: string;
  S: string;
begin
  Request.Session.Lock;
  try
    Pos := Request.Session.Content.IndexOf(KEY);
    if Pos <> -1 then
    begin
    DM := TDemoDataModule(Request.Session.Content.Objects[Pos]);
    end
    else
    begin
      WriteLn(Format('Create datamodule for session %s',
       [Request.Session.SessionID]));
      DM := TDemoDataModule.Create(nil);
      Request.Session.Content.AddObject(KEY, DM);
    end;
  finally
    Request.Session.Unlock;
  end;

If it is a POST request, the value of the input field will be extracted and added to the people list:

  if Request.CommandType = hcPOST then
  begin
    S := Utf8ToString(RawByteString(
           Request.Params.Values['textfield1']));
    if S <> '' then
    begin
      DM.People.Add(S);
    end;
  end;

We have all that is needed to build the HTML response now:

  • a reference to the datamodule instance which belongs to this session
  • the name which has been POSTed from the client is in the people list

Finally, the OnHandleRequest handler creates the HTML response. The names stored in the people list will be added to the HTML code (followed by the HTML form code, which is not shown here but included in the source code).

  Tmp := '<!DOCTYPE html>'

   ... // add HTML page code ...

  for S in DM.People do
  begin
    Tmp := Tmp + '  <p>' + S + '</p>' + #10;
  end;

  ... // more HTML page code ...

  Response.ContentText := Tmp;
  Response.ContentType := 'text/html';
  Response.CharSet := 'utf-8';

Housekeeping

In a server application, memory leaks would lead to out of memory errors sooner or later. Our code has to free the datamodule instance when the session ends. The Habari Web Component framework is build on top of Indy, so we can use the OnSessionEnd event of the internal TIdHTTPServer instance to do this. In the example project, we custom subclass of TdjHTTPConnector to add a handler for the OnSessionEnd event, and to set the session timeout to a lower value than the default.

program DataModuleDemo;

  ...

  TCleanUpConnector = class(TdjHTTPConnector)
  private
    procedure DoSessionCleanUp(Sender: TIdHTTPSession);
  public
    constructor Create(const Handler: IHandler); override;
  end;

{ TCleanUpConnector }

constructor TCleanUpConnector.Create(const Handler: IHandler);
begin
  inherited;

  HTTPServer.OnSessionEnd := DoSessionCleanUp;

  // 20 sec to demonstrate seesion cleanup
  HTTPServer.SessionTimeOut := 20000;
end;

procedure TCleanUpConnector.DoSessionCleanUp(Sender:
  TIdHTTPSession);
const
  KEY = 'datamodule';
var
  Pos: Integer;
begin
  Pos := Sender.Content.IndexOf(KEY);

  if (Pos <> -1) and Assigned(Sender.Content.Objects[Pos]) then
  begin
    WriteLn(Format('Destroy datamodule for session %s',
      [Sender.SessionID]));
    Sender.Content.Objects[Pos].Free;
  end
end;

Is it 100% thread safe?

Not yet: the People property of the datamodule is not protected against concurrent modificationss by different threads. This can cause problems when the client opens multiple connection to the server in the same session, and two connections read or write the People property.

Putting it all together

This excerpt of the demo project shows how the Web Component and the custom HTTP connector are wired in the Habari Web Components framework.

procedure Demo;
var
  Server: TdjServer;
  Connector: TdjHTTPConnector;
  Context: TdjWebAppContext;
begin
  Server := TdjServer.Create(8080);
  try
    Context := TdjWebAppContext.Create('demo', True);
    Context.Add(TDataFormPage, '/dataform.html');
    Server.Add(Context);

    Connector := TCleanUpConnector.Create(Server.Handler);

    Connector.Host := '127.0.0.1';
    Connector.Port := 8080;

    Server.AddConnector(Connector);

    SetShutdownHook(Server);

    Server.Start;

    // launch default web browser and navigate to dataform.html
    ShellExecute(0, 'open',
      'http://127.0.0.1:8080/demo/dataform.html', '', '', 0);
    WriteLn('Hit any key to terminate.');
    ReadLn;

  finally
    Server.Free;
  end;
end;

Server running

Habari Web Components 2.5 released

Habari Web Components is a web application framework for small to medium size HTTP services, based on the popular open source TCP/IP library for Delphi and Free Pascal, Internet Direct (Indy).

Changes in 2.5:

Free Pascal
Improved support for Free Pascal mixed compiler modes, the -Mdelphi compiler switch is no longer required.
Documentation
Additional documentation for unit tests and UTF-8 usage with Free Pascal, for the TdjStatisticsHandler class, and expected exceptions in unit tests.
Bootstrap
Upgraded example web pages to Bootstrap 3.0, jQuery to 1.10.2 and jQuery mobile to 1.3.2.
NCSA logger
NCSA logger example class can be used on Linux. Milliseconds have been removed from the output to follow the standard.
Demo
Minor fixes and improvements in the demo applications (for details please see the Getting Started documentation).

Stand-alone demo applications included in demo download: Kitchen sink, Flight Plan (jQuery mobile), Captcha.

Online demo:  the “Kitchen Sink” online demo on http://www.habariwebcomponents.de/demo/index.html runs on a Ubuntu Linux system and shows many examples, which are also included in the demo download (note that Linux is not officially supported yet).

Save 40 €: the new price for the Single Developer License includes one year free updates, source code, a non-exclusive life-time license, free redistribution with your product and a 60 day money back guarantee.

Habari Web Components

Habari Web Framework Demo for Android

Habari Web Components

Januar 31, 2013 – Habarisoft is pleased to announce the availability of its demo app for the Delphi and Free Pascal framework Habari Web Components. Habari Web Framework Demo 1.0 for Android contains a request statistics demo which uses HTTP and JSON to read the statistics of the demo server at http://www.habariwebcomponents.de/demo/index.html.

Get it on Google Play

Habar Web Framework Demo

The server statistics are also available in the online demo.

stats