Compare commits
No commits in common. "0ded5da8dd0494867b9c8a9184c5b36c61e36f22" and "208ba73a12c7b1042debaa25ad8e736d9697544b" have entirely different histories.
0ded5da8dd
...
208ba73a12
@ -1,10 +1,9 @@
|
|||||||
# 复制到 itfx 仓库 .gitea/workflows/deploy.yml
|
|
||||||
# push master → prod;push test → test
|
|
||||||
name: Build and Deploy
|
name: Build and Deploy
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master, test]
|
branches: [master, main]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CSPROJ: src/InterfaceForward.Api/InterfaceForward.Api.csproj
|
CSPROJ: src/InterfaceForward.Api/InterfaceForward.Api.csproj
|
||||||
@ -21,47 +20,15 @@ jobs:
|
|||||||
- name: Build and deploy
|
- name: Build and deploy
|
||||||
run: |
|
run: |
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
REF="${{ gitea.ref_name }}"
|
|
||||||
case "$REF" in
|
|
||||||
test) TARGET=test ;;
|
|
||||||
master) TARGET=prod ;;
|
|
||||||
*) echo "unsupported branch: $REF"; exit 1 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
SHA="${{ gitea.sha }}"
|
|
||||||
REPO="${{ gitea.repository }}"
|
|
||||||
test -n "$REPO" && [[ "$REPO" == */* ]]
|
|
||||||
|
|
||||||
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
|
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
|
||||||
unset NAMESPACE
|
TAG="${{ gitea.sha }}"
|
||||||
|
IMG="${{ env.TCR_REGISTRY }}/${{ env.TCR_NAMESPACE }}/${{ env.IMAGE_NAME }}:${TAG}"
|
||||||
|
REPO="${{ gitea.repository }}"
|
||||||
|
REPO="${REPO:-${{ github.repository }}}"
|
||||||
|
test -n "$REPO" && [[ "$REPO" == */* ]]
|
||||||
|
echo "REPO=$REPO TAG=$TAG host=$(hostname)"
|
||||||
cd /data/k3s
|
cd /data/k3s
|
||||||
./scripts/ci-publish-container.sh "$REPO" "${{ env.CSPROJ }}" \
|
./scripts/ci-publish-container.sh "$REPO" "${{ env.CSPROJ }}" \
|
||||||
"${{ env.IMAGE_NAME }}" "$TAG" "$SHA"
|
"${{ env.IMAGE_NAME }}" "$TAG" "$TAG"
|
||||||
|
|
||||||
case "$TARGET" in
|
|
||||||
test)
|
|
||||||
export KUBECONFIG=/etc/rancher/k3s/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
|
|
||||||
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 }}" \
|
./scripts/ci-deploy-api.sh "${{ env.DEPLOY_NAME }}" \
|
||||||
"${{ env.CONTAINER_NAME }}" "$IMG"
|
"${{ env.CONTAINER_NAME }}" "$IMG"
|
||||||
|
|||||||
@ -3,9 +3,8 @@ using Serilog;
|
|||||||
|
|
||||||
var builder = WebApplication.CreateSlimBuilder(args);
|
var builder = WebApplication.CreateSlimBuilder(args);
|
||||||
var configuration = builder.Configuration;
|
var configuration = builder.Configuration;
|
||||||
var prefix = builder.Environment.EnvironmentName == "Development" ? "dev" : "idwms";
|
builder.Configuration.AddConsul("idwms/common", source => source.ReloadOnChange = true);
|
||||||
builder.Configuration.AddConsul($"{prefix}/common", source => source.ReloadOnChange = true);
|
builder.Configuration.AddConsul("idwms/itfxapi", source => source.ReloadOnChange = true);
|
||||||
builder.Configuration.AddConsul($"{prefix}/itfxapi", source => source.ReloadOnChange = true);
|
|
||||||
Log.Logger = new LoggerConfiguration()
|
Log.Logger = new LoggerConfiguration()
|
||||||
.ReadFrom.Configuration(configuration)
|
.ReadFrom.Configuration(configuration)
|
||||||
.CreateLogger();
|
.CreateLogger();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"UseLocalConfigs": false,
|
"UseLocalConfigs": false,
|
||||||
"Consul": {
|
"Consul": {
|
||||||
"Address": "http://test.ideship.com:30850",
|
"Address": "https://consul.nanafa.com",
|
||||||
"Token": "c0aea902-dca0-ac29-299b-a0d47e5402aa"
|
"Token": "97217125-df0b-5c0a-dbfc-8885def5e471"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -421,8 +421,7 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
Dictionary<string, string> nameValueCollection;
|
Dictionary<string, string> nameValueCollection;
|
||||||
if (context.FormFieldList.Count != 0)
|
if (context.FormFieldList.Count != 0)
|
||||||
{
|
{
|
||||||
var field = context.FormFieldList.FirstOrDefault(x =>
|
var field = context.FormFieldList.FirstOrDefault(x => x.Value == GlobalConst.FromMappingBody);
|
||||||
x.Value is GlobalConst.FromMappingBody or GlobalConst.FromBody);
|
|
||||||
if (field != null) field.Value = body;
|
if (field != null) field.Value = body;
|
||||||
nameValueCollection = context.FormFieldList.ToDictionary(x => x.Name, x => x.Value);
|
nameValueCollection = context.FormFieldList.ToDictionary(x => x.Name, x => x.Value);
|
||||||
}
|
}
|
||||||
@ -533,18 +532,17 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
// Query / Header / 表单
|
// Query / Header / 表单
|
||||||
foreach (var item in context.QueryFieldList)
|
foreach (var item in context.QueryFieldList)
|
||||||
{
|
{
|
||||||
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description, keepMappingBodyPlaceholder: false);
|
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var item in context.HeaderFieldList)
|
foreach (var item in context.HeaderFieldList)
|
||||||
{
|
{
|
||||||
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description, keepMappingBodyPlaceholder: false);
|
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var item in context.FormFieldList)
|
foreach (var item in context.FormFieldList)
|
||||||
{
|
{
|
||||||
// FormUrlEncoded 的 Body KV 保留占位符,交由 SetContentType 用序列化后的 TargetInterfaceInput 填充
|
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description);
|
||||||
item.Value = ReplaceFormPlaceholder(item.Name, item.Value, item.Description, keepMappingBodyPlaceholder: true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绑定body部分的字段
|
// 绑定body部分的字段
|
||||||
@ -580,7 +578,7 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string ReplaceFormPlaceholder(string name, string value, string? description, bool keepMappingBodyPlaceholder)
|
string ReplaceFormPlaceholder(string name, string value, string? description)
|
||||||
{
|
{
|
||||||
return value switch
|
return value switch
|
||||||
{
|
{
|
||||||
@ -591,11 +589,9 @@ public class DefaultForwardFlow : IForwardFlow, ITransientDependency
|
|||||||
GlobalConst.DateTime => TurnDate(now, description),
|
GlobalConst.DateTime => TurnDate(now, description),
|
||||||
GlobalConst.Url => context.TargetInterface.RequestAddress,
|
GlobalConst.Url => context.TargetInterface.RequestAddress,
|
||||||
GlobalConst.FromAccount => context.GetAccountFieldValueOrNull(name) ?? string.Empty,
|
GlobalConst.FromAccount => context.GetAccountFieldValueOrNull(name) ?? string.Empty,
|
||||||
// Body 表单在 FormUrlEncoded 时保留占位符;Query/Header 必须立刻展开,否则会原样发出
|
GlobalConst.FromMappingBody => context.TargetInterface.ContentType == ContentType.FormUrlEncoded
|
||||||
GlobalConst.FromMappingBody or GlobalConst.FromBody =>
|
? GlobalConst.FromMappingBody
|
||||||
keepMappingBodyPlaceholder && context.TargetInterface.ContentType == ContentType.FormUrlEncoded
|
: JsonConvert.SerializeObject(context.OriginalInterfaceMappedInput),
|
||||||
? GlobalConst.FromMappingBody
|
|
||||||
: JsonConvert.SerializeObject(context.OriginalInterfaceMappedInput),
|
|
||||||
_ => value
|
_ => value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
@ -8,7 +7,6 @@ namespace InterfaceForward.Application.Services.Customized;
|
|||||||
[ApiExplorerSettings(GroupName = "接口转发服务")]
|
[ApiExplorerSettings(GroupName = "接口转发服务")]
|
||||||
[TypeFilter(typeof(ShopeeForwardAuthorizeFilter))]
|
[TypeFilter(typeof(ShopeeForwardAuthorizeFilter))]
|
||||||
[TypeFilter(typeof(ShopeeForwardExceptionFilter))]
|
[TypeFilter(typeof(ShopeeForwardExceptionFilter))]
|
||||||
[AllowAnonymous]
|
|
||||||
public class Shopee(InterfaceForwardCommon forwardCommon): ApplicationService
|
public class Shopee(InterfaceForwardCommon forwardCommon): ApplicationService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -108,7 +108,10 @@ public class InterfaceService : ApplicationService
|
|||||||
|
|
||||||
// 构造参数
|
// 构造参数
|
||||||
var paras = await InterfaceRepository.GetParameterListByIdAsync(id);
|
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
|
res.RequestBodyParameterList = !interfaceEntity.IsUpStream && interfaceEntity.ContentType is ContentType.Json or ContentType.Xml
|
||||||
? paras.Where(x => x.IsInPara && x.ParaKind == ParameterParaKind.Normal).ToList()
|
? paras.Where(x => x.IsInPara && x.ParaKind == ParameterParaKind.Normal).ToList()
|
||||||
: [];
|
: [];
|
||||||
|
|||||||
@ -26,9 +26,9 @@ public class InterfaceForwardCommon(
|
|||||||
: ITransientDependency
|
: ITransientDependency
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存数据:映射,账户 默认过期时间s
|
/// 缓存数据:映射,账户 默认过期时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly int DefaultCacheTtl = 7 * 24 * 60 * 60;
|
public static readonly int DefaultCacheTtl = int.MaxValue;
|
||||||
|
|
||||||
private readonly Dictionary<string, IForwardFlow> _flows = new();
|
private readonly Dictionary<string, IForwardFlow> _flows = new();
|
||||||
|
|
||||||
|
|||||||
@ -96,69 +96,6 @@ public class DefaultForwardFlowTests
|
|||||||
Assert.Equal("{\"orderId\":\"A001\"}", Assert.Single(context.QueryFieldList).Value);
|
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
|
class TestForwardFlow : DefaultForwardFlow
|
||||||
{
|
{
|
||||||
public void SetContentTypeForTest(ForwardCoreContext context, HttpRequestMessage message)
|
public void SetContentTypeForTest(ForwardCoreContext context, HttpRequestMessage message)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user