mormot1.18 THttpApiServer
mormot1.18 THttpApiServer
官方已经推荐使用mormot2,mormot1.18已经进入只修正bug的阶段。
THttpApiServer是对windows http.sys通信的封装,因此只适用于windows。
//cxg 2023-2-12
//mormot1.18 http.sys 适用于WINDOWS2003,XP SP2及以后版本
unit sock.httpsys;
interface
uses
System.JSON, Json.help, keyValue.serialize, api.router,
inifiles, SynCrtSock, Classes, SysUtils;
var
BinApis: TJSONObject; //二进制API
RestApis: TJSONObject; //REST API,包括json,protobuf
const //content-type
cBin = 'application/octet-stream; charset=utf-8';
cJson = 'application/json; charset=utf-8';
cProtobuf = 'application/protobuf; charset=utf-8';
type
THttpsys = class
private
fServer: THttpApiServer;
function Process(Ctxt: THttpServerRequest): Cardinal;
public
constructor Create;
destructor Destroy; override;
end;
implementation
function strof(const aBytes: TBytes): RawByteString; overload;
begin
SetLength(Result, Length(aBytes));
Move(aBytes[0], Result[1], Length(aBytes));
end;
function ReadJsonFile(const FileName: string): string;
begin
var f: TStringList := TStringList.Create;
f.LoadFromFile(FileName, TEncoding.UTF8);
Result := f.Text;
f.Free;
end;
procedure setHeader(const Ctxt: THttpServerRequest; const ContentType: string);
begin
Ctxt.OutContentType := ContentType;
Ctxt.OutCustomHeaders := 'Access-Control-Allow-Origin:*' + #13#10 + 'Access-Control-Allow-Methods:*' + #13#10 + 'Access-Control-Allow-Headers:*';
end;
procedure router(const Ctxt: THttpServerRequest);
begin
if Pos('/bin', Ctxt.URL) > 0 then //二进制 API
begin
setHeader(Ctxt, cBin);
var req: TSerialize := tserialize.Create;
var res: TSerialize := tserialize.Create;
if Ctxt.InContent > '' then
req.unMarshal(Ctxt.InContent);
var url: string := Ctxt.URL;
var arr: TArray<string> := url.Split(['/']);
var funcName: string := arr[2];
var ja: TJSONArray := BinApis.A['bin'];
for var i: Integer := 0 to ja.Count - 1 do
begin
var o: TJSONObject := ja.Items[i] as TJSONObject;
if o.S['funcname'] = funcName then
begin
RouterAPI(o.S['classname'], o.S['funcname'], [req, res]);
Break;
end;
end;
Ctxt.OutContent := res.marshal3;
req.Free;
res.Free;
end
else if Pos('/rest', Ctxt.URL) > 0 then //JSON API
begin
setHeader(Ctxt, cJson);
var url: string := Ctxt.URL;
var arr: TArray<string> := url.Split(['/']);
var resource: string := arr[2];
var req: TSerialize := tserialize.Create;
var res: TSerialize := tserialize.Create;
req.asStr['url'] := url;
if Ctxt.InContent > '' then
req.asStr['body'] := Ctxt.InContent;
req.asStr['type'] := 'json';
var ja: TJSONArray := RestApis.A[resource];
for var i: Integer := 0 to ja.Count - 1 do
begin
var o: TJSONObject := ja.Items[i] as TJSONObject;
if o.S['method'] = Ctxt.Method then
begin
RouterAPI(o.S['classname'], o.S['funcname'], [req, res]);
Break;
end;
end;
Ctxt.OutContent := UTF8Encode(res.asStr['res']);
req.Free;
res.Free;
end
else if Pos('/protobuf', Ctxt.URL) > 0 then //PROTOBUF API
begin
setHeader(Ctxt, cProtobuf);
var url: string := Ctxt.URL;
var arr: TArray<string> := url.Split(['/']);
var resource: string := arr[2];
var req: TSerialize := tserialize.Create;
var res: TSerialize := tserialize.Create;
req.asStr['url'] := url;
if Ctxt.InContent > '' then
req.asBytes['body'] := BytesOf(Ctxt.InContent);
req.asStr['type'] := 'protobuf';
var ja: TJSONArray := RestApis.A[resource];
for var i: Integer := 0 to ja.Count - 1 do
begin
var o: TJSONObject := ja.Items[i] as TJSONObject;
if o.S['method'] = Ctxt.Method then
begin
RouterAPI(o.S['classname'], o.S['funcname'], [req, res]);
Break;
end;
end;
Ctxt.OutContent := strof(res.asBytes['res']);
req.Free;
res.Free;
end;
end;
{ THttpsys }
function THttpsys.Process(Ctxt: THttpServerRequest): Cardinal;
begin
router(Ctxt);
Result := 200;
end;
constructor THttpsys.Create;
var
ini: tinifile;
httpport: string;
threadnum: integer;
ssl: Boolean;
begin
ini := tinifile.create(extractfilepath(paramstr(0)) + 'server.conf');
httpport := ini.readstring('config', 'httpport', '1122');
threadnum := ini.readinteger('config', 'threadnum', 32);
if threadnum > 256 then
threadnum := 256;
ssl := ini.ReadBool('config', 'ssl', False);
fServer := THttpApiServer.Create(False);
if not ssl then
fServer.AddUrl('', httpport, False, '+', True)
else
fServer.AddUrl('', httpport, True, '+', True);
fServer.OnRequest := Process;
fServer.Clone(threadnum);
ini.free;
{$IFDEF console}
Writeln('New http.sys server');
Writeln('Http port: ', httpport);
Writeln('Thread num: ', threadnum);
{$ENDIF}
end;
destructor THttpsys.Destroy;
begin
inherited Destroy;
end;
initialization
binapis := TJSONObject.Create;
restapis := TJSONObject.Create;
binapis.Parse(ReadJsonFile(ExtractFilePath(ParamStr(0)) + 'binrouter.json'));
restapis.Parse(ReadJsonFile(ExtractFilePath(ParamStr(0)) + 'restrouter.json'));
finalization
FreeAndNil(binapis);
FreeAndNil(restapis);
end.
本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/17483231.html

浙公网安备 33010602011771号