1- // Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
1+ // Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
22// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33// Website: https://www.blazor.zone or https://argozhang.github.io/
44
5+ using IP2Region . Net . Abstractions ;
56using IP2Region . Net . XDB ;
67using Microsoft . Extensions . Logging ;
78using Microsoft . Extensions . Options ;
9+ using System . Collections . Concurrent ;
10+ using System . Net ;
811
912namespace BootstrapBlazor . Components ;
1013
@@ -24,51 +27,64 @@ public IP2RegionService(IOptions<BootstrapBlazorOptions> options, IOptions<IP2Re
2427 _options = options ;
2528 _ipOptions = ipRegionOptions ;
2629 _logger = logger ;
27-
28- Task . Run ( InitSearch , CancellationToken . None ) . ConfigureAwait ( false ) ;
2930 }
3031
3132 private readonly IOptions < BootstrapBlazorOptions > _options ;
3233 private readonly IOptions < IP2RegionOptions > _ipOptions ;
3334 private readonly ILogger < IP2RegionService > _logger ;
3435 private readonly TaskCompletionSource _tcs = new ( ) ;
35- private Searcher ? _search ;
36+ private ConcurrentDictionary < string , ISearcher ? > _searchCache = [ ] ;
3637
3738 /// <summary>
3839 /// <inheritdoc/>
3940 /// </summary>
4041 /// <param name="ip"></param>
41- protected override async Task < string ? > LocateByIp ( string ip )
42+ protected override Task < string ? > LocateByIp ( string ip )
4243 {
43- await _tcs . Task ;
44-
4544 string ? result = null ;
46- if ( _search != null && _options . Value . WebClientOptions . EnableIpLocator )
45+ if ( _options . Value . WebClientOptions . EnableIpLocator && IPAddress . TryParse ( ip , out var address ) )
4746 {
48- result = _search . Search ( ip ) ;
47+ ISearcher ? searcher = null ;
48+ if ( address . AddressFamily == System . Net . Sockets . AddressFamily . InterNetwork )
49+ {
50+ searcher = CreateSearcher ( "ip2region_v4.xdb" ) ;
51+ }
52+ else if ( address . AddressFamily == System . Net . Sockets . AddressFamily . InterNetworkV6 )
53+ {
54+ searcher = CreateSearcher ( "ip2region_v6.xdb" ) ;
55+ }
56+ result = searcher ? . Search ( ip ) ;
4957 }
50- return result ;
58+ return Task . FromResult ( result ) ;
5159 }
5260
53- private void InitSearch ( )
61+ private ISearcher ? CreateSearcher ( string xdbFile ) => _searchCache . GetOrAdd ( xdbFile , key =>
5462 {
55- var xdbPath = _ipOptions . Value . XdbPath ?? Path . Combine ( AppContext . BaseDirectory , "ip2region" , "ip2region.xdb" ) ;
63+ var xdbPath = _ipOptions . Value . XdbPath ?? Path . Combine ( AppContext . BaseDirectory , "ip2region" , xdbFile ) ;
5664 if ( ! File . Exists ( xdbPath ) )
5765 {
5866 _logger . LogWarning ( "IP2Region xdb file not found, please check the file path: {dbPath}" , xdbPath ) ;
59- return ;
67+ return null ;
6068 }
6169
70+ ISearcher ? searcher = null ;
6271 try
6372 {
64- _search = new Searcher ( CachePolicy . Content , xdbPath ) ;
65- _logger . LogInformation ( "IP2Region xdb file {dbPath} loaded" , xdbPath ) ;
73+ var cachePolicy = _ipOptions . Value . CachePolicy ;
74+ searcher = new Searcher ( cachePolicy , xdbPath ) ;
75+
76+ if ( _logger . IsEnabled ( LogLevel . Information ) )
77+ {
78+ _logger . LogInformation ( "IP2Region xdb file {dbPath} loaded" , xdbPath ) ;
79+ }
6680 _tcs . TrySetResult ( ) ;
6781 }
6882 catch ( Exception ex )
6983 {
7084 _tcs . TrySetException ( ex ) ;
7185 _logger . LogError ( ex , "IP2Region xdb file path: {dbPath}" , xdbPath ) ;
7286 }
73- }
87+
88+ return searcher ;
89+ } ) ;
7490}
0 commit comments