brookframework

brookframework

首先必须了解一下Sagui 是一个跨平台的 C 库,有助于开发 Web 服务器或框架。它的核心是使用 GNU libmicrohttpd、uthash、PCRE2、ZLib 和 GnuTLS 开发的,这就是它在嵌入式系统上运行如此快速、紧凑和有用的原因。

Sagui 编译好的库下载:https://github.com/risoflora/libsagui/releases

提供有FOR WINDOWS和FOR LINUX的库下载。

Sagui特性:

  • Requests processing through:
    • Event-driven - single-thread + polling.
    • Threaded - one thread per request.
    • Polling - pre-allocated threads.
    • Isolated request - request processed outside main thread.
  • High-performance path routing that supports:
    • Regular expressions using PCRE2 syntax.
    • Just-in-time optimization (JIT).
    • Binary search in path entry-points.
  • HTTP compression:
    • Deflate for static contents and streams compression.
    • Gzip for files compression.
  • HTTPS support:
    • TLS 1.3 through GnuTLS library.
  • Dual stack:
    • Single socket for IPv4 and IPv6 support.
  • Basic authentication:
    • For standard login using user name/password.
  • Upload/download streaming by:
    • Payload - for raw data transferring as JSON, XML and other.
    • File - for large data transferring as videos, images, binaries and so on.
  • Mathematical expression evaluator:
    • Arithmetic, bitwise and logical operators.
    • Variables allocation at build and/or run time.
    • Macro support to define functions at run time.
    • Extendable with custom functions.
    • Error handling with error kind and position.
  • Dynamic strings:
    • Makes it easy strings operations in C.
  • String map:
    • Fast key-value mapping.
  • And more:
    • Fields, parameters, cookies, headers under hash table structure.
    • Several callbacks for total library customization.

BrookFramework 是一个跨平台的微框架,支持 Delphi 或 Lazarus  构建跨平台的开发框架。它的核心是使用 Sagui 库开发的,这就是它在嵌入式系统上运行如此快速、紧凑和有用的原因。

BrookFramework开源地址:https://github.com/risoflora/brookframework

Successfully tested on:

  • Windows
  • Linux
  • Raspbian/Android

compiled using:

  • Delphi XE family (Rio)
  • Lazarus / Free Pascal (Lazarus 2.0+ / FPC 3.2+)

服务端:

uses
  BrookHTTPRequest,
  BrookHTTPResponse,
  BrookHTTPServer,
  Persistence;

type
  THTTPServer = class(TBrookHTTPServer)
  protected
    procedure DoRequest(ASender: TObject; ARequest: TBrookHTTPRequest;
      AResponse: TBrookHTTPResponse); override;
  end;

procedure THTTPServer.DoRequest(ASender: TObject; ARequest: TBrookHTTPRequest;
  AResponse: TBrookHTTPResponse);
begin
  if ARequest.Payload.Length > 0 then
    SavePersons(ARequest.Payload.Content)
  else
    AResponse.SendStream(ListPersons, 200);
end;

begin
  with THTTPServer.Create(nil) do
  try
    Port := 8080;
    Open;
    if not Active then
      Exit;
    WriteLn('Server running at http://localhost:', Port);
    ReadLn;
  finally
    Free;
  end;

 

(*   _                     _
 *  | |__  _ __ ___   ___ | | __
 *  | '_ \| '__/ _ \ / _ \| |/ /
 *  | |_) | | | (_) | (_) |   <
 *  |_.__/|_|  \___/ \___/|_|\_\
 *
 * Microframework which helps to develop web Pascal applications.
 *
 * Copyright (c) 2012-2021 Silvio Clecio <silvioprog@gmail.com>
 *
 * Brook framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Brook framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Brook framework; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *)

unit Persistence;

interface

uses
  System.SysUtils,
  System.Classes,
  FireDAC.DApt,
  FireDAC.Stan.Def,
  FireDAC.Stan.Intf,
  FireDAC.Stan.Async,
  FireDAC.Phys.SQLite,
  FireDAC.Comp.Client,
  FireDAC.Stan.StorageBin;

function ListPersons: TStream;
procedure SavePersons(const ABytes: TBytes);

implementation

const
  SQL_SELECT_PERSONS = 'SELECT * FROM persons';
  SQL_INSERT_PERSONS = 'INSERT INTO persons (name) VALUES (:name)';

var
  DBConnection: TFDConnection;

procedure CreateAndConfigureDBConnection;
begin
  DBConnection := TFDConnection.Create(nil);
  DBConnection.DriverName := 'SQLite';
  DBConnection.Params.Database := '../../../DB/DataBase.sqlite3';
end;

procedure DestroyDBConnection;
begin
  FreeAndNil(DBConnection);
end;

function CreateQuery(const ASelectSQL: string;
  const AInsertSQL: string = ''): TFDQuery;
var
  VUpdate: TFDUpdateSQL;
begin
  Result := TFDQuery.Create(nil);
  if not AInsertSQL.IsEmpty then
  begin
    VUpdate := TFDUpdateSQL.Create(Result);
    VUpdate.Connection := DBConnection;
    VUpdate.InsertSQL.Text := AInsertSQL;
    Result.UpdateObject := VUpdate;
  end;
  Result.Connection := DBConnection;
  Result.CachedUpdates := True;
  Result.SQL.Text := ASelectSQL;
end;

function ListPersons: TStream;
var
  VQuery: TFDQuery;
begin
  Result := TBytesStream.Create;
  VQuery := CreateQuery(SQL_SELECT_PERSONS);
  try
    VQuery.Open;
    VQuery.SaveToStream(Result, sfBinary);
    Result.Seek(0, TSeekOrigin.soBeginning);
  finally
    VQuery.Destroy;
  end;
end;

procedure SavePersons(const ABytes: TBytes);
var
  VQuery: TFDQuery;
  VData: TBytesStream;
begin
  VQuery := CreateQuery(SQL_SELECT_PERSONS, SQL_INSERT_PERSONS);
  VData := TBytesStream.Create(ABytes);
  try
    VQuery.LoadFromStream(VData, sfBinary);
    VQuery.ApplyUpdates;
    DBConnection.Commit;
  finally
    VQuery.Destroy;
    VData.Free;
  end;
end;

initialization
  CreateAndConfigureDBConnection;

finalization
  DestroyDBConnection;

end.

 客户端:

(*   _                     _
 *  | |__  _ __ ___   ___ | | __
 *  | '_ \| '__/ _ \ / _ \| |/ /
 *  | |_) | | | (_) | (_) |   <
 *  |_.__/|_|  \___/ \___/|_|\_\
 *
 * Microframework which helps to develop web Pascal applications.
 *
 * Copyright (c) 2012-2021 Silvio Clecio <silvioprog@gmail.com>
 *
 * Brook framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Brook framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Brook framework; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *)

unit Client;

interface

uses
  System.SysUtils,
  System.Classes,
  Data.DB,
  System.Net.HTTPClient,
  FireDAC.Stan.Intf,
  FireDAC.Comp.Client,
  FireDAC.Stan.StorageBin;

function NewGuid: string;
function ListPersons(const AURL: string): TDataSet;
procedure SavePersons(const AURL: string; ADataSet: TDataSet);
function CreatePersonsDataSet: TDataSet;

implementation

function NewGuid: string;
begin
  Result := TGuid.NewGuid.ToString;
end;

function CreateDataSet: TFDMemTable;
begin
  Result := TFDMemTable.Create(nil);
  Result.CachedUpdates := True;
end;

function ListPersons(const AURL: string): TDataSet;
var
  VClient: THTTPClient;
begin
  Result := CreateDataSet;
  VClient := THTTPClient.Create;
  try
    TFDMemTable(Result).LoadFromStream(VClient.Get(AURL).ContentStream, sfBinary);
  finally
    VClient.Free;
  end;
end;

procedure SavePersons(const AURL: string; ADataSet: TDataSet);
var
  VClient: THTTPClient;
  VData: TStream;
begin
  if ADataSet.State in dsEditModes then
    ADataSet.Post;
  try
    VData := TBytesStream.Create;
    VClient := THTTPClient.Create;
    try
      TFDMemTable(ADataSet).SaveToStream(VData, sfBinary);
      VData.Seek(0, TSeekOrigin.soBeginning);
      VClient.Post(AURL, VData);
    finally
      VClient.Free;
      VData.Free;
    end;
  finally
    FreeAndNil(ADataSet);
  end;
end;

function CreatePersonsDataSet: TDataSet;
begin
  Result := CreateDataSet;
  Result.FieldDefs.Add('name', ftString, 100);
  TFDMemTable(Result).CreateDataSet;
end;

end.

 

posted @ 2022-02-22 19:04  delphi中间件  阅读(340)  评论(0编辑  收藏  举报