diff --git a/.gitignore b/.gitignore index bde74b7..34c0441 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ *.user *.userosscache *.sln.docstates - +.output # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/simples/global.json b/simples/global.json new file mode 100644 index 0000000..5395ff4 --- /dev/null +++ b/simples/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "6.0.101" + } +} \ No newline at end of file diff --git a/simples/pipeline.props b/simples/pipeline.props index 52758ec..c2ade37 100644 --- a/simples/pipeline.props +++ b/simples/pipeline.props @@ -1,4 +1,8 @@  + + none + false + diff --git a/simples/publish.bat b/simples/publish.bat new file mode 100644 index 0000000..12a25f0 --- /dev/null +++ b/simples/publish.bat @@ -0,0 +1 @@ +dotnet publish ./JT808.Gateway.SimpleServer/JT808.Gateway.SimpleServer.csproj -c Release -o .output -r linux-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true -p:IncludeNativeLibrariesForSelfExtract=true -p:DebugType=none -p:DebugSymbols=false \ No newline at end of file diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs index 231c7c0..7991612 100644 --- a/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs +++ b/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs @@ -67,7 +67,7 @@ namespace JT808.Gateway.NormalHosting //httpclient客户端调用 //services.AddHostedService(); //客户端测试 依赖AddClient()服务 - services.AddHostedService(); + //services.AddHostedService(); }); await serverHostBuilder.RunConsoleAsync(); diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/PipeTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/PipeTest.cs index 9037342..02536f6 100644 --- a/src/JT808.Gateway.Tests/JT808.Gateway.Test/PipeTest.cs +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/PipeTest.cs @@ -96,5 +96,38 @@ namespace JT808.Gateway.Test } }); } + + [Fact] + public void Test4() + { + Func method = (a) => + { + if (a == 2) + { + Thread.Sleep(6000); + } + return new byte[20]; + }; + + var result1 = Call(1, method, out bool timeout1); + var result2 = Call(2, method, out bool timeout2); + } + + private byte[] Call(int data, Func method, out bool timeout) + { + try + { + using CancellationTokenSource cancelSource1 = new CancellationTokenSource(5000); + Task result = Task.Run(() => method(data), cancelSource1.Token); + result.Wait(cancelSource1.Token); + timeout = false; + return result.Result; + } + catch (OperationCanceledException ) + { + timeout = true; + } + return default(byte[]); + } } } diff --git a/src/JT808.Gateway/Extensions/JT808HttpContextExtensions.cs b/src/JT808.Gateway/Extensions/JT808HttpContextExtensions.cs index a4c85fc..1e64d06 100644 --- a/src/JT808.Gateway/Extensions/JT808HttpContextExtensions.cs +++ b/src/JT808.Gateway/Extensions/JT808HttpContextExtensions.cs @@ -76,6 +76,19 @@ namespace JT808.Gateway.Extensions context.Response.Close(); } + public static async ValueTask Http504(this HttpListenerContext context) + { + byte[] b = Encoding.UTF8.GetBytes("call service timeout."); + context.Response.StatusCode = (int)HttpStatusCode.GatewayTimeout; + context.Response.KeepAlive = false; + context.Response.ContentType = jsonType; + context.Response.ContentLength64 = b.Length; + var output = context.Response.OutputStream; + await output.WriteAsync(b, CancellationToken.None); + context.Response.OutputStream.Close(); + context.Response.Close(); + } + public static async ValueTask HttpSend(this HttpListenerContext context, ReadOnlyMemory buffer) { context.Response.StatusCode = (int)HttpStatusCode.OK; diff --git a/src/JT808.Gateway/JT808HttpServer.cs b/src/JT808.Gateway/JT808HttpServer.cs index ab3a826..776f993 100644 --- a/src/JT808.Gateway/JT808HttpServer.cs +++ b/src/JT808.Gateway/JT808HttpServer.cs @@ -33,6 +33,8 @@ namespace JT808.Gateway private readonly JT808MsgIdDefaultWebApiHandler MsgIdDefaultWebApiHandler; + const int CallTimeoutMS = 10000; + public JT808HttpServer( JT808MsgIdDefaultWebApiHandler jT808MsgIdDefaultWebApiHandler, IOptions jT808ConfigurationAccessor, @@ -76,7 +78,6 @@ namespace JT808.Gateway context.Http404(); continue; } - // 增加CORS // https://stackoverflow.com/questions/25437405/cors-access-for-httplistener context.Response.AppendHeader("Access-Control-Allow-Origin", "*"); @@ -86,8 +87,7 @@ namespace JT808.Gateway context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST"); context.Response.AddHeader("Access-Control-Max-Age", "1728000"); context.Http204(); - } - + } if (authorization.Authorization(context, out var principal)) { await ProcessRequestAsync(context, principal); @@ -120,17 +120,35 @@ namespace JT808.Gateway context.Http404(); return; } - if(context.Request.HttpMethod == HttpMethod.Get.Method) + bool timeout=false; + byte[] response; + if (context.Request.HttpMethod == HttpMethod.Get.Method) { var index = context.Request.Url.AbsoluteUri.IndexOf('?'); if (index > 0) { var uriParamStr = context.Request.Url.AbsoluteUri[(index + 1)..].ToString(); - await context.HttpSend(router.Value(uriParamStr)); + response = Call(uriParamStr, router.Value, out timeout); + if (!timeout) + { + await context.HttpSend(response); + } + else + { + await context.Http504(); + } } else { - await context.HttpSend(router.Value("")); + response = Call("", router.Value, out timeout); + if (!timeout) + { + await context.HttpSend(response); + } + else + { + await context.Http504(); + } } } else if(context.Request.HttpMethod == HttpMethod.Post.Method) @@ -140,7 +158,15 @@ namespace JT808.Gateway { json = reader.ReadToEnd(); } - await context.HttpSend(router.Value(json)); + response = Call(json, router.Value, out timeout); + if (!timeout) + { + await context.HttpSend(response); + } + else + { + await context.Http504(); + } } else { @@ -148,6 +174,23 @@ namespace JT808.Gateway } } + private byte[] Call(string data, Func method,out bool timeout) + { + try + { + using CancellationTokenSource cancelSource1 = new CancellationTokenSource(CallTimeoutMS); + Task result = Task.Run(() => method(data), cancelSource1.Token); + result.Wait(cancelSource1.Token); + timeout = false; + return result.Result; + } + catch (OperationCanceledException) + { + timeout = true; + } + return default(byte[]); + } + public Task StopAsync(CancellationToken cancellationToken) { try diff --git a/src/global.json b/src/global.json new file mode 100644 index 0000000..5395ff4 --- /dev/null +++ b/src/global.json @@ -0,0 +1,5 @@ +{ + "sdk": { + "version": "6.0.101" + } +} \ No newline at end of file