From db2cea4c8b368df666ca4a8b37423799686fbcb5 Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Mon, 21 Sep 2026 15:42:49 +0800 Subject: [PATCH 1/8] init test --- .gitea/workflows/deploy.yml | 57 ++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 49dc933..c69ca77 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,9 +1,19 @@ +# 复制到 itfx 仓库 .gitea/workflows/deploy.yml +# push master/main → prod;push test → test name: Build and Deploy on: push: - branches: [master, main] + branches: [master, main, test] workflow_dispatch: + inputs: + target: + description: Deploy target (仅手动;push 时由分支决定) + type: choice + options: + - prod + - test + default: prod env: CSPROJ: src/InterfaceForward.Api/InterfaceForward.Api.csproj @@ -20,15 +30,48 @@ jobs: - name: Build and deploy run: | set -euxo pipefail - export KUBECONFIG=/etc/rancher/k3s/k3s.yaml - TAG="${{ gitea.sha }}" - IMG="${{ env.TCR_REGISTRY }}/${{ env.TCR_NAMESPACE }}/${{ env.IMAGE_NAME }}:${TAG}" + REF="${{ gitea.ref_name }}" + + if [[ "${{ gitea.event_name }}" == "workflow_dispatch" ]]; then + TARGET="${{ inputs.target }}" + TARGET="${TARGET:-prod}" + else + case "$REF" in + test) TARGET=test ;; + *) TARGET=prod ;; + esac + fi + + SHA="${{ gitea.sha }}" REPO="${{ gitea.repository }}" - REPO="${REPO:-${{ github.repository }}}" test -n "$REPO" && [[ "$REPO" == */* ]] - echo "REPO=$REPO TAG=$TAG host=$(hostname)" + + case "$TARGET" in + test) TAG="test-${SHA}" ;; + *) TAG="${SHA}" ;; + esac + + IMG="${{ env.TCR_REGISTRY }}/${{ env.TCR_NAMESPACE }}/${{ env.IMAGE_NAME }}:${TAG}" + echo "TARGET=$TARGET REF=$REF REPO=$REPO TAG=$TAG host=$(hostname)" + + export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + unset NAMESPACE cd /data/k3s ./scripts/ci-publish-container.sh "$REPO" "${{ env.CSPROJ }}" \ - "${{ env.IMAGE_NAME }}" "$TAG" "$TAG" + "${{ env.IMAGE_NAME }}" "$TAG" "$SHA" + + case "$TARGET" in + test) + export KUBECONFIG=/root/.kube/k3s-test.yaml + export NAMESPACE=test + export MANIFEST_ROOT=/data/k3s-test + ;; + *) + export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + export NAMESPACE=prod + export MANIFEST_ROOT=/data/k3s + ;; + esac + test -f "$KUBECONFIG" ./scripts/ci-deploy-api.sh "${{ env.DEPLOY_NAME }}" \ "${{ env.CONTAINER_NAME }}" "$IMG" -- 2.45.2 From f0f648fb791ab7ccd25d5dc3900ba3a32b9d65ce Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Mon, 21 Sep 2026 15:44:08 +0800 Subject: [PATCH 2/8] test --- .gitea/workflows/deploy.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index c69ca77..619b79d 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -6,14 +6,6 @@ on: push: branches: [master, main, test] workflow_dispatch: - inputs: - target: - description: Deploy target (仅手动;push 时由分支决定) - type: choice - options: - - prod - - test - default: prod env: CSPROJ: src/InterfaceForward.Api/InterfaceForward.Api.csproj -- 2.45.2 From 3f3da5bd3702f8e356fe7629040c95d7afab2c7a Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Mon, 21 Sep 2026 15:59:36 +0800 Subject: [PATCH 3/8] test --- .gitea/workflows/deploy.yml | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 619b79d..f8a63d2 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,11 +1,10 @@ # 复制到 itfx 仓库 .gitea/workflows/deploy.yml -# push master/main → prod;push test → test +# push master → prod;push test → test name: Build and Deploy on: push: - branches: [master, main, test] - workflow_dispatch: + branches: [master, test] env: CSPROJ: src/InterfaceForward.Api/InterfaceForward.Api.csproj @@ -23,16 +22,11 @@ jobs: run: | set -euxo pipefail REF="${{ gitea.ref_name }}" - - if [[ "${{ gitea.event_name }}" == "workflow_dispatch" ]]; then - TARGET="${{ inputs.target }}" - TARGET="${TARGET:-prod}" - else - case "$REF" in - test) TARGET=test ;; - *) TARGET=prod ;; - esac - fi + case "$REF" in + test) TARGET=test ;; + master) TARGET=prod ;; + *) echo "unsupported branch: $REF"; exit 1 ;; + esac SHA="${{ gitea.sha }}" REPO="${{ gitea.repository }}" -- 2.45.2 From 9016dc4116d28f8c8021870fbe83758676f39421 Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Tue, 22 Sep 2026 15:50:02 +0800 Subject: [PATCH 4/8] cicd --- .gitea/workflows/deploy.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index f8a63d2..ba05476 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -48,7 +48,7 @@ jobs: case "$TARGET" in test) - export KUBECONFIG=/root/.kube/k3s-test.yaml + export KUBECONFIG=/etc/rancher/k3s/k3s-test.yaml export NAMESPACE=test export MANIFEST_ROOT=/data/k3s-test ;; @@ -58,6 +58,10 @@ jobs: export MANIFEST_ROOT=/data/k3s ;; esac - test -f "$KUBECONFIG" + if [[ ! -f "$KUBECONFIG" ]]; then + echo "FAIL: missing KUBECONFIG=$KUBECONFIG host=$(hostname) uid=$(id -u)" + ls -la /etc/rancher/k3s/ /root/.kube/ 2>/dev/null || true + exit 1 + fi ./scripts/ci-deploy-api.sh "${{ env.DEPLOY_NAME }}" \ "${{ env.CONTAINER_NAME }}" "$IMG" -- 2.45.2 From 25d0f2f778862d28f7bf5d0a54dcac94e43fc6c5 Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Mon, 28 Sep 2026 15:35:15 +0800 Subject: [PATCH 5/8] local dev --- src/InterfaceForward.Api/Program.cs | 5 +++-- src/InterfaceForward.Api/appsettings.json | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/InterfaceForward.Api/Program.cs b/src/InterfaceForward.Api/Program.cs index 8398e9a..2f13bd6 100644 --- a/src/InterfaceForward.Api/Program.cs +++ b/src/InterfaceForward.Api/Program.cs @@ -3,8 +3,9 @@ using Serilog; var builder = WebApplication.CreateSlimBuilder(args); var configuration = builder.Configuration; -builder.Configuration.AddConsul("idwms/common", source => source.ReloadOnChange = true); -builder.Configuration.AddConsul("idwms/itfxapi", source => source.ReloadOnChange = true); +var prefix = builder.Environment.EnvironmentName == "Development" ? "dev" : "idwms"; +builder.Configuration.AddConsul($"{prefix}/common", source => source.ReloadOnChange = true); +builder.Configuration.AddConsul($"{prefix}/itfxapi", source => source.ReloadOnChange = true); Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) .CreateLogger(); diff --git a/src/InterfaceForward.Api/appsettings.json b/src/InterfaceForward.Api/appsettings.json index 860fa46..06ba18d 100644 --- a/src/InterfaceForward.Api/appsettings.json +++ b/src/InterfaceForward.Api/appsettings.json @@ -1,7 +1,7 @@ { "UseLocalConfigs": false, "Consul": { - "Address": "https://consul.nanafa.com", - "Token": "97217125-df0b-5c0a-dbfc-8885def5e471" + "Address": "http://test.ideship.com:30850", + "Token": "c0aea902-dca0-ac29-299b-a0d47e5402aa" } } -- 2.45.2 From fdcc6c56f8b34eb57f576a0403bc950b429176d7 Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Wed, 30 Sep 2026 14:40:04 +0800 Subject: [PATCH 6/8] =?UTF-8?q?feat=EF=BC=9A=E5=8E=BB=E6=8E=89=E5=AE=9A?= =?UTF-8?q?=E5=88=B6=E5=8C=96=E6=8E=A5=E5=8F=A3=E7=99=BB=E5=BD=95=E6=A3=80?= =?UTF-8?q?=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/InterfaceForward.Application/Services/Customized/Shopee.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/InterfaceForward.Application/Services/Customized/Shopee.cs b/src/InterfaceForward.Application/Services/Customized/Shopee.cs index 3fdfbd9..91ab90a 100644 --- a/src/InterfaceForward.Application/Services/Customized/Shopee.cs +++ b/src/InterfaceForward.Application/Services/Customized/Shopee.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json.Linq; @@ -7,6 +8,7 @@ namespace InterfaceForward.Application.Services.Customized; [ApiExplorerSettings(GroupName = "接口转发服务")] [TypeFilter(typeof(ShopeeForwardAuthorizeFilter))] [TypeFilter(typeof(ShopeeForwardExceptionFilter))] +[AllowAnonymous] public class Shopee(InterfaceForwardCommon forwardCommon): ApplicationService { /// -- 2.45.2 From 142e8ff441d87ffd0825f9db1ce97f5634fb16ce Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Fri, 9 Oct 2026 11:43:53 +0800 Subject: [PATCH 7/8] =?UTF-8?q?feat=EF=BC=9A=E7=BC=93=E5=AD=98=E9=BB=98?= =?UTF-8?q?=E8=AE=A47day?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/InterfaceForwardCommon.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/InterfaceForward.Application/Services/InterfaceForwardCommon.cs b/src/InterfaceForward.Application/Services/InterfaceForwardCommon.cs index 1b902d5..cdce7a3 100644 --- a/src/InterfaceForward.Application/Services/InterfaceForwardCommon.cs +++ b/src/InterfaceForward.Application/Services/InterfaceForwardCommon.cs @@ -26,9 +26,9 @@ public class InterfaceForwardCommon( : ITransientDependency { /// - /// 缓存数据:映射,账户 默认过期时间 + /// 缓存数据:映射,账户 默认过期时间s /// - public static readonly int DefaultCacheTtl = int.MaxValue; + public static readonly int DefaultCacheTtl = 7 * 24 * 60 * 60; private readonly Dictionary _flows = new(); -- 2.45.2 From d8ae8a76bafddc2cf1973deb0d9ed9f77abe3c0a Mon Sep 17 00:00:00 2001 From: xiaolipro <2357729423@qq.com> Date: Mon, 12 Oct 2026 10:47:29 +0800 Subject: [PATCH 8/8] fix --- .../ForwardCore/DefaultForwardFlow.cs | 20 +++--- .../Services/Interface/InterfaceService.cs | 5 +- .../DefaultForwardFlowTests.cs | 63 +++++++++++++++++++ 3 files changed, 76 insertions(+), 12 deletions(-) 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) -- 2.45.2