brook


brook

Brook 是一个跨平台的微框架,有助于开发由 Delphi 或 Lazarus IDE 和 Free Pascal 构建的 Web Pascal 应用程序。它的核心是使用 Sagui 库开发的,这就是它在嵌入式系统上运行如此快速、紧凑和有用的原因。

https://github.com/risoflora/brookframework

Sagui 库下载:https://github.com/risoflora/libsagui/releases

服务端:

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 
 *
 * 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 
 *
 * 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.

相关