using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; using Sers.Core.Module.Api; using Sers.Core.Module.Api.LocalApi.StaticFileTransmit; using Sers.Core.Module.Api.Rpc; using Sers.Core.Module.Message; using Sers.Core.Module.Rpc; using Sers.SersLoader; using Sers.SersLoader.ApiDesc.Attribute.RpcVerify; using Sers.SersLoader.ApiDesc.Attribute.Valid; using Vit.Core.Util.ComponentModel.Api; using Vit.Core.Util.ComponentModel.Data; using Vit.Core.Util.ComponentModel.Model; using Vit.Core.Util.ConfigurationManager; using Vit.Extensions; using Vit.Net.Http.FormFile; namespace Did.SersLoader.Demo.Controllers.Demo { //站点名称,可多个。若不指定,则从 配置文件中LocalApiService中的"apiStationNames"获取 [SsStationName("demo")] //[SsStationName("demo2"), SsStationName("demo3")] //路由前缀,可不指定 [SsRoutePrefix("v1/api")] public class SampleController : IApiController { #region (x.1)route /// /// route示例 /// /// [SsRoute("101/route"), SsRoute("102/route")] [SsRoute("/demo/v1/api/103/route")] //使用绝对路径路由 public ApiReturn Route() { return new { url = RpcContext.RpcData.http_url_Get() }; } /// /// route示例-泛接口 /// /// [SsRoute("104/route/*")] //使用泛接口路径路由 public ApiReturn Route4() { var rpcData = RpcContext.RpcData; var route = rpcData.route; var http_url = rpcData.http_url_Get(); var http_url_search = rpcData.http_url_search_Get(); var http_url_RelativePath = rpcData.http_url_RelativePath_Get(); var http_method = rpcData.http_method_Get() ; var data = new { route, http_url, http_url_search, http_url_RelativePath, http_method }; return new ApiReturn(data); } /// /// HttpMethod示例GET /// /// [SsRoute("105/route",HttpMethod ="GET")] public ApiReturn Route5_Get() { return new { apiName = "Route5_Get", rpcData = RpcContext.RpcData }; } /// /// HttpMethod示例POST /// /// [SsRoute("105/route", HttpMethod = "POST")] public ApiReturn Route5_POST() { return new { apiName = "Route5_POST", rpcData = RpcContext.RpcData }; } #endregion #region (x.2)Name和Desc /// /// 演示 如何使用Name 和 Description。 /// 函数注释和使用SsDescription是一样的效果。 /// /// [SsRoute("201/NameDesc")] [SsName("NameDesc1")] public ApiReturn NameDesc() { return new ApiReturn(); } /// /// /// /// [SsRoute("202/NameDesc")] [SsDescription("演示 如何使用Name 和 Description。\n函数注释和使用SsDescription是一样的效果。")] public ApiReturn NameDesc2() { return new ApiReturn(); } #endregion #region (x.3)参数 #region (x.x.1)无参 /// /// 无参 /// /// [SsRoute("310/arg")] public ApiReturn Arg301() { return new ApiReturn(); } #endregion #region (x.x.2)首个参数为参数实体 /// /// 首个参数为参数实体(引用类型) /// /// arg1注释 /// ArgModelDesc-returns [SsRoute("320/arg")] public ApiReturn Arg320( [SsExample("{\"arg\":\"arg\",\"arg2\":\"arg2\"}"), SsDefaultValue("{\"arg\":\"arg\",\"arg2\":\"arg2\"}"), SsDescription("argDescription")]ArgModel args ) { return args; } /// /// 首个参数为参数实体(引用类型) /// /// /// [SsRoute("321/arg")] public ApiReturn Arg321( [SsExample("[\"arg1\",\"arg2\"]"), SsDefaultValue("[\"arg1\",\"arg2\"]"), SsDescription("argDescription")]string[] args) { return args; } /// /// 标识函数第一个参数为Api的参数实体。(忽略其他参数(若存在),调用函数时其他参数(若存在)为空) /// /// args注释 /// [SsRoute("322/arg")] public ApiReturn Arg322( [SsExample("argExample"), SsDefaultValue("argDefaultValue"), SsDescription("argDescription"),SsArgEntity]string args) { return args; } /// /// 标识函数第一个参数为Api的参数实体。(忽略其他参数(若存在),调用函数时其他参数(若存在)为空) /// /// /// /// [SsRoute("323/arg")] public ApiReturn Arg323([SsArgEntity]string args,string arg2) { return args; } #endregion #region (x.x.3)函数参数列表为参数实体 /// /// 函数参数列表为参数实体 /// /// /// [SsRoute("330/arg")] public ApiReturn Arg330([SsExample("argExample"), SsDefaultValue("argDefaultValue"), SsDescription("argDescription")]string arg1) { return new { arg1 }; } /// /// 函数参数列表为参数实体 /// /// arg1注释 /// arg2注释 /// [SsRoute("331/arg")] public ApiReturn Arg331( [SsExample("example1"), SsDefaultValue("default1"), SsDescription("desc1")]string arg1, [SsExample("6"), SsDefaultValue("1")]int arg2) { return new { arg1 , arg2 }; } /// /// 函数参数列表为参数实体 /// /// arg1注释 /// arg2注释 /// [SsRoute("332/arg")] public ApiReturn Arg332(ArgModel arg1, [SsExample("6"), SsDefaultValue("1")]int arg2) { return new { arg1, arg2 }; } /// /// 函数第一个参数为Api的参数实体的属性之一。(一般放置在第一个参数上,代表第一个参数不为参数实体) /// /// arg1注释 /// [SsRoute("333/arg")] public ApiReturn Arg333([SsArgProperty]ArgModel arg1) { return new { arg1}; } #endregion public class ArgModel { /// /// 姓名 /// [SsExample("lith"), SsDefaultValue("NoName")] [JsonProperty("arg")] public string name { get; set; } /// /// /// [SsExample("20"), SsDefaultValue("0"), SsDescription("年龄,请指定在16-50中间的整数")] public int age; } #endregion #region (x.4)返回值 /// /// Return1 /// /// Return注释-FromXml [SsRoute("401/ret")] public ApiReturn Return1() { return new ReturnData { name = "张三" }; } /// /// Return2 /// /// [SsRoute("402/ret")] [return: SsExample("{\"data\":12}"), SsDescription("成功个数")] public ApiReturn Return2() { return 5; } /// /// /// /// [SsRoute("403/ret")] public ApiReturn> Return3() { return new List{ "1","2"}; } /// /// /// /// [SsRoute("404/ret")] [return: SsExample("test"), SsDescription("返回test1")] public string Return4() { return "test1"; } /// /// /// /// [SsRoute("405/ret")] [return: SsExample("5"), SsDescription("返回5")] public int Return5() { return 5; } /// /// /// /// [SsRoute("406/ret")] [return: /*SsExample("{\"name\":\"张三\"}"),*/ SsDescription("返回模型数据")] public ReturnData Return6() { return new ReturnData { name = "张三" }; } /// /// Return注释-FromType /// public class ReturnData { /// /// 姓名 /// [SsExample("lith"), SsDefaultValue("NoName")] public string name { get; set; } } #endregion #region (x.5) Rpc /// /// rpc示例 /// /// [SsRoute("501/GetRpcOriData")] public ApiReturn GetRpcOriData() { return new ApiReturn(RpcContext.RpcData); } /// /// rpc示例 /// /// [SsRoute("502/RpcDemo")] public ApiReturn RpcDemo() { var rpcData = RpcContext.RpcData; var data = new { rpcData.route, http_url = rpcData.http_url_Get(), userInfo = rpcData.user_userInfo_Get(), serviceId= DateTime.Now.ToString("sss") }; return new ApiReturn(data); } /// /// rpc示例 /// /// [SsRoute("503/RpcReplyDemo")] public ApiReturn RpcReplyDemo([SsArgEntity,SsExample("requestContent")]string request) { #region reply header RpcContext.Current.apiReplyMessage.rpcContextData_OriData = RpcFactory.Instance.CreateRpcContextData() .http_statusCode_Set(201) //.http_header_Set("Content-Type", "application/json") .http_header_ContentType_Set("application/json") .http_header_Set("testHeader", "abc") .PackageOriData(); //var replyRpcData = RpcFactory.Instance.CreateRpcContextData(); //var header = new JObject(); //header["testHeader"] = "abc"; //header["Content-Type"] = "application/json";s //replyRpcData.http_headers_Set(header); //RpcContext.Current.apiReplyMessage.rpcContextData_OriData = replyRpcData.PackageOriData(); #endregion var data = new { RpcContext.RpcData, request }; return data; } #endregion #region (x.6) ApiClient #region (x.x.1)ApiClient示例,调用其他接口 /// /// ApiClient示例,调用其他接口 /// /// [SsRoute("610/ApiClient")] public ApiReturn ApiClient610( [SsExample("/demo/v1/api/332/arg")]string apiRoute, [SsExample("{\"arg1\":\"dd\",\"arg2\":\"33\"}")]object arg) { var apiRet = ApiClient.CallRemoteApi>(apiRoute, arg); return new ApiReturn(new { RpcContext.RpcData, apiRet }); } #endregion #region (x.x.2) ApiClient示例,传输二进制数据 /// /// ApiClient示例,传输二进制数据 /// /// /// [SsRoute("620/ApiClient")] [SsName("ApiClient demo")] [return:SsExample("1122AAFF"), SsDescription("二进制数据")] public byte[] ApiClient620( [SsExample("1122AAFF"), SsDescription("二进制数据")]byte[] ba) // 使用ArraySegment 会减少一步复制的操作,若传输大数据建议使用ArraySegment { return ba; } /// /// ApiClient示例,传输二进制数据 /// /// /// [SsRoute("621/ApiClient")] [SsName("ApiClient demo")] [return: SsExample("1122AAFF"), SsDescription("二进制数据")] public ArraySegment ApiClient621( [SsExample("1122AAFF"), SsDescription("二进制数据")]ArraySegment ba) { return ba; } /// /// ApiClient示例,传输二进制数据 /// /// [SsRoute("622/ApiClient")] public ApiReturn ApiClient622() { var apiRet = ApiClient.CallRemoteApi>("/demo/v1/api/621/ApiClient", new byte[] { 3, 2, 3, 4, 5 }); return new ApiReturn(); } #endregion #region (x.x.3) ApiClient示例,传输额外数据 /// /// ApiClient示例,二进制数据和ReplyRpc /// /// [SsRoute("630/ApiClient")] public ApiReturn ApiClient630() { var apiReply = RpcContext.Current.apiReplyMessage; var file1 = new byte[] { 1, 2, 3, 4, 5 }; var file2 = new byte[] { 2, 3, 3, 4, 5 }; apiReply.AddFiles(file1.BytesToArraySegmentByte(), file2.BytesToArraySegmentByte()); #region file from request var apiRequest = RpcContext.Current.apiRequestMessage; if (apiRequest.Files.Count >= 3) { var file3 = apiRequest.Files[2]; apiReply.AddFiles(file3); } #endregion apiReply.rpcContextData_OriData = RpcContext.Current.apiRequestMessage.rpcContextData_OriData; return new ApiReturn(); } /// /// ApiClient示例,传输二进制数据和ReplyRpc /// /// [SsRoute("631/ApiClient")] public ApiReturn ApiClient3_2() { var apiRequestMessage = new ApiMessage().InitAsApiRequestMessage("/demo/v1/630/ApiClient", null); var fileToSend = new byte[] { 3, 2, 3, 4, 5 }; apiRequestMessage.AddFiles(fileToSend.BytesToArraySegmentByte()); var apiReplyMessage = ApiClient.CallRemoteApi(apiRequestMessage); var file1 = apiReplyMessage.Files[2]; var file2 = apiReplyMessage.Files[3]; var file3 = apiReplyMessage.Files[4]; //var replyRpcData = RpcFactory.Instance.CreateRpcContextData(); //replyRpcData.UnpackOriData(apiReplyMessage.rpcContextData_OriData); return new ApiReturn(); } #endregion #endregion #region (x.7) UseStaticFiles // wwwroot 路径从配置文件获取 static StaticFileMap staticFileMap = new StaticFileMap(ConfigurationManager.Instance.GetByPath("Demo.staticFiles")); /// /// UseStaticFiles /// /// [SsRoute("700/static/*")] public byte[] UseStaticFiles() { return staticFileMap.TransmitFile(); } #endregion #region (x.8) RpcVerify #region (x.8.1) 自定义限制 SsRpcVerify /// /// 810自定义限制 SsRpcVerify /// /// [SsRoute("810/SsRpcVerify")] [SsRpcVerify( condition = "{\"type\":\"==\",\"path\":\"http.method\",\"value\":\"PUT\"}", verifiedWhenNull = false , errorMessage = "只接受PUT请求", errorCode = 1000)] // condition: SsExp,参考 rpcVerify2.md // path: RpcData中被验证的值,(参考 RpcContextData.md)。如 http.url 、http.method 、 http.headers.Authorization // verifiedWhenNull: 当出现空值时,是否通过验证(默认不通过,false)。例如,为fakse时,若没有指定值http.method,则禁止调用接口,返回错误消息; // 为true时,在没有指定http.method时可以调用哦接口 // // errorMessage: 校验不通过时的提示消息,若不指定则使用默认提示消息 // errorCode: 校验不通过时的errorCode, 如 1000。可不指定 public ApiReturn SsRpcVerify() { return new ApiReturn(); } #endregion #region (x.8.2) CallerSource /// /// 820限制只可内部调用 /// /// [SsRoute("820/CallerSource")] [SsNotEqual(path = "caller.source", value = "Internal", errorMessage = "无权限")] //[SsNotEqual(type="!=",path = "caller.source", value = "Internal", errorMessage = "无权限")] public ApiReturn CallerSource820() { return new ApiReturn(); } /// /// 821限制只可内部调用 /// /// [SsRoute("821/CallerSource")] //[SsCallerSource(ECallerSource.Internal)] //[SsCallerSource(ECallerSource.Internal| ECallerSource.OutSide)] [SsCallerSource(callerSourceString = "Internal,OutSide")] public ApiReturn CallerSource821() { return new ApiReturn(); } /// /// 822限制只可外部调用 /// /// [SsRoute("822/CallerSource")] [SsCallerSource(ECallerSource.OutSide, errorMessage = "只可外部调用")] public ApiReturn CallerSource822() { return new ApiReturn(); } #endregion #region (x.8.3) SsCmp /// /// 830 SsCmp /// /// [SsRoute("830/SsCmp")] [SsCmp(path = "http.method", type = "==" , value="PUT")] public ApiReturn SsCmp830() { return new ApiReturn(); } #endregion #region (x.8.4) SsEqual /// /// 840 SsEqual /// /// [SsRoute("840/SsEqual")] [SsEqual(path = "http.method", value = "PUT")] public ApiReturn SsEqual840() { return new ApiReturn(); } #endregion #region (x.8.5) SsNotEqual /// /// 850 SsNotEqual /// /// [SsRoute("850/SsNotEqual")] [SsNotEqual(path = "http.method", value = "PUT",errorMessage = "不可为PUT请求")] public ApiReturn SsNotEqual850() { return new ApiReturn(); } #endregion #region (x.8.6) SsNotNull /// /// 860 SsNotNull /// /// [SsRoute("860/SsNotNull")] [SsNotNull(path = "http.headers.Authorization", errorMessage = "必须指定Authorization")] public ApiReturn SsNotNull860() { return new ApiReturn(); } #endregion #region (x.8.7) SsRegex /// /// 870 SsRegex(请求地址 /demo/v1/api/870/SsRegex/a.html ) /// /// [SsRoute("870/SsRegex/*")] [SsRegex(path = "http.url", value = "(?<=\\.html)$", errorMessage = "url后缀必须为 .html")] public ApiReturn SsRegex870() { return new ApiReturn(); } #endregion #endregion #region (x.9)特殊示例 #region (x.x.1) 递归demo /// /// 递归。 f(n) = f(n-1) + f(n-2) /// /// [SsRoute("901/Recursive")] public ApiReturn Recursive([SsExample("4")]int n) { if (n <= 2) return 1; var task1 = ApiClient.CallRemoteApiAsync>(RpcContext.RpcData.route, new { n = n - 1 }); var task2 = ApiClient.CallRemoteApiAsync>(RpcContext.RpcData.route, new { n = n - 2 }); Task.WaitAll(task1, task1); var apiRet1 = task1.Result; var apiRet2 = task2.Result; if (!apiRet1.success) return apiRet1.error; if (!apiRet2.success) return apiRet2.error; return apiRet1.data+ apiRet2.data; } #endregion #region (x.x.2) Sleep /// /// 睡眠指定时间 /// /// [SsRoute("902/sleep")] public ApiReturn Sleep( [SsExample("2"),SsDescription("单位:s")]int s) { Thread.Sleep(s * 1000); return s; } #endregion #region (x.x.3) Upload /// /// 上传文件(测试地址 /demo/v1/api/700/static/upload.html) /// /// [SsRoute("903/upload",HttpMethod = "POST")] public ApiReturn Upload(byte[] data) { MultipartForm result=new MultipartForm(data, RpcContext.RpcData.http_header_ContentType_Get()); return result; } #endregion #endregion } }