diff --git a/lib/common/path.dart b/lib/common/path.dart index 78c0d33..cb9d69a 100644 --- a/lib/common/path.dart +++ b/lib/common/path.dart @@ -188,10 +188,17 @@ class AppPath { Future getProvidersFilePath( String id, String type, + String providerName, String url, ) async { final directory = await profilesPath; - return join(directory, 'providers', id, type, url.toMd5()); + return join( + directory, + 'providers', + id, + type, + '${providerName.toMd5()}-${url.toMd5()}', + ); } Future get tempPath async { diff --git a/lib/common/task.dart b/lib/common/task.dart index 95056fc..93ae0f0 100644 --- a/lib/common/task.dart +++ b/lib/common/task.dart @@ -141,13 +141,17 @@ Future> _makeRealProfileTask( final addedRules = data.addedRules; final appendSystemDns = data.appendSystemDns; final defaultUA = data.defaultUA; - String getProvidersFilePathInner(String type, String url) { + String getProvidersFilePathInner( + String type, + String providerName, + String url, + ) { return join( profilesPath, 'providers', profileId.toString(), type, - url.toMd5(), + '${providerName.toMd5()}-${url.toMd5()}', ); } @@ -203,6 +207,7 @@ Future> _makeRealProfileTask( if (proxyProvider['url'] != null) { proxyProvider['path'] = getProvidersFilePathInner( 'proxies', + key.toString(), proxyProvider['url'], ); } @@ -218,6 +223,7 @@ Future> _makeRealProfileTask( if (ruleProvider['url'] != null) { ruleProvider['path'] = getProvidersFilePathInner( 'rules', + key.toString(), ruleProvider['url'], ); } diff --git a/test/common/task_test.dart b/test/common/task_test.dart index bf76fac..e266d74 100644 --- a/test/common/task_test.dart +++ b/test/common/task_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:fl_clash/common/task.dart'; +import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/models/models.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -41,6 +41,58 @@ void main() { expect(result['ip-version'], 'ipv6-prefer'); }); + test( + 'proxy providers with the same URL receive separate cache files', + () async { + const url = 'https://subscription.example/providers'; + final rawConfig = { + 'proxy-providers': { + 'provider-one': { + 'type': 'http', + 'url': url, + 'header': { + 'Id': ['file-one'], + }, + }, + 'provider-two': { + 'type': 'http', + 'url': url, + 'header': { + 'Id': ['file-two'], + }, + }, + }, + }; + final profile = await makeRealProfileTask( + MakeRealProfileState( + profilesPath: '/tmp/flclash-provider-cache-test', + profileId: 15, + rawConfig: rawConfig, + realPatchConfig: const PatchClashConfig(), + overrideDns: false, + appendSystemDns: false, + proxyGroups: const [], + rules: const [], + addedRules: const [], + defaultUA: 'FlClash-Test', + ), + ); + + expect( + profile.a, + contains( + 'providers/15/proxies/${'provider-one'.toMd5()}-${url.toMd5()}', + ), + ); + expect( + profile.a, + contains( + 'providers/15/proxies/${'provider-two'.toMd5()}-${url.toMd5()}', + ), + ); + }, + ); + test('profile ipv6 false also wins over the client fallback', () { final result = applyCorePatchConfig( rawConfig: {'ipv6': false},