XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEExtension.NetCore.ServerInteractive

[DLL] Server interaction extension, including user identity verification and querying in conjunction with AutoConfig

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFEExtension.NetCore.ServerInteractive

fix: address review comments - best-match wildcards, priority ordering, and name→wildcard validation

1. TryMatchWildcardStandardService now uses priority-based best-match (most specific pattern wins) consistent with server-side XFEServerCore. 2. StandardClientInstanceRequestDictionary exact match now precedes wildcard fallback to prevent broad wildcards from swallowing instance requests. 3. AddRequest<T>() throws InvalidOperationException when a Name alias maps to a wildcard path, preventing literal '*' in request URLs. Agent-Logs-Url: https://github.com/XFEstudio/XFEExtension.NetCore.ServerInteractive/sessions/595a9bed-b384-4e66-a18b-640f71419a7b Co-authored-by: XFEstudio <132526994+XFEstudio@users.noreply.github.com>

7b6dfa9
copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
提交于

代码差异

2 个文件 +47 -24
Modified XFEExtension.NetCore.ServerInteractive/Utilities/Requester/XFEClientRequester.cs +43 -24
@@ -101,6 +101,23 @@ public abstract class XFEClientRequester : IRequesterBase
101 101 result.Message = response;
102 102 }
103 103 }
104 else if (StandardClientInstanceRequestDictionary.TryGetValue(serviceName, out var instance))
105 {
106 var (response, code) = await InteractiveHelper.GetServerResponse(RequestAddress + $"/{serviceName}", instance.ConstructBody(Session, DeviceInfo, parameters), _jsonSerializerOptions);
107 result.StatusCode = code;
108 if (code == HttpStatusCode.OK)
109 {
110 var requestResult = instance.ProcessResponse?.Invoke(response);
111 MessageReceived?.Invoke(this, new ServerInteractiveEventArgsImpl("Success", code));
112 result.Message = "Success";
113 result.Result = requestResult ?? new();
114 }
115 else
116 {
117 MessageReceived?.Invoke(this, new ServerInteractiveEventArgsImpl(response, code));
118 result.Message = response;
119 }
120 }
104 121 else if (TryMatchWildcardStandardService(serviceName, out var wildcardFactory, out var matchedPattern))
105 122 {
106 123 var xFEService = wildcardFactory!();
@@ -134,23 +151,6 @@ public abstract class XFEClientRequester : IRequesterBase
134 151 result.Message = response;
135 152 }
136 153 }
137 else if (StandardClientInstanceRequestDictionary.TryGetValue(serviceName, out var instance))
138 {
139 var (response, code) = await InteractiveHelper.GetServerResponse(RequestAddress + $"/{serviceName}", instance.ConstructBody(Session, DeviceInfo, parameters), _jsonSerializerOptions);
140 result.StatusCode = code;
141 if (code == HttpStatusCode.OK)
142 {
143 var requestResult = instance.ProcessResponse?.Invoke(response);
144 MessageReceived?.Invoke(this, new ServerInteractiveEventArgsImpl("Success", code));
145 result.Message = "Success";
146 result.Result = requestResult ?? new();
147 }
148 else
149 {
150 MessageReceived?.Invoke(this, new ServerInteractiveEventArgsImpl(response, code));
151 result.Message = response;
152 }
153 }
154 154 return result;
155 155 }
156 156 catch (Exception ex)
@@ -163,7 +163,7 @@ public abstract class XFEClientRequester : IRequesterBase
163 163 }
164 164
165 165 /// <summary>
166 /// 尝试通过通配符模式匹配标准请求服务
166 /// 尝试通过通配符模式匹配标准请求服务(选择最具体的匹配模式,与服务端行为一致)
167 167 /// </summary>
168 168 /// <param name="serviceName">请求路径</param>
169 169 /// <param name="factory">匹配到的服务工厂</param>
@@ -171,17 +171,36 @@ public abstract class XFEClientRequester : IRequesterBase
171 171 /// <returns>是否匹配成功</returns>
172 172 private bool TryMatchWildcardStandardService(string serviceName, out Func<IStandardRequestService>? factory, out string? matchedPattern)
173 173 {
174 foreach (var (pattern, serviceFactory) in WildcardStandardRequestServiceList)
174 // 在所有命中的候选中选择最具体的模式(字面量段越多越优先),避免结果依赖注册顺序
175 static int GetWildcardPatternPriority(string pattern)
175 176 {
176 if (RouteMatchHelper.MatchWildcardRoute(pattern, serviceName))
177 var segments = pattern.Split('/');
178 var literalSegmentCount = 0;
179 var wildcardSegmentCount = 0;
180 foreach (var segment in segments)
177 181 {
178 factory = serviceFactory;
179 matchedPattern = pattern;
180 return true;
182 if (segment == "*")
183 wildcardSegmentCount++;
184 else
185 literalSegmentCount++;
181 186 }
187 return (literalSegmentCount * 1000) - (wildcardSegmentCount * 10) + pattern.Length;
182 188 }
189
190 var bestPriority = int.MinValue;
183 191 factory = null;
184 192 matchedPattern = null;
185 return false;
193
194 foreach (var (pattern, serviceFactory) in WildcardStandardRequestServiceList)
195 {
196 if (!RouteMatchHelper.MatchWildcardRoute(pattern, serviceName)) continue;
197 var currentPriority = GetWildcardPatternPriority(pattern);
198 if (currentPriority <= bestPriority) continue;
199 bestPriority = currentPriority;
200 factory = serviceFactory;
201 matchedPattern = pattern;
202 }
203
204 return factory is not null;
186 205 }
187 206 }
Modified XFEExtension.NetCore.ServerInteractive/Utilities/Requester/XFEClientRequesterBuilder.cs +4 -0
@@ -66,6 +66,7 @@ public abstract class XFEClientRequesterBuilder : XFEBuilderBase<XFEClientReques
66 66 throw new InvalidOperationException($"类型 {typeof(T).Name} 的 RequestPoints/ResponsePoints/RequestRouteMap 为空,请确保已使用[Request]或[Response]标记方法");
67 67
68 68 // 为每个路径/名称注册服务工厂(通配符路径注册到通配符列表,其余注册到标准字典)
69 // 对于Name别名,需检查其目标路径是否为通配符:Name→通配符路径不支持,因为无法确定具体请求路径
69 70 foreach (var key in routeKeys)
70 71 {
71 72 if (RouteMatchHelper.IsWildcardRoute(key))
@@ -81,6 +82,9 @@ public abstract class XFEClientRequesterBuilder : XFEBuilderBase<XFEClientReques
81 82 }
82 83 else
83 84 {
85 // 检查Name别名是否映射到通配符路径
86 if (probeService.RequestRouteMap.TryGetValue(key, out var targetPath) && targetPath != key && RouteMatchHelper.IsWildcardRoute(targetPath))
87 throw new InvalidOperationException($"名称别名 '{key}' 映射到通配符路径 '{targetPath}',不支持通过名称调用通配符路由,请直接使用具体路径进行请求");
84 88 _standardRequestServiceDictionary.Add(key, () =>
85 89 {
86 90 var inst = new T();