Browse Source

Merge pull request #23032 from abpframework/WebClientInfoProvider

Use `MyCSharp.HttpUserAgentParser` to replace `DeviceDetector.NET` for better performance.
pull/23058/head
Engincan VESKE 8 months ago
committed by GitHub
parent
commit
43d91d7eba
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      Directory.Packages.props
  2. 1
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs
  3. 2
      framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
  4. 3
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs
  5. 36
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs
  6. 2
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationScheme.cs
  7. 8
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderDto.cs
  8. 26
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController.cs
  9. 36
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController_Tests.cs

2
Directory.Packages.props

@ -29,7 +29,7 @@
<PackageVersion Include="Dapper" Version="2.1.66" />
<PackageVersion Include="Dapr.AspNetCore" Version="1.15.4" />
<PackageVersion Include="Dapr.Client" Version="1.15.4" />
<PackageVersion Include="DeviceDetector.NET" Version="6.4.2" />
<PackageVersion Include="MyCSharp.HttpUserAgentParser" Version="3.0.25" />
<PackageVersion Include="Devart.Data.Oracle.EFCore" Version="10.4.235.9" />
<PackageVersion Include="DistributedLock.Core" Version="1.0.8" />
<PackageVersion Include="DistributedLock.Redis" Version="1.0.3" />

1
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/DefaultAbpRequestLocalizationOptionsProvider.cs

@ -4,7 +4,6 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DeviceDetectorNET;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.DependencyInjection;

2
framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj

@ -31,7 +31,7 @@
<ProjectReference Include="..\Volo.Abp.VirtualFileSystem\Volo.Abp.VirtualFileSystem.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" />
<PackageReference Include="IdentityModel" />
<PackageReference Include="DeviceDetector.NET" />
<PackageReference Include="MyCSharp.HttpUserAgentParser" />
</ItemGroup>
</Project>

3
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Hosting.StaticWebAssets;
using Microsoft.AspNetCore.RequestLocalization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using MyCSharp.HttpUserAgentParser.DependencyInjection;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.Auditing;
@ -59,6 +60,8 @@ public class AbpAspNetCoreModule : AbpModule
context.Services.AddAbpDynamicOptions<RequestLocalizationOptions, AbpRequestLocalizationOptionsManager>();
StaticWebAssetsLoader.UseStaticWebAssets(context.Services.GetHostingEnvironment(), context.Services.GetConfiguration());
context.Services.AddHttpUserAgentCachedParser();
}
private static void AddAspNetServices(IServiceCollection services)

36
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs

@ -1,7 +1,8 @@
using System;
using DeviceDetectorNET;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MyCSharp.HttpUserAgentParser;
using MyCSharp.HttpUserAgentParser.Providers;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.WebClientInfo;
@ -11,13 +12,16 @@ public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransie
{
protected ILogger<HttpContextWebClientInfoProvider> Logger { get; }
protected IHttpContextAccessor HttpContextAccessor { get; }
protected IHttpUserAgentParserProvider HttpUserAgentParser { get; }
public HttpContextWebClientInfoProvider(
ILogger<HttpContextWebClientInfoProvider> logger,
IHttpContextAccessor httpContextAccessor)
IHttpContextAccessor httpContextAccessor,
IHttpUserAgentParserProvider httpUserAgentParser)
{
Logger = logger;
HttpContextAccessor = httpContextAccessor;
HttpUserAgentParser = httpUserAgentParser;
}
public string? BrowserInfo => GetBrowserInfo();
@ -46,27 +50,21 @@ public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransie
protected virtual string? GetDeviceInfo()
{
string? deviceInfo = null;
var deviceDetector = new DeviceDetector(GetBrowserInfo());
deviceDetector.Parse();
if (!deviceDetector.IsParsed())
var browserInfo = GetBrowserInfo();
if (browserInfo.IsNullOrWhiteSpace())
{
return deviceInfo;
}
var osInfo = deviceDetector.GetOs();
if (osInfo.Success)
{
deviceInfo = osInfo.Match.Name;
return null;
}
var clientInfo = deviceDetector.GetClient();
if (clientInfo.Success)
var httpUserAgentInformation = HttpUserAgentParser.Parse(browserInfo);
switch (httpUserAgentInformation.Type)
{
deviceInfo = deviceInfo.IsNullOrWhiteSpace() ? clientInfo.Match.Name : deviceInfo + " " + clientInfo.Match.Name;
case HttpUserAgentType.Browser:
case HttpUserAgentType.Robot:
return (httpUserAgentInformation.Platform.HasValue ? httpUserAgentInformation.Platform.Value.Name + " " : string.Empty) + httpUserAgentInformation.Name;
case HttpUserAgentType.Unknown:
default:
return httpUserAgentInformation.UserAgent;
}
return deviceInfo;
}
}

2
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/FakeAuthenticationScheme.cs

@ -1,8 +1,8 @@
using System;
using System.Linq;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using DeviceDetectorNET;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

8
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderDto.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.AspNetCore.Mvc.WebClientInfoProvider;
public class WebClientInfoProviderDto
{
public string BrowserInfo { get; set; }
public string DeviceInfo { get; set; }
}

26
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController.cs

@ -0,0 +1,26 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.WebClientInfo;
namespace Volo.Abp.AspNetCore.Mvc.WebClientInfoProvider;
[Route("api/web-client-info")]
public class WebClientInfoProviderTestController : AbpController
{
private IWebClientInfoProvider _webClientInfoProvider { get; }
public WebClientInfoProviderTestController(IWebClientInfoProvider webClientInfoProvider)
{
_webClientInfoProvider = webClientInfoProvider;
}
[HttpGet]
public Task<WebClientInfoProviderDto> GetAsync()
{
return Task.FromResult(new WebClientInfoProviderDto
{
BrowserInfo = _webClientInfoProvider.BrowserInfo,
DeviceInfo = _webClientInfoProvider.DeviceInfo
});
}
}

36
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/WebClientInfoProvider/WebClientInfoProviderTestController_Tests.cs

@ -0,0 +1,36 @@
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.WebClientInfoProvider;
public class WebClientInfoProviderTestController_Tests : AspNetCoreMvcTestBase
{
[Theory]
[InlineData("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Windows 10 Chrome")]
[InlineData("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Mac OS X Chrome")]
[InlineData("PostmanRuntime/7.43.4", "PostmanRuntime/7.43.4")]
[InlineData("curl/7.64.1", "curl/7.64.1")]
[InlineData("Mozilla/5.0 (compatible; MojeekBot/0.11; +mojeek.com/bot.html)", "MojeekBot")]
public async Task TestAsync(string ua, string device)
{
var clientInfo = await GetWebClientInfoAsync(ua);
clientInfo.ShouldNotBeNull();
clientInfo.BrowserInfo.ShouldBe(ua);
clientInfo.DeviceInfo.ShouldBe(device);
}
private async Task<WebClientInfoProviderDto> GetWebClientInfoAsync(string userAgent )
{
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, "api/web-client-info"))
{
requestMessage.Headers.Add("User-Agent", userAgent);
var response = await Client.SendAsync(requestMessage);
response.StatusCode.ShouldBe(HttpStatusCode.OK);
return JsonSerializer.Deserialize<WebClientInfoProviderDto>(await response.Content.ReadAsStringAsync(), JsonSerializerOptions.Web);
}
}
}
Loading…
Cancel
Save