首页 > 其他分享 >TDiocpHttpServer

TDiocpHttpServer

时间:2023-06-15 16:34:24浏览次数:44  
标签:begin end res req var TDiocpHttpServer Ctxt

TDiocpHttpServer

DIOCP只支持windows。

unit sock.DiocpHttpServer;
/// <author>cxg 2023-2-12</author>

interface

uses classes,
  system.JSON, json.help, keyValue.serialize, api.router,
  IniFiles, global, diocp_ex_httpServer, 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
  TiocpHttpServer = class
  private
    FServer: TDiocpHttpServer;
    procedure OnHttpSvrRequest(pvRequest: TDiocpHttpRequest);
  public
    constructor Create; overload;
    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;

procedure setHeader(const Ctxt: TDiocpHttpRequest; const ContentType: string);
begin
  Ctxt.Response.ContentType := ContentType;
  Ctxt.Response.Header.ForceByName('Access-Control-Allow-Origin').AsString := '*';
  Ctxt.Response.Header.ForceByName('Access-Control-Allow-Methods').AsString := '*';
  Ctxt.Response.Header.ForceByName('Access-Control-Allow-Headers').AsString := '*';
end;

procedure router(const Ctxt: TDiocpHttpRequest);   //diocp router
begin
  if Pos('/bin', Ctxt.RequestURL) > 0 then      //二进制 API
  begin
    setHeader(Ctxt, cBin);
    var req: TSerialize := tserialize.Create;
    var res: TSerialize := tserialize.Create;
    if Ctxt.ContentBody.Length > 0 then
      req.unMarshal(Ctxt.ContentBody.ToBytes);
    var url: string := Ctxt.RequestURL;
    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 bs: TBytes := res.marshal2;
    Ctxt.Response.WriteBuf(PByte(bs), Length(bs));
    Ctxt.SendResponse();
    req.Free;
    res.Free;
  end
  else if Pos('/rest', Ctxt.RequestURL) > 0 then    //JSON API
  begin
    setHeader(Ctxt, cJson);
    var url: string := Ctxt.RequestURL;
    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.ContentBody.Length > 0 then
      req.asStr['body'] := Ctxt.ContentBody.ToString;
    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.RequestMethod then
      begin
        RouterAPI(o.S['classname'], o.S['funcname'], [req, res]);
        Break;
      end;
    end;
    Ctxt.Response.WriteString(UTF8Encode(res.asStr['res']));
    Ctxt.SendResponse();
    req.Free;
    res.Free;
  end
  else if Pos('/protobuf', Ctxt.RequestURL) > 0 then   //PROTOBUF API
  begin
    setHeader(Ctxt, cProtobuf);
    var url: string := Ctxt.RequestURL;
    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.ContentBody.Length > 0 then
      req.asBytes['body'] := Ctxt.ContentBody.ToBytes;
    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.RequestMethod then
      begin
        RouterAPI(o.S['classname'], o.S['funcname'], [req, res]);
        Break;
      end;
    end;
    var bs: TBytes := res.asBytes['res'];
    Ctxt.Response.WriteBuf(PByte(bs), Length(bs));
    Ctxt.SendResponse();
    req.Free;
    res.Free;
  end;
end;

constructor TiocpHttpServer.Create;
var
  ini: tinifile;
begin
  FServer := TDiocpHttpServer.Create(nil);
  FServer.UseObjectPool := True;
  FServer.SetMaxSendingQueueSize(100000);
  FServer.OnDiocpHttpRequest := OnHttpSvrRequest;
  ini := TIniFile.Create(SvrCfg);
  var threadnum: Integer := ini.readinteger('config', 'threadnum', 32);
  if threadnum > 256 then
    threadnum := 256;
  FServer.WorkerCount := threadnum;
  FServer.Port := ini.ReadInteger('config', 'httpport', 1234);
  ini.free;
  fserver.Active := True;
  {$IFDEF console}
  Writeln('New IOCP http server');
  Writeln('Thread num: ', FServer.WorkerCount);
  Writeln('Http port: ', FServer.Port);
  {$ENDIF}
end;

destructor TiocpHttpServer.Destroy;
begin
  FServer.DisConnectAll();
  FServer.SafeStop;
  FServer.Free;
  inherited;
end;

procedure TiocpHttpServer.OnHttpSvrRequest(pvRequest: TDiocpHttpRequest);
begin
  router(pvRequest);
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,var,TDiocpHttpServer,Ctxt
From: https://www.cnblogs.com/hnxxcxg/p/17483268.html

相关文章