首页 > 其他分享 >TBrookHTTPServer

TBrookHTTPServer

时间:2023-06-15 16:33:14浏览次数:39  
标签:begin end res req TBrookHTTPServer var Ctxt

TBrookHTTPServer

brook是c写的,以dll供delphi和lazarus调用。

unit Brook.HTTPServer;
//cxg 2023-2-12

interface

uses
  sock.router, System.JSON, Json.help, keyValue.serialize, api.router,
  BrookHTTPRequest, BrookHTTPResponse, BrookHTTPServer, global, IniFiles,
  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
  TbrookServer = class(TBrookHTTPServer)
  protected
    procedure DoRequest(ASender: TObject; ARequest: TBrookHTTPRequest; AResponse: TBrookHTTPResponse); override;
  public
    constructor Create; overload;
    destructor Destroy; override;
  end;

var
  SERVER: TbrookServer;

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: TBrookHTTPResponse);
begin
  Ctxt.Headers.Add('Access-Control-Allow-Origin', '*');
  Ctxt.Headers.Add('Access-Control-Allow-Methods', '*');
  Ctxt.Headers.Add('Access-Control-Allow-Headers', '*');
end;

procedure router(const Ctxt: TBrookHTTPRequest; const Ctxt2: TBrookHTTPResponse);  //brook router
begin
  if Pos('/bin', Ctxt.path) > 0 then      //二进制 API
  begin
    setHeader(Ctxt2);
    var req: TSerialize := tserialize.Create;
    var res: TSerialize := tserialize.Create;
    if Ctxt.Payload.Length > 0 then
      req.unMarshal(Ctxt.Payload.Content);
    var url: string := Ctxt.path;
    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;
    var r: TBytes := res.marshal2;
    Ctxt2.SendBytes(r, Length(r), cBin, 200);
    req.Free;
    res.Free;
  end
  else if Pos('/rest', Ctxt.path) > 0 then    //JSON API
  begin
    setHeader(Ctxt2);
    var url: string := Ctxt.path;
    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 body: RawByteString;
    if Ctxt.Payload.Length > 0 then
    begin
      body := strof(Ctxt.Payload.Content);
      req.asStr['body'] := body;
    end;
    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']), cJson, 200);
    req.Free;
    res.Free;
  end
  else if Pos('/protobuf', Ctxt.path) > 0 then   //PROTOBUF API
  begin
    setHeader(Ctxt2);
    var url: string := Ctxt.path;
    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.Payload.Length > 0 then
      req.asBytes['body'] := Ctxt.Payload.Content;
    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;
    var r: TBytes := res.asBytes['res'];
    Ctxt2.SendBytes(r, Length(r), cProtobuf, 200);
    req.Free;
    res.Free;
  end;
end;

constructor TbrookServer.Create;
var
  ini: tinifile;
begin
  SERVER := TbrookServer.Create(nil);
  ini := TIniFile.Create(svrcfg);
  ini.readinteger('config', 'httpport', 0);
  var threadnum: Integer := ini.readinteger('config', 'threadnum', 32);
  if threadnum > 256 then
    threadnum := 256;
  server.ThreadPoolSize := threadnum;
  SERVER.Port :=ini.readinteger('config', 'httpport', 0);
  ini.free;
  SERVER.Open;
  {$IFDEF console}
  Writeln('New brook http server');
  Writeln('Http port: ', SERVER.Port);
  Writeln('Thread num: ', server.ThreadPoolSize);
  {$ENDIF}
end;

destructor TbrookServer.Destroy;
begin
  SERVER.Free;
  inherited;
end;

procedure TbrookServer.DoRequest(ASender: TObject; ARequest: TBrookHTTPRequest; AResponse: TBrookHTTPResponse);
begin
  router(ARequest, AResponse);
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,res,req,TBrookHTTPServer,var,Ctxt
From: https://www.cnblogs.com/hnxxcxg/p/17483287.html

相关文章