diff --git a/src/InterfaceForward.Application/ForwardCore/DefaultForwardFlow.cs b/src/InterfaceForward.Application/ForwardCore/DefaultForwardFlow.cs index 2e148c9..11a1cb2 100644 --- a/src/InterfaceForward.Application/ForwardCore/DefaultForwardFlow.cs +++ b/src/InterfaceForward.Application/ForwardCore/DefaultForwardFlow.cs @@ -421,7 +421,8 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency Dictionary nameValueCollection; if (context.FormFieldList.Count != 0) { - var field = context.FormFieldList.FirstOrDefault(x => x.Value == GlobalConst.FromMappingBody); + var field = context.FormFieldList.FirstOrDefault(x => + x.Value is GlobalConst.FromMappingBody or GlobalConst.FromBody); if (field != null) field.Value = body; nameValueCollection = context.FormFieldList.ToDictionary(x => x.Name, x => x.Value); } @@ -532,17 +533,18 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency // Query / Header / 表单 foreach (var item in context.QueryFieldList) { - item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description); + item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description, keepMappingBodyPlaceholder: false); } foreach (var item in context.HeaderFieldList) { - item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description); + item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description, keepMappingBodyPlaceholder: false); } foreach (var item in context.FormFieldList) { - item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description); + // FormUrlEncoded 的 Body KV 保留占位符,交由 SetContentType 用序列化后的 TargetInterfaceInput 填充 + item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description, keepMappingBodyPlaceholder: true); } // 绑定body部分的字段 @@ -578,7 +580,7 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency } } - string ReplaceFormPlaceholder(string name, string value, string? description) + string ReplaceFormPlaceholder(string name, string value, string? description, bool keepMappingBodyPlaceholder) { return value switch { @@ -589,9 +591,11 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency GlobalConst.DateTime => TurnDate(now, description), GlobalConst.Url => context.TargetInterface.RequestAddress, GlobalConst.FromAccount => context.GetAccountFieldValueOrNull(name) ?? string.Empty, - GlobalConst.FromMappingBody => context.TargetInterface.ContentType == ContentType.FormUrlEncoded - ? GlobalConst.FromMappingBody - : JsonConvert.SerializeObject(context.OriginalInterfaceMappedInput), + // Body 表单在 FormUrlEncoded 时保留占位符;Query/Header 必须立刻展开,否则会原样发出 + GlobalConst.FromMappingBody or GlobalConst.FromBody => + keepMappingBodyPlaceholder && context.TargetInterface.ContentType == ContentType.FormUrlEncoded + ? GlobalConst.FromMappingBody + : JsonConvert.SerializeObject(context.OriginalInterfaceMappedInput), _ => value }; } diff --git a/src/InterfaceForward.Application/Services/Interface/InterfaceService.cs b/src/InterfaceForward.Application/Services/Interface/InterfaceService.cs index 2cb11c5..e8ad644 100644 --- a/src/InterfaceForward.Application/Services/Interface/InterfaceService.cs +++ b/src/InterfaceForward.Application/Services/Interface/InterfaceService.cs @@ -108,10 +108,7 @@ public class InterfaceService : ApplicationService // 构造参数 var paras = await InterfaceRepository.GetParameterListByIdAsync(id); - // 入参树形列表 - res.InParameterList = interfaceEntity.IsUpStream - ? paras.Where(x => x.IsInPara && x.ParaKind == ParameterParaKind.Normal).ToList() - : []; + res.RequestBodyParameterList = !interfaceEntity.IsUpStream && interfaceEntity.ContentType is ContentType.Json or ContentType.Xml ? paras.Where(x => x.IsInPara && x.ParaKind == ParameterParaKind.Normal).ToList() : []; diff --git a/tests/InterfaceForward.Application.Tests/DefaultForwardFlowTests.cs b/tests/InterfaceForward.Application.Tests/DefaultForwardFlowTests.cs index 1781af9..b5e505c 100644 --- a/tests/InterfaceForward.Application.Tests/DefaultForwardFlowTests.cs +++ b/tests/InterfaceForward.Application.Tests/DefaultForwardFlowTests.cs @@ -96,6 +96,69 @@ public class DefaultForwardFlowTests Assert.Equal("{\"orderId\":\"A001\"}", Assert.Single(context.QueryFieldList).Value); } + [Fact] + public void ReplacePlaceholder_ShouldExpandQueryFromMappingBodyForFormUrlEncoded() + { + var flow = new TestForwardFlow(); + var context = new ForwardCoreContext + { + TargetInterface = new InterfaceDto + { + ContentType = ContentType.FormUrlEncoded, + RequestAddress = "https://example.com/openapi" + }, + OriginalInterfaceMappedInput = new JObject { ["orderId"] = "A001" }, + QueryFieldList = + [ + new InterfaceFormFieldDto + { + Name = "bizData", + Value = GlobalConst.FromMappingBody + } + ], + FormFieldList = + [ + new InterfaceFormFieldDto + { + Name = "notifyBizEventDTO", + Value = GlobalConst.FromMappingBody + } + ] + }; + + flow.ReplacePlaceholder(context); + + Assert.Equal("{\"orderId\":\"A001\"}", Assert.Single(context.QueryFieldList).Value); + Assert.Equal(GlobalConst.FromMappingBody, Assert.Single(context.FormFieldList).Value); + } + + [Fact] + public void ReplacePlaceholder_ShouldExpandLegacyFromBodyInQuery() + { + var flow = new TestForwardFlow(); + var context = new ForwardCoreContext + { + TargetInterface = new InterfaceDto + { + ContentType = ContentType.FormUrlEncoded, + RequestAddress = "https://example.com/openapi" + }, + OriginalInterfaceMappedInput = new JObject { ["orderId"] = "A001" }, + QueryFieldList = + [ + new InterfaceFormFieldDto + { + Name = "bizData", + Value = GlobalConst.FromBody + } + ] + }; + + flow.ReplacePlaceholder(context); + + Assert.Equal("{\"orderId\":\"A001\"}", Assert.Single(context.QueryFieldList).Value); + } + class TestForwardFlow : DefaultForwardFlow { public void SetContentTypeForTest(ForwardCoreContext context, HttpRequestMessage message)