方小清 發表於 2022-2-22 19:04:00

brookframework

<p>brookframework</p>
<p>首先必须了解一下<strong>Sagui</strong> 是一个跨平台的 C 库,有助于开发 Web 服务器或框架。它的核心是使用 GNU libmicrohttpd、uthash、PCRE2、ZLib 和 GnuTLS 开发的,这就是它在嵌入式系统上运行如此快速、紧凑和有用的原因。</p>
<p>Sagui 编译好的库下载:https://github.com/risoflora/libsagui/releases</p>
<p>提供有FOR WINDOWS和FOR LINUX的库下载。</p>
<p><strong>Sagui特性:</strong></p>
<ul dir="auto">
<li>Requests processing through:
<ul dir="auto">
<li>Event-driven - single-thread + polling.</li>
<li>Threaded - one thread per request.</li>
<li>Polling - pre-allocated threads.</li>
<li>Isolated request - request processed outside main thread.</li>
</ul>
</li>
<li>High-performance path routing that supports:
<ul dir="auto">
<li>Regular expressions using&nbsp;PCRE2&nbsp;syntax.</li>
<li>Just-in-time optimization (JIT).</li>
<li>Binary search in path entry-points.</li>
</ul>
</li>
<li>HTTP compression:
<ul dir="auto">
<li>Deflate&nbsp;for static contents and streams compression.</li>
<li>Gzip&nbsp;for files compression.</li>
</ul>
</li>
<li>HTTPS support:
<ul dir="auto">
<li>TLS 1.3 through&nbsp;GnuTLS&nbsp;library.</li>
</ul>
</li>
<li>Dual stack:
<ul dir="auto">
<li>Single socket for IPv4 and IPv6 support.</li>
</ul>
</li>
<li>Basic authentication:
<ul dir="auto">
<li>For standard login using&nbsp;<em>user name/password</em>.</li>
</ul>
</li>
<li>Upload/download streaming by:
<ul dir="auto">
<li>Payload - for raw data transferring as JSON, XML and other.</li>
<li>File - for large data transferring as videos, images, binaries and so on.</li>
</ul>
</li>
<li>Mathematical expression evaluator:
<ul dir="auto">
<li>Arithmetic, bitwise and logical operators.</li>
<li>Variables allocation at build and/or run time.</li>
<li>Macro support to define functions at run time.</li>
<li>Extendable with custom functions.</li>
<li>Error handling with error kind and position.</li>
</ul>
</li>
<li>Dynamic strings:
<ul dir="auto">
<li>Makes it easy strings operations in C.</li>
</ul>
</li>
<li>String map:
<ul dir="auto">
<li>Fast key-value mapping.</li>
</ul>
</li>
<li>And more:
<ul dir="auto">
<li>Fields, parameters, cookies, headers under hash table structure.</li>
<li>Several callbacks for total library customization.</li>
</ul>
</li>
</ul>
<p>BrookFramework 是一个跨平台的微框架,支持 Delphi 或 Lazarus&nbsp; 构建跨平台的开发框架。它的核心是使用 Sagui 库开发的,这就是它在嵌入式系统上运行如此快速、紧凑和有用的原因。</p>
<p>BrookFramework开源地址:https://github.com/risoflora/brookframework</p>
<p dir="auto">Successfully tested on:</p>
<ul dir="auto">
<li>Windows</li>
<li>Linux</li>
<li>Raspbian/Android</li>
</ul>
<p dir="auto">compiled using:</p>
<ul dir="auto">
<li>Delphi XE family (Rio)</li>
<li>Lazarus / Free Pascal (Lazarus 2.0+ / FPC 3.2+)</li>
</ul>
<p>服务端:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">uses
BrookHTTPRequest,
BrookHTTPResponse,
BrookHTTPServer,
Persistence;

type
THTTPServer </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TBrookHTTPServer)
</span><span style="color: rgba(0, 0, 255, 1)">protected</span><span style="color: rgba(0, 0, 0, 1)">
    procedure DoRequest(ASender: TObject; ARequest: TBrookHTTPRequest;
      AResponse: TBrookHTTPResponse); </span><span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)">;
end;

procedure THTTPServer.DoRequest(ASender: TObject; ARequest: TBrookHTTPRequest;
AResponse: TBrookHTTPResponse);
begin
</span><span style="color: rgba(0, 0, 255, 1)">if</span> ARequest.Payload.Length &gt; <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)"> then
    SavePersons(ARequest.Payload.Content)
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
    AResponse.SendStream(ListPersons, </span><span style="color: rgba(128, 0, 128, 1)">200</span><span style="color: rgba(0, 0, 0, 1)">);
end;

begin
with THTTPServer.Create(nil) </span><span style="color: rgba(0, 0, 255, 1)">do</span>
<span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
    Port :</span>= <span style="color: rgba(128, 0, 128, 1)">8080</span><span style="color: rgba(0, 0, 0, 1)">;
    Open;
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> not Active then
      Exit;
    WriteLn(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Server running at http://localhost:</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, Port);
    ReadLn;
</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">
    Free;
end;</span></pre>
</div>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>(*<span style="color: rgba(0, 0, 0, 1)">   _                     _
</span>*| |___ __ ___   ___ | |<span style="color: rgba(0, 0, 0, 1)"> __
</span>*| <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">_ \| </span><span style="color: rgba(128, 0, 0, 1)">'</span>__/ _ \ / _ \| |/ /
*| |_) | | | (_) | (_) |   &lt;
*|_.__/|_|\___/ \___/|_|<span style="color: rgba(0, 0, 0, 1)">\_\
</span>*
*<span style="color: rgba(0, 0, 0, 1)"> Microframework which helps to develop web Pascal applications.
</span>*
* Copyright (c) <span style="color: rgba(128, 0, 128, 1)">2012</span>-<span style="color: rgba(128, 0, 128, 1)">2021</span> Silvio Clecio &lt;silvioprog@gmail.com&gt;
*
* Brook framework <span style="color: rgba(0, 0, 255, 1)">is</span> free software; you can redistribute it and/<span style="color: rgba(0, 0, 0, 1)">or
</span>*<span style="color: rgba(0, 0, 0, 1)"> modify it under the terms of the GNU Lesser General Public
</span>* License <span style="color: rgba(0, 0, 255, 1)">as</span><span style="color: rgba(0, 0, 0, 1)"> published by the Free Software Foundation; either
</span>* version <span style="color: rgba(128, 0, 128, 1)">2.1</span><span style="color: rgba(0, 0, 0, 1)"> of the License, or (at your option) any later version.
</span>*
* Brook framework <span style="color: rgba(0, 0, 255, 1)">is</span> distributed <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> the hope that it will be useful,
</span>*<span style="color: rgba(0, 0, 0, 1)"> but WITHOUT ANY WARRANTY; without even the implied warranty of
</span>*<span style="color: rgba(0, 0, 0, 1)"> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
</span>* Lesser General Public License <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> more details.
</span>*
*<span style="color: rgba(0, 0, 0, 1)"> You should have received a copy of the GNU Lesser General Public
</span>* License along with Brook framework; <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> not, write to the Free Software
</span>* Foundation, Inc., <span style="color: rgba(128, 0, 128, 1)">51</span> Franklin Street, Fifth Floor, Boston, MA<span style="color: rgba(128, 0, 128, 1)">02110</span>-<span style="color: rgba(128, 0, 128, 1)">1301</span><span style="color: rgba(0, 0, 0, 1)">USA
</span>*<span style="color: rgba(0, 0, 0, 1)">)

unit Persistence;

</span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)">

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(</span><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> ABytes: TBytes);

implementation

</span><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)">
SQL_SELECT_PERSONS </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM persons</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
SQL_INSERT_PERSONS </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">INSERT INTO persons (name) VALUES (:name)</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
DBConnection: TFDConnection;

procedure CreateAndConfigureDBConnection;
begin
DBConnection :</span>=<span style="color: rgba(0, 0, 0, 1)"> TFDConnection.Create(nil);
DBConnection.DriverName :</span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SQLite</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
DBConnection.Params.Database :</span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">../../../DB/DataBase.sqlite3</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
end;

procedure DestroyDBConnection;
begin
FreeAndNil(DBConnection);
end;

function CreateQuery(</span><span style="color: rgba(0, 0, 255, 1)">const</span> ASelectSQL: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">const</span> AInsertSQL: <span style="color: rgba(0, 0, 255, 1)">string</span> = <span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)">): TFDQuery;
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
VUpdate: TFDUpdateSQL;
begin
Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> TFDQuery.Create(nil);
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> not AInsertSQL.IsEmpty then
begin
    VUpdate :</span>=<span style="color: rgba(0, 0, 0, 1)"> TFDUpdateSQL.Create(Result);
    VUpdate.Connection :</span>=<span style="color: rgba(0, 0, 0, 1)"> DBConnection;
    VUpdate.InsertSQL.Text :</span>=<span style="color: rgba(0, 0, 0, 1)"> AInsertSQL;
    Result.UpdateObject :</span>=<span style="color: rgba(0, 0, 0, 1)"> VUpdate;
end;
Result.Connection :</span>=<span style="color: rgba(0, 0, 0, 1)"> DBConnection;
Result.CachedUpdates :</span>=<span style="color: rgba(0, 0, 0, 1)"> True;
Result.SQL.Text :</span>=<span style="color: rgba(0, 0, 0, 1)"> ASelectSQL;
end;

function ListPersons: TStream;
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
VQuery: TFDQuery;
begin
Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> TBytesStream.Create;
VQuery :</span>=<span style="color: rgba(0, 0, 0, 1)"> CreateQuery(SQL_SELECT_PERSONS);
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
    VQuery.Open;
    VQuery.SaveToStream(Result, sfBinary);
    Result.Seek(</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, TSeekOrigin.soBeginning);
</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">
    VQuery.Destroy;
end;
end;

procedure SavePersons(</span><span style="color: rgba(0, 0, 255, 1)">const</span><span style="color: rgba(0, 0, 0, 1)"> ABytes: TBytes);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
VQuery: TFDQuery;
VData: TBytesStream;
begin
VQuery :</span>=<span style="color: rgba(0, 0, 0, 1)"> CreateQuery(SQL_SELECT_PERSONS, SQL_INSERT_PERSONS);
VData :</span>=<span style="color: rgba(0, 0, 0, 1)"> TBytesStream.Create(ABytes);
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
    VQuery.LoadFromStream(VData, sfBinary);
    VQuery.ApplyUpdates;
    DBConnection.Commit;
</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">
    VQuery.Destroy;
    VData.Free;
end;
end;

initialization
CreateAndConfigureDBConnection;

finalization
DestroyDBConnection;

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

unit Client;

</span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)">

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

function NewGuid: </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
function ListPersons(</span><span style="color: rgba(0, 0, 255, 1)">const</span> AURL: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">): TDataSet;
procedure SavePersons(</span><span style="color: rgba(0, 0, 255, 1)">const</span> AURL: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">; ADataSet: TDataSet);
function CreatePersonsDataSet: TDataSet;

implementation

function NewGuid: </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
begin
Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> TGuid.NewGuid.ToString;
end;

function CreateDataSet: TFDMemTable;
begin
Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> TFDMemTable.Create(nil);
Result.CachedUpdates :</span>=<span style="color: rgba(0, 0, 0, 1)"> True;
end;

function ListPersons(</span><span style="color: rgba(0, 0, 255, 1)">const</span> AURL: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">): TDataSet;
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
VClient: THTTPClient;
begin
Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> CreateDataSet;
VClient :</span>=<span style="color: rgba(0, 0, 0, 1)"> THTTPClient.Create;
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
    TFDMemTable(Result).LoadFromStream(VClient.Get(AURL).ContentStream, sfBinary);
</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">
    VClient.Free;
end;
end;

procedure SavePersons(</span><span style="color: rgba(0, 0, 255, 1)">const</span> AURL: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">; ADataSet: TDataSet);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
VClient: THTTPClient;
VData: TStream;
begin
</span><span style="color: rgba(0, 0, 255, 1)">if</span> ADataSet.State <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> dsEditModes then
    ADataSet.Post;
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
    VData :</span>=<span style="color: rgba(0, 0, 0, 1)"> TBytesStream.Create;
    VClient :</span>=<span style="color: rgba(0, 0, 0, 1)"> THTTPClient.Create;
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
      TFDMemTable(ADataSet).SaveToStream(VData, sfBinary);
      VData.Seek(</span><span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, TSeekOrigin.soBeginning);
      VClient.Post(AURL, VData);
    </span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">
      VClient.Free;
      VData.Free;
    end;
</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">
    FreeAndNil(ADataSet);
end;
end;

function CreatePersonsDataSet: TDataSet;
begin
Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> CreateDataSet;
Result.FieldDefs.Add(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">'</span>, ftString, <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">);
TFDMemTable(Result).CreateDataSet;
end;

end.</span></pre>
</div>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/15924526.html</p><br><br>
来源:https://www.cnblogs.com/hnxxcxg/p/15924526.html
頁: [1]
查看完整版本: brookframework