cross socket ICrossHttpServer
cross socket是delphi跨平台的一个socket库。
/// <author>cxg 2023-2-12</author> /// TStream(ARequest.body),auto be free unit sock.CrossHttpSvr; interface uses system.JSON, json.help, keyValue.serialize, api.router, Net.CrossSocket.Base, global, yn.log, Net.CrossHttpServer, Net.CrossSslSocket, Net.CrossSslDemoCert, System.Math, System.IniFiles, System.SysUtils, System.Classes; 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 TcrossHttpSvr = class private FHttpServer: ICrossHttpServer; FShutdown: Boolean; procedure Process; public constructor Create; overload; destructor Destroy; override; public procedure Start; procedure Stop; property HttpServer: ICrossHttpServer read FHttpServer; end; implementation function strof(const aStream: TStream): RawByteString; overload; begin SetLength(Result, aStream.Size); aStream.Position := 0; aStream.Read(Result[1], aStream.Size); 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: ICrossHttpResponse; const ContentType: string); begin Ctxt.Header['Access-Control-Allow-Origin'] := '*'; Ctxt.Header['Access-Control-Allow-Methods'] := '*'; Ctxt.Header['Access-Control-Allow-Headers'] := '*'; Ctxt.ContentType := ContentType; end; procedure router(const Ctxt: ICrossHttpRequest; const Ctxt2: ICrossHttpResponse); begin if Pos('/bin', Ctxt.RawPathAndParams) > 0 then //二进制 API begin setHeader(Ctxt2, cBin); var req: TSerialize := tserialize.Create; var res: TSerialize := tserialize.Create; var ms: TStream := TStream(Ctxt.Body); if ms <> nil then req.unMarshal(ms); var url: string := Ctxt.RawPathAndParams; 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; Ctxt2.Send(res.marshal2, procedure(const AConnection: ICrossConnection; const ASuccess: Boolean) begin req.Free; res.Free; end); end else if Pos('/rest', Ctxt.RawPathAndParams) > 0 then //JSON API begin setHeader(Ctxt2, cJson); var url: string := Ctxt.RawPathAndParams; 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; var ms: TStream := TStream(Ctxt.Body); var body: RawByteString; if ms <> nil then body := strof(ms); req.asStr['body'] := body; 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; Ctxt2.Send(UTF8Encode(res.asStr['res']), procedure(const AConnection: ICrossConnection; const ASuccess: Boolean) begin req.Free; res.Free; end); end else if Pos('/protobuf', Ctxt.RawPathAndParams) > 0 then //PROTOBUF API begin setHeader(Ctxt2, cProtobuf); var url: string := Ctxt.RawPathAndParams; 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; var ms: TStream := TStream(Ctxt.Body); var body: TBytes; if ms <> nil then strof(ms); req.asBytes['body'] := body; 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; Ctxt2.Send(res.asBytes['res'], procedure(const AConnection: ICrossConnection; const ASuccess: Boolean) begin req.Free; res.Free; end); end; end; constructor TcrossHttpSvr.Create; begin var ini: TIniFile := TIniFile.create(SvrCfg); var threadnum: Integer := ini.readinteger('config', 'threadnum', 32); if threadnum > 256 then threadnum := 256; var ssl: Boolean := ini.readbool('config', 'ssl', False); FHttpServer := TCrossHttpServer.create(threadnum, ssl); // New http server if FHttpServer.SSL then begin FHttpServer.SetCertificate(SSL_SERVER_CERT); FHttpServer.SetPrivateKey(SSL_SERVER_PKEY); end; FHttpServer.Addr := IPv4v6_ALL; FHttpServer.Port := ini.readinteger('config', 'httpport', 0); // port ini.Free; {$IFDEF console} Writeln('New cross http server'); Writeln('Http port: ', FHttpServer.Port); Writeln('Thread num: ', threadnum); {$ENDIF} FHttpServer.Compressible := True; // zip? Process; Self.Start; end; destructor TcrossHttpSvr.Destroy; begin Self.Stop; FHttpServer := nil; inherited; end; procedure TcrossHttpSvr.Start; begin FHttpServer.Start; end; procedure TcrossHttpSvr.Stop; begin FHttpServer.Stop; FShutdown := True; Sleep(150); end; procedure TcrossHttpSvr.Process; begin try FHttpServer.All('*', procedure(const ARequest: ICrossHttpRequest; const AResponse: ICrossHttpResponse) begin router(ARequest, AResponse); end); except on E: Exception do begin writelog('TcrossHttpSvr.Process()' + E.message); end; end; 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,socket,req,cross,var,const,ICrossHttpServer,Ctxt From: https://www.cnblogs.com/hnxxcxg/p/17483253.html