mormot2 THttpAsyncServer
支持delphi和lazarus。
/// <author>cxg 2023-2-12</author> /// mormot2 异步httpserver 支持delphi+lazarus unit sock.mormot2.httpserver; {$IFDEF fpc} {$MODE DELPHI}{$H+} {$ENDIF} interface uses classes, keyValue.serialize, api.router, IniFiles, mormot.Net.sock, SysUtils, system.JSON, json.help, mormot.net.async, mormot.net.http, mormot.net.server; 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 THttpSVR = class private FServer: THttpAsyncServer; function process(Ctxt: THttpServerRequestAbstract): cardinal; public constructor Create; destructor Destroy; override; end; implementation function ReadJsonFile(const FileName: string): string; begin var f: TStringList := TStringList.Create; f.LoadFromFile(FileName, TEncoding.UTF8); Result := f.Text; f.Free; end; function strof(const aBytes: TBytes): RawByteString; overload; begin SetLength(Result, Length(aBytes)); Move(aBytes[0], Result[1], Length(aBytes)); end; procedure setHeader(const Ctxt: THttpServerRequestAbstract; const ContentType: string); //mormot2 binary http header 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: THttpServerRequestAbstract); //mormot2 router 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; { THttpSVR } constructor THttpSVR.Create; var ini: tinifile; httpport: string; threadnum: integer; ssl: Boolean; KeepAliveTimeOut: Integer; queueLen: Integer; tls: TNetTlsContext; 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); //https? ini.free; KeepAliveTimeOut := 30000; if not ssl then FServer := THttpAsyncServer.Create(httpport, nil, nil, 'yn', threadnum, KeepAliveTimeOut, []) else FServer := THttpAsyncServer.Create(httpport, nil, nil, 'yn', threadnum, KeepAliveTimeOut, [hsoEnableTls]); queueLen := 100000; FServer.HttpQueueLength := queueLen; FServer.OnRequest := process; if not ssl then FServer.WaitStarted else begin InitNetTlsContextSelfSignedServer(tls); //自签名 try FServer.WaitStarted(10, @tls); finally DeleteFile(Utf8ToString(tls.CertificateFile)); DeleteFile(Utf8ToString(tls.PrivateKeyFile)); end; end; {$IFDEF console} Writeln('New THttpAsyncServer server'); if not ssl then Writeln('Http port: ', httpport) else Writeln('Https port: ', httpport); Writeln('Thread num: ', threadnum); {$ENDIF} end; destructor THttpSVR.Destroy; begin FreeAndNil(FServer); inherited; end; function THttpSVR.process(Ctxt: THttpServerRequestAbstract): cardinal; begin router(Ctxt); Result := 200; 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.
标签:begin,end,THttpAsyncServer,req,res,mormot2,var,Ctxt From: https://www.cnblogs.com/hnxxcxg/p/17483302.html