From a619bd382c9b6e9ce79b3b179c1ea62bc09090de Mon Sep 17 00:00:00 2001 From: "SmallChi(Koike)" <564952747@qq.com> Date: Wed, 2 Sep 2020 12:04:42 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=AE=8C=E5=96=84http=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=A4=84=E7=90=86=E7=A8=8B=E5=BA=8F=202.=E6=B7=BB=E5=8A=A0http?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=AE=A4=E8=AF=81=203.=E6=B7=BB=E5=8A=A0http?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AFDI=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/README.md | 60 ------------------- .../JT808.Gateway.NormalHosting/Program.cs | 17 +++--- .../JT808.Gateway.Test.csproj | 9 +++ .../JT808.Gateway.Test/JT808HttpClientTest.cs | 50 ++++++++++++++++ .../JT808.Gateway.Test/appsettings.json | 6 ++ .../JT808.Gateway.WebApiClientTool.csproj | 3 + .../JT808.Gateway.WebApiClientTool.xml | 34 +++++++++++ .../JT808HttpClient.cs | 8 +-- .../JT808HttpClientExtensions.cs | 6 +- .../JT808AuthorizationDefault.cs | 48 +++++++++++++++ .../Extensions/JT808HttpContextExtensions.cs | 9 +++ src/JT808.Gateway/JT808GatewayExtensions.cs | 3 + src/JT808.Gateway/JT808HttpServer.cs | 46 ++++++++++---- 13 files changed, 215 insertions(+), 84 deletions(-) create mode 100644 src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808HttpClientTest.cs create mode 100644 src/JT808.Gateway.Tests/JT808.Gateway.Test/appsettings.json create mode 100644 src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.xml create mode 100644 src/JT808.Gateway/Authorization/JT808AuthorizationDefault.cs diff --git a/api/README.md b/api/README.md index d71c6f8..c7b2c43 100644 --- a/api/README.md +++ b/api/README.md @@ -18,12 +18,6 @@ [基于Udp管理会话服务](#udp_session) -## 4.消息包计数服务 - -[基于Tcp消息包计数服务](#tcp_counter) - -[基于Udp消息包计数服务](#udp_counter) - ## 接口请求对照表 ### 公共接口请求 @@ -39,7 +33,6 @@ | 127.0.0.1:828/jt808api/Tcp/Session/GetAll| GET| 基于Tcp管理会话服务-获取会话集合| | 127.0.0.1:828/jt808api/Tcp/Session/QueryTcpSessionByTerminalPhoneNo| POST| 基于Tcp管理会话服务-通过设备终端号查询对应会话| | 127.0.0.1:828/jt808api/Tcp/Session/RemoveByTerminalPhoneNo| POST| 基于Tcp管理会话服务-通过设备终端号移除对应会话| -| 127.0.0.1:828/jt808api/Tcp/GetAtomicCounter| GET| 基于Tcp消息包计数服务| ### 基于Udp接口请求 @@ -47,7 +40,6 @@ |:------|:------|:------| | 127.0.0.1:828/jt808api/Udp/Session/GetAll| GET| 基于Udp管理会话服务-获取会话集合| | 127.0.0.1:828/jt808api/Udp/Session/RemoveByTerminalPhoneNo| POST| 基于Udp管理会话服务-通过设备终端号移除对应会话| -| 127.0.0.1:828/jt808api/Udp/GetAtomicCounter| GET| 基于Udp消息包计数服务| ### 统一对象返回 JT808ResultDto\ @@ -240,55 +232,3 @@ "Data":true } ``` - -### 基于Tcp消息包计数服务 - -请求地址:Tcp/GetAtomicCounter - -请求方式:GET - -返回数据: - -|属性|数据类型|参数说明| -|------|:------:|:------| -| MsgSuccessCount| long| 消息包成功数| -| MsgFailCount| long| 消息包失败数| - -返回结果: - -``` counter -{ - "Message":"", - "Code":200, - "Data":{ - "MsgSuccessCount":10000, - "MsgFailCount":0 - } -} -``` - -### 基于Udp消息包计数服务 - -请求地址:Udp/GetAtomicCounter - -请求方式:GET - -返回数据: - -|属性|数据类型|参数说明| -|------|:------:|:------| -| MsgSuccessCount| long| 消息包成功数| -| MsgFailCount| long| 消息包失败数| - -返回结果: - -``` counter -{ - "Message":"", - "Code":200, - "Data":{ - "MsgSuccessCount":1000, - "MsgFailCount":0 - } -} -``` diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs b/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs index 265ecb3..8d1b064 100644 --- a/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs +++ b/src/JT808.Gateway.Tests/JT808.Gateway.NormalHosting/Program.cs @@ -53,20 +53,21 @@ namespace JT808.Gateway.NormalHosting //// options.UdpPort = 808; ////}) .AddNormalGateway(hostContext.Configuration) - .ReplaceNormalReplyMessageHandler() - .AddMsgLogging() - .AddTraffic() - .AddSessionNotice() - .AddTransmit(hostContext.Configuration) + //.ReplaceNormalReplyMessageHandler() + //.AddMsgLogging() + //.AddTraffic() + //.AddSessionNotice() + //.AddTransmit(hostContext.Configuration) .AddTcp() - .AddUdp() + //.AddUdp() + .AddHttp() ; //流量统计 - services.AddHostedService(); + //services.AddHostedService(); //grpc客户端调用 //services.AddHostedService(); //客户端测试 依赖AddClient()服务 - services.AddHostedService(); + //services.AddHostedService(); }); await serverHostBuilder.RunConsoleAsync(); diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj b/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj index f19de0f..06bb3fd 100644 --- a/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808.Gateway.Test.csproj @@ -7,6 +7,8 @@ + + @@ -22,7 +24,14 @@ + + + + Always + + + diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808HttpClientTest.cs b/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808HttpClientTest.cs new file mode 100644 index 0000000..7bd298c --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/JT808HttpClientTest.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using JT808.Gateway.WebApiClientTool; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace JT808.Gateway.Test +{ + public class JT808HttpClientTest + { + [Fact(DisplayName="客户端DI测试配置文件1")] + public void Test() + { + IServiceCollection serviceDescriptors = new ServiceCollection(); + serviceDescriptors.AddJT808WebApiClientTool(new Uri("http://localhost/"), "123456"); + } + + [Fact(DisplayName = "客户端DI测试配置文件2")] + public void Test1() + { + var builder = new ConfigurationBuilder(); + builder.AddJsonFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.json")); + IServiceCollection serviceDescriptors = new ServiceCollection(); + var configuration = builder.Build(); + var token = configuration.GetSection("JT808WebApiClientToolConfig:Token").Get(); + var uri = configuration.GetSection("JT808WebApiClientToolConfig:Uri").Get(); + Assert.Equal("123456", token); + Assert.Equal("http://localhost/", uri); + serviceDescriptors.AddJT808WebApiClientTool(builder.Build()); + } + + [Fact(DisplayName = "使用postman测试")] + public void Test2() + { + //头部添加或者url参数带有token=123456 + //TCP + //http://127.0.0.1:828/jt808api/Tcp/Session/GetAll + //http://127.0.0.1:828/jt808api/Tcp/Session/QueryTcpSessionByTerminalPhoneNo + //123456789 + //http://127.0.0.1:828/jt808api/Tcp/Session/RemoveByTerminalPhoneNo + //123456789 + ///http://127.0.0.1:828/jt808api/UnificationSend + //{"TerminalPhoneNo":"123456789","Data":"7e 01 02 7e"} + //{"TerminalPhoneNo":"123456789","Data":"7e01027e"} + } + } +} diff --git a/src/JT808.Gateway.Tests/JT808.Gateway.Test/appsettings.json b/src/JT808.Gateway.Tests/JT808.Gateway.Test/appsettings.json new file mode 100644 index 0000000..e5df207 --- /dev/null +++ b/src/JT808.Gateway.Tests/JT808.Gateway.Test/appsettings.json @@ -0,0 +1,6 @@ +{ + "JT808WebApiClientToolConfig": { + "Token": "123456", + "Uri": "http://localhost/" + } +} diff --git a/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.csproj b/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.csproj index a5877ab..9f9ae3b 100644 --- a/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.csproj +++ b/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.csproj @@ -22,6 +22,9 @@ JT808.Gateway.WebApiClientTool.xml + + JT808.Gateway.WebApiClientTool.xml + diff --git a/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.xml b/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.xml new file mode 100644 index 0000000..5fca67f --- /dev/null +++ b/src/JT808.Gateway.WebApiClientTool/JT808.Gateway.WebApiClientTool.xml @@ -0,0 +1,34 @@ + + + + JT808.Gateway.WebApiClientTool + + + + + 会话服务集合 + + + + + + 会话服务-通过设备终端号移除对应会话 + + + + + + + 统一下发信息 + + + + + + + 会话服务集合 + + + + + diff --git a/src/JT808.Gateway.WebApiClientTool/JT808HttpClient.cs b/src/JT808.Gateway.WebApiClientTool/JT808HttpClient.cs index c6b01bf..ee2c135 100644 --- a/src/JT808.Gateway.WebApiClientTool/JT808HttpClient.cs +++ b/src/JT808.Gateway.WebApiClientTool/JT808HttpClient.cs @@ -25,7 +25,7 @@ namespace JT808.Gateway.WebApiClientTool public async ValueTask>> GetTcpSessionAll() { var request = new HttpRequestMessage(HttpMethod.Get, JT808GatewayConstants.JT808WebApiRouteTable.SessionTcpGetAll); - var response = HttpClient.SendAsync(request).Result; + var response = await HttpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var data = await response.Content.ReadAsStreamAsync(); var value = await JsonSerializer.DeserializeAsync>>(data); @@ -41,7 +41,7 @@ namespace JT808.Gateway.WebApiClientTool { var request = new HttpRequestMessage(HttpMethod.Post, JT808GatewayConstants.JT808WebApiRouteTable.SessionRemoveByTerminalPhoneNo); request.Content = new StringContent(terminalPhoneNo); - var response = HttpClient.SendAsync(request).Result; + var response = await HttpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var data = await response.Content.ReadAsStreamAsync(); var value = await JsonSerializer.DeserializeAsync>(data); @@ -57,7 +57,7 @@ namespace JT808.Gateway.WebApiClientTool { var request = new HttpRequestMessage(HttpMethod.Post, JT808GatewayConstants.JT808WebApiRouteTable.UnificationSend); request.Content = new StringContent(JsonSerializer.Serialize(jT808UnificationSendRequestDto)); - var response = HttpClient.SendAsync(request).Result; + var response = await HttpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var data = await response.Content.ReadAsStreamAsync(); var value = await JsonSerializer.DeserializeAsync>(data); @@ -71,7 +71,7 @@ namespace JT808.Gateway.WebApiClientTool public async ValueTask>> GetUdpSessionAll() { var request = new HttpRequestMessage(HttpMethod.Get, JT808GatewayConstants.JT808WebApiRouteTable.SessionUdpGetAll); - var response = HttpClient.SendAsync(request).Result; + var response = await HttpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var data = await response.Content.ReadAsStreamAsync(); var value = await JsonSerializer.DeserializeAsync>>(data); diff --git a/src/JT808.Gateway.WebApiClientTool/JT808HttpClientExtensions.cs b/src/JT808.Gateway.WebApiClientTool/JT808HttpClientExtensions.cs index 11f6b1d..efee4ed 100644 --- a/src/JT808.Gateway.WebApiClientTool/JT808HttpClientExtensions.cs +++ b/src/JT808.Gateway.WebApiClientTool/JT808HttpClientExtensions.cs @@ -8,10 +8,11 @@ namespace JT808.Gateway.WebApiClientTool { public static class JT808HttpClientExtensions { - public static IServiceCollection AddJT808WebApiClientTool(this IServiceCollection serviceDescriptors, Uri webapiUri) + public static IServiceCollection AddJT808WebApiClientTool(this IServiceCollection serviceDescriptors, Uri webapiUri,string token) { serviceDescriptors.AddHttpClient("JT808WebApiClientTool", c => { + c.DefaultRequestHeaders.Add("token", token); c.BaseAddress = webapiUri; c.Timeout = TimeSpan.FromSeconds(3); }) @@ -23,7 +24,8 @@ namespace JT808.Gateway.WebApiClientTool { serviceDescriptors.AddHttpClient("JT808WebApiClientTool", c => { - c.BaseAddress = new Uri(configuration.GetSection("JT808WebApiClientToolConfig").Get()); + c.DefaultRequestHeaders.Add("token", configuration.GetSection("JT808WebApiClientToolConfig:Token").Get()); + c.BaseAddress = new Uri(configuration.GetSection("JT808WebApiClientToolConfig:Uri").Get()); c.Timeout = TimeSpan.FromSeconds(3); }) .AddTypedClient(); diff --git a/src/JT808.Gateway/Authorization/JT808AuthorizationDefault.cs b/src/JT808.Gateway/Authorization/JT808AuthorizationDefault.cs new file mode 100644 index 0000000..039938f --- /dev/null +++ b/src/JT808.Gateway/Authorization/JT808AuthorizationDefault.cs @@ -0,0 +1,48 @@ +using JT808.Gateway.Abstractions; +using JT808.Gateway.Configurations; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Security.Claims; +using System.Security.Principal; +using System.Text; + +namespace JT808.Gateway.Authorization +{ + class JT808AuthorizationDefault : IJT808Authorization + { + private IOptionsMonitor optionsMonitor; + public JT808AuthorizationDefault(IOptionsMonitor optionsMonitor) + { + this.optionsMonitor = optionsMonitor; + } + public bool Authorization(HttpListenerContext context, out IPrincipal principal) + { + var uriSpan = context.Request.Url.AbsoluteUri.AsSpan(); + var uriParamStr = uriSpan.Slice(uriSpan.IndexOf('?')+1).ToString().ToLower(); + var uriParams = uriParamStr.Split('&'); + var tokenParam = uriParams.FirstOrDefault(m => m.Contains("token")); + string tokenValue = string.Empty; + if (!string.IsNullOrEmpty(tokenParam)) + { + tokenValue = tokenParam.Split('=')[1]; + } + else + { + tokenValue = context.Request.Headers.Get("token"); + } + if (optionsMonitor.CurrentValue.WebApiToken == tokenValue) + { + principal = new ClaimsPrincipal(new GenericIdentity(tokenValue)); + return true; + } + else + { + principal = null; + return false; + } + } + } +} diff --git a/src/JT808.Gateway/Extensions/JT808HttpContextExtensions.cs b/src/JT808.Gateway/Extensions/JT808HttpContextExtensions.cs index 1a1c8ee..f2a3090 100644 --- a/src/JT808.Gateway/Extensions/JT808HttpContextExtensions.cs +++ b/src/JT808.Gateway/Extensions/JT808HttpContextExtensions.cs @@ -46,6 +46,15 @@ namespace JT808.Gateway.Extensions context.Response.Close(); } + public static void Http405(this HttpListenerContext context) + { + context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed; + context.Response.KeepAlive = false; + context.Response.ContentType = jsonType; + context.Response.OutputStream.Close(); + context.Response.Close(); + } + public static async ValueTask Http500(this HttpListenerContext context) { byte[] b = Encoding.UTF8.GetBytes("inner error"); diff --git a/src/JT808.Gateway/JT808GatewayExtensions.cs b/src/JT808.Gateway/JT808GatewayExtensions.cs index 539798a..2be0b6c 100644 --- a/src/JT808.Gateway/JT808GatewayExtensions.cs +++ b/src/JT808.Gateway/JT808GatewayExtensions.cs @@ -1,4 +1,5 @@ using JT808.Gateway.Abstractions; +using JT808.Gateway.Authorization; using JT808.Gateway.Configurations; using JT808.Gateway.Enums; using JT808.Gateway.Handlers; @@ -77,6 +78,7 @@ namespace JT808.Gateway public static IJT808GatewayBuilder AddHttp(this IJT808GatewayBuilder config) { + config.JT808Builder.Services.AddSingleton(); config.JT808Builder.Services.AddSingleton(); config.JT808Builder.Services.AddHostedService(); return config; @@ -85,6 +87,7 @@ namespace JT808.Gateway public static IJT808GatewayBuilder AddHttp(this IJT808GatewayBuilder config) where TJT808MsgIdDefaultWebApiHandler: JT808MsgIdDefaultWebApiHandler { + config.JT808Builder.Services.AddSingleton(); config.JT808Builder.Services.AddSingleton(typeof(JT808MsgIdDefaultWebApiHandler),typeof(TJT808MsgIdDefaultWebApiHandler)); config.JT808Builder.Services.AddHostedService(); return config; diff --git a/src/JT808.Gateway/JT808HttpServer.cs b/src/JT808.Gateway/JT808HttpServer.cs index 208cc77..085d1cd 100644 --- a/src/JT808.Gateway/JT808HttpServer.cs +++ b/src/JT808.Gateway/JT808HttpServer.cs @@ -10,7 +10,9 @@ using System; using System.Buffers; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net; +using System.Net.Http; using System.Net.WebSockets; using System.Security.Principal; using System.Text; @@ -62,14 +64,19 @@ namespace JT808.Gateway Logger.LogWarning(ex, $"{ex.Message}:使用cmd命令[netsh http add urlacl url=http://*:{Configuration.WebApiPort}/ user=Everyone]"); } Logger.LogInformation($"JT808 Http Server start at {IPAddress.Any}:{Configuration.WebApiPort}."); - Task.Factory.StartNew(async() => + Task.Factory.StartNew(async () => { while (listener.IsListening) { var context = await listener.GetContextAsync(); try { - if (authorization.Authorization(context,out var principal)) + if (context.Request.RawUrl.StartsWith("/favicon.ico")) + { + context.Http404(); + continue; + } + if (authorization.Authorization(context, out var principal)) { await ProcessRequestAsync(context, principal); } @@ -90,18 +97,37 @@ namespace JT808.Gateway private async ValueTask ProcessRequestAsync(HttpListenerContext context, IPrincipal principal) { - if(context.Request.RawUrl.StartsWith("/favicon.ico")) + var router = MsgIdDefaultWebApiHandler.HandlerDict.FirstOrDefault(f => context.Request.RawUrl.StartsWith(f.Key)); + if (router.Key == null) { context.Http404(); return; } - var uri = new Uri(context.Request.RawUrl); - //todo: 处理对应的handler - string url = uri.AbsolutePath; - var queryParams = uri.Query.Substring(1, uri.Query.Length - 1).Split('&'); - if (queryParams.Length < 2) { - context.Http404(); - return; + if(context.Request.HttpMethod == HttpMethod.Get.Method) + { + var index = context.Request.Url.AbsoluteUri.IndexOf('?'); + if (index > 0) + { + var uriParamStr = context.Request.Url.AbsoluteUri.Substring(index + 1).ToString(); + await context.HttpSend(router.Value(uriParamStr)); + } + else + { + await context.HttpSend(router.Value("")); + } + } + else if(context.Request.HttpMethod == HttpMethod.Post.Method) + { + string json = string.Empty; + using (var reader = new StreamReader(context.Request.InputStream,context.Request.ContentEncoding)) + { + json = reader.ReadToEnd(); + } + await context.HttpSend(router.Value(json)); + } + else + { + context.Http405(); } }