Browse Source

增加路由聚合的实现,以及增加专用于AbpApiDefinition接口的自定义路由聚合中间件

pull/1/head
cKey 6 years ago
parent
commit
5f6296a324
  1. 1
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/ApiGatewayPermissionDefinitionProvider.cs
  2. 1
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/ApiGatewayPermissions.cs
  3. 4
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Localization/ApplicationContracts/en.json
  4. 4
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Localization/ApplicationContracts/zh-Hans.json
  5. 20
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateReRouteConfigCreateDto.cs
  6. 14
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateReRouteConfigGetByKeyInputDto.cs
  7. 15
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateReRouteCreateDto.cs
  8. 13
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateReRouteUpdateDto.cs
  9. 10
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateRouteGetByRouteIdInputDto.cs
  10. 4
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/Base/AggregateReRouteDtoBase.cs
  11. 10
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/Result/AggregateReRouteDto.cs
  12. 12
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/IAggregateReRouteAppService.cs
  13. 18
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN/ApiGateway/ApiGatewayApplicationAutoMapperProfile.cs
  14. 121
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN/ApiGateway/Ocelot/AggregateReRouteAppService.cs
  15. 2
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN/ApiGateway/Ocelot/ReRouteAppService.cs
  16. 48
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN/ApiGateway/Ocelot/Aggregate/AggregateReRoute.cs
  17. 4
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN/ApiGateway/Ocelot/Aggregate/IAggregateReRouteRepository.cs
  18. 10
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.EntityFrameworkCore/LINGYUN/ApiGateway/Ocelot/EfCoreAggregateReRouteRepository.cs
  19. 39
      aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi/LINGYUN/ApiGateway/Ocelot/AggregateReRouteController.cs
  20. 5
      aspnet-core/modules/tenants/LINGYUN.TenantManagement.Application.Contracts/LINGYUN.TenantManagement.Application.Contracts.csproj
  21. 8
      aspnet-core/modules/tenants/LINGYUN.TenantManagement.Application/LINGYUN.TenantManagement.Application.csproj
  22. BIN
      aspnet-core/modules/tenants/LINGYUN.TenantManagement.Application/obj/Debug/netstandard2.0/LINGYUN.TenantManagement.Application.csprojAssemblyReference.cache
  23. 6
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayHostModule.cs
  24. 152
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Ocelot/Middleware/Multiplexer/AbpApiDefinitionResponseAggregator.cs
  25. 141
      vueJs/src/api/apigateway.ts
  26. 17
      vueJs/src/lang/zh.ts
  27. 10
      vueJs/src/router/index.ts
  28. 295
      vueJs/src/views/admin/apigateway/aggregateRoute.vue
  29. 197
      vueJs/src/views/admin/apigateway/components/AggregateRouteCreateOrEditForm.vue
  30. 1
      vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue

1
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/ApiGatewayPermissionDefinitionProvider.cs

@ -45,6 +45,7 @@ namespace LINGYUN.ApiGateway
aggregateRoute.AddChild(ApiGatewayPermissions.AggregateRoute.Export, L("Permissions:Export"), MultiTenancySides.Host);
aggregateRoute.AddChild(ApiGatewayPermissions.AggregateRoute.Import, L("Permissions:Import"), MultiTenancySides.Host);
aggregateRoute.AddChild(ApiGatewayPermissions.AggregateRoute.Delete, L("Permissions:Delete"), MultiTenancySides.Host);
aggregateRoute.AddChild(ApiGatewayPermissions.AggregateRoute.ManageRouteConfig, L("Permissions:ManageRouteConfig"), MultiTenancySides.Host);
}
protected virtual LocalizableString L(string name)

1
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/ApiGatewayPermissions.cs

@ -51,6 +51,7 @@
public const string Delete = Default + ".Delete";
public const string Export = Default + ".Export";
public const string Import = Default + ".Import";
public const string ManageRouteConfig = Default + ".ManageRouteConfig";
}
}
}

4
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Localization/ApplicationContracts/en.json

@ -7,9 +7,11 @@
"Permissions:Route": "Route",
"Permissions:DynamicRoute": "Dynamic",
"Permissions:AggregateRoute": "Aggregate",
"Permissions:ManageRouteConfig": "Route config",
"Permissions:Update": "Update",
"Permissions:Export": "Export",
"Permissions:Import": "Import",
"Permissions:Delete": "Delete"
"Permissions:Delete": "Delete",
"AggregateReRouteExists": "Aggregate name: {0} already exists!"
}
}

4
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Localization/ApplicationContracts/zh-Hans.json

@ -7,10 +7,12 @@
"Permissions:Route": "路由配置",
"Permissions:DynamicRoute": "动态路由",
"Permissions:AggregateRoute": "路由聚合",
"Permissions:ManageRouteConfig": "管理路由配置",
"Permissions:Create": "新增",
"Permissions:Update": "编辑",
"Permissions:Export": "导出",
"Permissions:Import": "导入",
"Permissions:Delete": "删除"
"Permissions:Delete": "删除",
"AggregateReRouteExists": "聚合名称: {0} 已存在!"
}
}

20
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateReRouteConfigCreateDto.cs

@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.ApiGateway.Ocelot
{
public class AggregateReRouteConfigCreateDto
{
[Required]
public string RouteId { get; set; }
[Required]
[StringLength(256)]
public string ReRouteKey { get; set; }
[StringLength(1000)]
public string Parameter { get; set; }
[StringLength(256)]
public string JsonPath { get; set; }
}
}

14
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateReRouteConfigGetByKeyInputDto.cs

@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.ApiGateway.Ocelot
{
public class AggregateReRouteConfigGetByKeyInputDto
{
[Required]
public string RouteId { get; set; }
[Required]
[StringLength(256)]
public string ReRouteKey { get; set; }
}
}

15
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateReRouteCreateDto.cs

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.ApiGateway.Ocelot
{
public class AggregateReRouteCreateDto : AggregateReRouteDtoBase
{
[Required]
[StringLength(50)]
public string AppId { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
}
}

13
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateReRouteUpdateDto.cs

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.ApiGateway.Ocelot
{
public class AggregateReRouteUpdateDto : AggregateReRouteDtoBase
{
[Required]
public string RouteId { get; set; }
[Required]
public string ConcurrencyStamp { get; set; }
}
}

10
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/AggregateRouteGetByRouteIdInputDto.cs

@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.ApiGateway.Ocelot
{
public class AggregateRouteGetByRouteIdInputDto
{
[Required]
public string RouteId { get; set; }
}
}

4
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/Base/AggregateReRouteDtoBase.cs

@ -7,18 +7,16 @@ namespace LINGYUN.ApiGateway.Ocelot
public class AggregateReRouteDtoBase
{
public List<string> ReRouteKeys { get; set; }
public List<AggregateReRouteConfigDto> ReRouteKeysConfig { get; set; }
public string UpstreamPathTemplate { get; set; }
public string UpstreamHost { get; set; }
public bool ReRouteIsCaseSensitive { get; set; }
public string Aggregator { get; set; }
public int Priority { get; set; }
public int? Priority { get; set; }
public List<string> UpstreamHttpMethod { get; set; }
public AggregateReRouteDtoBase()
{
ReRouteKeys = new List<string>();
UpstreamHttpMethod = new List<string>();
ReRouteKeysConfig = new List<AggregateReRouteConfigDto>();
}
}
}

10
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/Dto/Result/AggregateReRouteDto.cs

@ -1,16 +1,26 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace LINGYUN.ApiGateway.Ocelot
{
[Serializable]
public class AggregateReRouteDto : AggregateReRouteDtoBase
{
public string AppId { get; set; }
[JsonConverter(typeof(HexLongConverter))]
public long ReRouteId { get; set; }
public string Name { get; set; }
public string ConcurrencyStamp { get; set; }
public List<AggregateReRouteConfigDto> ReRouteKeysConfig { get; set; }
public AggregateReRouteDto()
{
ReRouteKeysConfig = new List<AggregateReRouteConfigDto>();
}
}
}

12
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application.Contracts/LINGYUN/ApiGateway/Ocelot/IAggregateReRouteAppService.cs

@ -6,8 +6,20 @@ namespace LINGYUN.ApiGateway.Ocelot
{
public interface IAggregateReRouteAppService : IApplicationService
{
Task<AggregateReRouteDto> GetAsync(AggregateRouteGetByRouteIdInputDto aggregateRouteGetByRouteId);
Task<ListResultDto<AggregateReRouteDto>> GetAsync(AggregateRouteGetByAppIdInputDto aggregateRouteGetByAppId);
Task<PagedResultDto<AggregateReRouteDto>> GetPagedListAsync(AggregateRouteGetByPagedInputDto aggregateRouteGetByPaged);
Task<AggregateReRouteDto> CreateAsync(AggregateReRouteCreateDto aggregateReRouteCreate);
Task<AggregateReRouteDto> UpdateAsync(AggregateReRouteUpdateDto aggregateReRouteUpdate);
Task DeleteAsync(AggregateRouteGetByRouteIdInputDto aggregateRouteGetByRouteId);
Task<AggregateReRouteConfigDto> AddRouteConfigAsync(AggregateReRouteConfigCreateDto aggregateReRouteConfigCreate);
Task DeleteRouteConfigAsync(AggregateReRouteConfigGetByKeyInputDto aggregateReRouteConfigGetByKey);
}
}

18
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN/ApiGateway/ApiGatewayApplicationAutoMapperProfile.cs

@ -64,12 +64,18 @@ namespace LINGYUN.ApiGateway
CreateMap<AggregateReRouteConfig, AggregateReRouteConfigDto>();
CreateMap<AggregateReRoute, AggregateReRouteDto>()
.ForMember(dto => dto.ReRouteKeys, map => map.MapFrom(m => !m.ReRouteKeys.IsNullOrWhiteSpace() && m.ReRouteKeys.Contains(",")
? m.ReRouteKeys.Split(',').ToList()
: new List<string>()))
.ForMember(dto => dto.UpstreamHttpMethod, map => map.MapFrom(m => !m.UpstreamHttpMethod.IsNullOrWhiteSpace() && m.UpstreamHttpMethod.Contains(",")
? m.UpstreamHttpMethod.Split(',').ToList()
: new List<string>()));
.ForMember(dto => dto.ReRouteKeys, map => map.MapFrom(m => MapperList(m.ReRouteKeys)))
.ForMember(dto => dto.UpstreamHttpMethod, map => map.MapFrom(m => MapperList(m.UpstreamHttpMethod)));
CreateMap<AggregateReRouteCreateDto, AggregateReRoute>()
.ForCtorParam("name", x => x.MapFrom(m => m.Name))
.ForCtorParam("routeId", x => x.MapFrom(m => snowflakeIdGenerator.NextId()))
.ForCtorParam("aggregator", x => x.MapFrom(m => m.Aggregator))
.ForCtorParam("appId", x => x.MapFrom(m => m.AppId))
.ForMember(src => src.ExtraProperties, x => x.Ignore())
.ForMember(src => src.ReRouteKeys, x => x.Ignore())
.ForMember(src => src.ReRouteKeysConfig, x => x.Ignore())
.ForMember(src => src.UpstreamHttpMethod, x => x.Ignore());
CreateMap<GlobalConfiguration, GlobalConfigurationDto>();

121
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN/ApiGateway/Ocelot/AggregateReRouteAppService.cs

@ -1,21 +1,40 @@
using Microsoft.AspNetCore.Authorization;
using DotNetCore.CAP;
using LINGYUN.ApiGateway.EventBus;
using LINGYUN.ApiGateway.Snowflake;
using Microsoft.AspNetCore.Authorization;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
namespace LINGYUN.ApiGateway.Ocelot
{
// 2020-05-20 15:00
// TODO 重构项目 规范化实体的存储形式,数组类型分为多张表存储
// TODO 取消long类型的实体主键 改用GUID
[Authorize(ApiGatewayPermissions.AggregateRoute.Default)]
public class AggregateReRouteAppService : ApiGatewayApplicationServiceBase, IAggregateReRouteAppService
{
private readonly ICapPublisher _eventPublisher;
private readonly IAggregateReRouteRepository _aggregateReRouteRepository;
public AggregateReRouteAppService(
ICapPublisher eventPublisher,
IAggregateReRouteRepository aggregateReRouteRepository)
{
_eventPublisher = eventPublisher;
_aggregateReRouteRepository = aggregateReRouteRepository;
}
public virtual async Task<AggregateReRouteDto> GetAsync(AggregateRouteGetByRouteIdInputDto aggregateRouteGetByRouteId)
{
var routeId = long.Parse(aggregateRouteGetByRouteId.RouteId);
var reroute = await _aggregateReRouteRepository.GetByRouteIdAsync(routeId);
return ObjectMapper.Map<AggregateReRoute, AggregateReRouteDto>(reroute);
}
[Authorize(ApiGatewayPermissions.AggregateRoute.Export)]
public async Task<ListResultDto<AggregateReRouteDto>> GetAsync(AggregateRouteGetByAppIdInputDto aggregateRouteGetByAppId)
{
@ -34,5 +53,105 @@ namespace LINGYUN.ApiGateway.Ocelot
return new PagedResultDto<AggregateReRouteDto>(reroutesTuple.total,
ObjectMapper.Map<List<AggregateReRoute>, List<AggregateReRouteDto>>(reroutesTuple.routes));
}
[Authorize(ApiGatewayPermissions.AggregateRoute.Create)]
public virtual async Task<AggregateReRouteDto> CreateAsync(AggregateReRouteCreateDto aggregateReRouteCreate)
{
var aggregateNameExists = await _aggregateReRouteRepository
.AggregateReRouteNameExistsAsync(aggregateReRouteCreate.Name);
if (aggregateNameExists)
{
throw new UserFriendlyException(L["AggregateReRouteExists", aggregateReRouteCreate.Name]);
}
var aggregateRoute = ObjectMapper.Map<AggregateReRouteCreateDto, AggregateReRoute>(aggregateReRouteCreate);
aggregateRoute.SetUpstream(aggregateReRouteCreate.UpstreamHost, aggregateReRouteCreate.UpstreamPathTemplate);
foreach (var httpMethod in aggregateReRouteCreate.UpstreamHttpMethod)
{
aggregateRoute.AddUpstreamHttpMethod(httpMethod);
}
foreach (var routeKey in aggregateReRouteCreate.ReRouteKeys)
{
aggregateRoute.AddRouteKey(routeKey);
}
aggregateRoute = await _aggregateReRouteRepository.InsertAsync(aggregateRoute);
await _eventPublisher.PublishAsync(ApigatewayConfigChangeCommand.EventName,
new ApigatewayConfigChangeCommand("AggregateRoute", "Create"));
return ObjectMapper.Map<AggregateReRoute, AggregateReRouteDto>(aggregateRoute);
}
[Authorize(ApiGatewayPermissions.AggregateRoute.Update)]
public virtual async Task<AggregateReRouteDto> UpdateAsync(AggregateReRouteUpdateDto aggregateReRouteUpdate)
{
var routeId = long.Parse(aggregateReRouteUpdate.RouteId);
var aggregateRoute = await _aggregateReRouteRepository.GetByRouteIdAsync(routeId);
aggregateRoute.Priority = aggregateReRouteUpdate.Priority;
aggregateRoute.ConcurrencyStamp = aggregateReRouteUpdate.ConcurrencyStamp;
aggregateRoute.ReRouteIsCaseSensitive = aggregateReRouteUpdate.ReRouteIsCaseSensitive;
aggregateRoute.Aggregator = aggregateReRouteUpdate.Aggregator;
aggregateRoute.SetUpstream(aggregateReRouteUpdate.UpstreamHost, aggregateReRouteUpdate.UpstreamPathTemplate);
aggregateRoute.RemoveAllUpstreamHttpMethod();
foreach (var httpMethod in aggregateReRouteUpdate.UpstreamHttpMethod)
{
aggregateRoute.AddUpstreamHttpMethod(httpMethod);
}
aggregateRoute.RemoveAllRouteKey();
foreach (var routeKey in aggregateReRouteUpdate.ReRouteKeys)
{
aggregateRoute.AddRouteKey(routeKey);
}
aggregateRoute = await _aggregateReRouteRepository.UpdateAsync(aggregateRoute, true);
await _eventPublisher.PublishAsync(ApigatewayConfigChangeCommand.EventName,
new ApigatewayConfigChangeCommand("AggregateRoute", "Update"));
return ObjectMapper.Map<AggregateReRoute, AggregateReRouteDto>(aggregateRoute);
}
[Authorize(ApiGatewayPermissions.AggregateRoute.Delete)]
public virtual async Task DeleteAsync(AggregateRouteGetByRouteIdInputDto aggregateRouteGetByRouteId)
{
var routeId = long.Parse(aggregateRouteGetByRouteId.RouteId);
var aggregateRoute = await _aggregateReRouteRepository.GetByRouteIdAsync(routeId);
await _aggregateReRouteRepository.DeleteAsync(aggregateRoute);
await _eventPublisher.PublishAsync(ApigatewayConfigChangeCommand.EventName,
new ApigatewayConfigChangeCommand("AggregateRoute", "Delete"));
}
[Authorize(ApiGatewayPermissions.AggregateRoute.ManageRouteConfig)]
public virtual async Task<AggregateReRouteConfigDto> AddRouteConfigAsync(AggregateReRouteConfigCreateDto aggregateReRouteConfigCreate)
{
var routeId = long.Parse(aggregateReRouteConfigCreate.RouteId);
var aggregateRoute = await _aggregateReRouteRepository.GetByRouteIdAsync(routeId);
aggregateRoute.RemoveReRouteConfig(aggregateReRouteConfigCreate.ReRouteKey)
.AddReRouteConfig(aggregateReRouteConfigCreate.ReRouteKey, aggregateReRouteConfigCreate.Parameter,
aggregateReRouteConfigCreate.JsonPath);
var aggregateRouteConfig = aggregateRoute.FindReRouteConfig(aggregateReRouteConfigCreate.ReRouteKey);
await _aggregateReRouteRepository.UpdateAsync(aggregateRoute);
await _eventPublisher.PublishAsync(ApigatewayConfigChangeCommand.EventName,
new ApigatewayConfigChangeCommand("AggregateRoute", "AddRouteConfig"));
return ObjectMapper.Map<AggregateReRouteConfig, AggregateReRouteConfigDto>(aggregateRouteConfig);
}
[Authorize(ApiGatewayPermissions.AggregateRoute.ManageRouteConfig)]
public virtual async Task DeleteRouteConfigAsync(AggregateReRouteConfigGetByKeyInputDto aggregateReRouteConfigGetByKey)
{
var routeId = long.Parse(aggregateReRouteConfigGetByKey.RouteId);
var aggregateRoute = await _aggregateReRouteRepository.GetByRouteIdAsync(routeId);
aggregateRoute.RemoveReRouteConfig(aggregateReRouteConfigGetByKey.ReRouteKey);
await _aggregateReRouteRepository.UpdateAsync(aggregateRoute);
await _eventPublisher.PublishAsync(ApigatewayConfigChangeCommand.EventName,
new ApigatewayConfigChangeCommand("AggregateRoute", "DeleteRouteConfig"));
}
}
}

2
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Application/LINGYUN/ApiGateway/Ocelot/ReRouteAppService.cs

@ -46,7 +46,7 @@ namespace LINGYUN.ApiGateway.Ocelot
public async Task<ReRouteDto> UpdateAsync(ReRouteUpdateDto routeUpdateDto)
{
var reRoute = await _reRouteRepository.GetByReRouteIdAsync(long.Parse(routeUpdateDto.ReRouteId));
reRoute.SetRouteName(routeUpdateDto.ReRouteName);
reRoute.DangerousAcceptAnyServerCertificateValidator = routeUpdateDto.DangerousAcceptAnyServerCertificateValidator;
reRoute.DownstreamScheme = routeUpdateDto.DownstreamScheme;
reRoute.Key = routeUpdateDto.Key;

48
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN/ApiGateway/Ocelot/Aggregate/AggregateReRoute.cs

@ -16,8 +16,8 @@ namespace LINGYUN.ApiGateway.Ocelot
public virtual string ReRouteKeys { get; private set; }
public virtual string UpstreamPathTemplate { get; private set; }
public virtual string UpstreamHost { get; private set; }
public virtual bool ReRouteIsCaseSensitive { get; private set; }
public virtual string Aggregator { get; private set; }
public virtual bool ReRouteIsCaseSensitive { get; set; }
public virtual string Aggregator { get; set; }
public virtual int? Priority { get; set; }
public virtual string UpstreamHttpMethod { get; private set; }
public virtual ICollection<AggregateReRouteConfig> ReRouteKeysConfig { get; private set; }
@ -26,26 +26,27 @@ namespace LINGYUN.ApiGateway.Ocelot
ReRouteKeysConfig = new List<AggregateReRouteConfig>();
}
public AggregateReRoute SetUpstreamPath(string host, string path, string appId)
public AggregateReRoute(string name, long routeId, string aggregator, string appId) : this()
{
AppId = appId;
UpstreamHost = host;
UpstreamPathTemplate = path;
return this;
}
public AggregateReRoute(string name, long routeId, string aggregator) : this()
{
Name = name;
ReRouteId = routeId;
Aggregator = aggregator;
ReRouteKeys = "";
UpstreamHttpMethod = "";
}
public void SetUpstream(string host, string template)
{
UpstreamHost = host;
UpstreamPathTemplate = template;
}
public AggregateReRoute AddUpstreamHttpMethod(string method)
{
if (!UpstreamHttpMethod.Contains(method))
{
UpstreamHttpMethod += "," + method;
UpstreamHttpMethod += method + ",";
}
return this;
}
@ -60,11 +61,17 @@ namespace LINGYUN.ApiGateway.Ocelot
return this;
}
public AggregateReRoute RemoveAllUpstreamHttpMethod()
{
UpstreamHttpMethod = "";
return this;
}
public AggregateReRoute AddRouteKey(string key)
{
if (!ReRouteKeys.Contains(key))
{
ReRouteKeys += "," + key;
ReRouteKeys += key + ",";
}
return this;
}
@ -79,6 +86,17 @@ namespace LINGYUN.ApiGateway.Ocelot
return this;
}
public AggregateReRoute RemoveAllRouteKey()
{
ReRouteKeys = "";
return this;
}
public AggregateReRouteConfig FindReRouteConfig(string routeKey)
{
return ReRouteKeysConfig.FirstOrDefault(cfg => cfg.ReRouteKey.Equals(routeKey));
}
public AggregateReRoute AddReRouteConfig(string routeKey, string paramter, string jsonPath)
{
if (!ReRouteKeysConfig.Any(k => k.ReRouteKey.Equals(routeKey)))
@ -95,5 +113,11 @@ namespace LINGYUN.ApiGateway.Ocelot
ReRouteKeysConfig.RemoveAll(k => k.ReRouteKey.Equals(routeKey));
return this;
}
public AggregateReRoute RemoveAllReRouteConfig()
{
ReRouteKeysConfig.Clear();
return this;
}
}
}

4
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.Domain/LINGYUN/ApiGateway/Ocelot/Aggregate/IAggregateReRouteRepository.cs

@ -6,6 +6,10 @@ namespace LINGYUN.ApiGateway.Ocelot
{
public interface IAggregateReRouteRepository : IBasicRepository<AggregateReRoute, int>
{
Task<bool> AggregateReRouteNameExistsAsync(string name);
Task<AggregateReRoute> GetByRouteIdAsync(long routeId);
Task<List<AggregateReRoute>> GetByAppIdAsync(string appId);
Task<(List<AggregateReRoute> routes, long total)> GetPagedListAsync(string appId, string filter = "", string sorting = "", int skipCount = 1, int maxResultCount = 100);

10
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.EntityFrameworkCore/LINGYUN/ApiGateway/Ocelot/EfCoreAggregateReRouteRepository.cs

@ -15,6 +15,16 @@ namespace LINGYUN.ApiGateway.Ocelot
{
}
public async Task<bool> AggregateReRouteNameExistsAsync(string name)
{
return await DbSet.AnyAsync(ar => ar.Name.Equals(name));
}
public async Task<AggregateReRoute> GetByRouteIdAsync(long routeId)
{
return await WithDetails().Where(ar => ar.ReRouteId.Equals(routeId)).FirstOrDefaultAsync();
}
public async Task<List<AggregateReRoute>> GetByAppIdAsync(string appId)
{
return await WithDetails().Where(ar => ar.AppId.Equals(appId)).ToListAsync();

39
aspnet-core/modules/apigateway/LINGYUN.ApiGateway.HttpApi/LINGYUN/ApiGateway/Ocelot/AggregateReRouteController.cs

@ -29,5 +29,44 @@ namespace LINGYUN.ApiGateway.Ocelot
{
return await AggregateReRouteAppService.GetPagedListAsync(aggregateRouteGetByPaged);
}
[HttpGet]
[Route("{RouteId}")]
public async Task<AggregateReRouteDto> GetAsync(AggregateRouteGetByRouteIdInputDto aggregateRouteGetByRouteId)
{
return await AggregateReRouteAppService.GetAsync(aggregateRouteGetByRouteId);
}
[HttpPost]
public async Task<AggregateReRouteDto> CreateAsync(AggregateReRouteCreateDto aggregateReRouteCreate)
{
return await AggregateReRouteAppService.CreateAsync(aggregateReRouteCreate);
}
[HttpPut]
public async Task<AggregateReRouteDto> UpdateAsync(AggregateReRouteUpdateDto aggregateReRouteUpdate)
{
return await AggregateReRouteAppService.UpdateAsync(aggregateReRouteUpdate);
}
[HttpDelete]
public async Task DeleteAsync(AggregateRouteGetByRouteIdInputDto aggregateRouteGetByRouteId)
{
await AggregateReRouteAppService.DeleteAsync(aggregateRouteGetByRouteId);
}
[HttpPost]
[Route("RouteConfig")]
public async Task<AggregateReRouteConfigDto> AddRouteConfigAsync(AggregateReRouteConfigCreateDto aggregateReRouteConfigCreate)
{
return await AggregateReRouteAppService.AddRouteConfigAsync(aggregateReRouteConfigCreate);
}
[HttpDelete]
[Route("RouteConfig")]
public async Task DeleteRouteConfigAsync(AggregateReRouteConfigGetByKeyInputDto aggregateReRouteConfigGetByKey)
{
await AggregateReRouteAppService.DeleteRouteConfigAsync(aggregateReRouteConfigGetByKey);
}
}
}

5
aspnet-core/modules/tenants/LINGYUN.TenantManagement.Application.Contracts/LINGYUN.TenantManagement.Application.Contracts.csproj

@ -5,12 +5,9 @@
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<Folder Include="LINGYUN\Abp\TenantManagement\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="2.7.0" />
<PackageReference Include="Volo.Abp.TenantManagement.Domain.Shared" Version="2.7.0" />
</ItemGroup>
</Project>

8
aspnet-core/modules/tenants/LINGYUN.TenantManagement.Application/LINGYUN.TenantManagement.Application.csproj

@ -5,4 +5,12 @@
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.TenantManagement.Domain" Version="2.7.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.TenantManagement.Application.Contracts\LINGYUN.TenantManagement.Application.Contracts.csproj" />
</ItemGroup>
</Project>

BIN
aspnet-core/modules/tenants/LINGYUN.TenantManagement.Application/obj/Debug/netstandard2.0/LINGYUN.TenantManagement.Application.csprojAssemblyReference.cache

Binary file not shown.

6
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/LINGYUN/ApiGateway/ApiGatewayHostModule.cs

@ -5,6 +5,7 @@ using Microsoft.Extensions.Options;
using Ocelot.Configuration.Repository;
using Ocelot.DependencyInjection;
using Ocelot.Extenssions;
using Ocelot.Middleware.Multiplexer;
using Ocelot.Provider.Polly;
using Volo.Abp;
using Volo.Abp.AspNetCore;
@ -54,7 +55,10 @@ namespace LINGYUN.ApiGateway
options.ApiSecret = configuration["AuthServer:ApiSecret"];
});
context.Services.AddOcelot().AddPolly();
context.Services
.AddOcelot()
.AddPolly()
.AddSingletonDefinedAggregator<AbpApiDefinitionAggregator>();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)

152
aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/Ocelot/Middleware/Multiplexer/AbpApiDefinitionResponseAggregator.cs

@ -0,0 +1,152 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace Ocelot.Middleware.Multiplexer
{
public class AbpApiDefinitionAggregator : IDefinedAggregator
{
public async Task<DownstreamResponse> Aggregate(List<DownstreamContext> responses)
{
var isAbpResponse = responses.Any(response => response.DownstreamResponse.Headers.Any(h => h.Key.Equals("_abperrorformat")));
return await MapAbpApiDefinitionAggregateContentAsync(responses);
//if (isAbpResponse)
//{
// return await MapAbpApiDefinitionAggregateContentAsync(responses);
//}
//else
//{
// return await MapSimpleJsonAggregateContentAsync(responses);
//}
}
protected virtual async Task<DownstreamResponse> MapAbpApiDefinitionAggregateContentAsync(List<DownstreamContext> downstreamContexts)
{
var responseKeys = downstreamContexts.Select(s => s.DownstreamReRoute.Key).Distinct().ToList();
JObject responseObject = null;
for (var k = 0; k < responseKeys.Count; k++)
{
var contexts = downstreamContexts.Where(w => w.DownstreamReRoute.Key == responseKeys[k]).ToList();
if (contexts.Count == 1)
{
if (contexts[0].IsError)
{
return contexts[0].DownstreamResponse;
}
var content = await contexts[0].DownstreamResponse.Content.ReadAsStringAsync();
var contentObject = JsonConvert.DeserializeObject(content);
if (responseObject == null)
{
responseObject = JObject.FromObject(contentObject);
}
else
{
responseObject.Merge(contentObject);
}
}
else
{
for (var i = 0; i < contexts.Count; i++)
{
if (contexts[i].IsError)
{
return contexts[i].DownstreamResponse;
}
var content = await contexts[i].DownstreamResponse.Content.ReadAsStringAsync();
var contentObject = JsonConvert.DeserializeObject(content);
if (responseObject == null)
{
responseObject = JObject.FromObject(contentObject);
}
else
{
responseObject.Merge(contentObject);
}
}
}
}
var stringContent = new StringContent(responseObject.ToString())
{
Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
};
stringContent.Headers.Add("_abperrorformat", "true");
return new DownstreamResponse(stringContent, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "cannot return from aggregate..which reason phrase would you use?");
}
protected virtual async Task<DownstreamResponse> MapSimpleJsonAggregateContentAsync(List<DownstreamContext> downstreamContexts)
{
var contentBuilder = new StringBuilder();
contentBuilder.Append("{");
var responseKeys = downstreamContexts.Select(s => s.DownstreamReRoute.Key).Distinct().ToList();
for (var k = 0; k < responseKeys.Count; k++)
{
var contexts = downstreamContexts.Where(w => w.DownstreamReRoute.Key == responseKeys[k]).ToList();
if (contexts.Count == 1)
{
if (contexts[0].IsError)
{
return contexts[0].DownstreamResponse;
}
var content = await contexts[0].DownstreamResponse.Content.ReadAsStringAsync();
contentBuilder.Append($"\"{responseKeys[k]}\":{content}");
}
else
{
contentBuilder.Append($"\"{responseKeys[k]}\":");
contentBuilder.Append("[");
for (var i = 0; i < contexts.Count; i++)
{
if (contexts[i].IsError)
{
return contexts[i].DownstreamResponse;
}
var content = await contexts[i].DownstreamResponse.Content.ReadAsStringAsync();
if (string.IsNullOrWhiteSpace(content))
{
continue;
}
contentBuilder.Append($"{content}");
if (i + 1 < contexts.Count)
{
contentBuilder.Append(",");
}
}
contentBuilder.Append("]");
}
if (k + 1 < responseKeys.Count)
{
contentBuilder.Append(",");
}
}
contentBuilder.Append("}");
var stringContent = new StringContent(contentBuilder.ToString())
{
Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
};
return new DownstreamResponse(stringContent, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "cannot return from aggregate..which reason phrase would you use?");
}
}
}

141
vueJs/src/api/apigateway.ts

@ -120,6 +120,50 @@ export default class ApiGateWay {
_url += '?appId=' + appId
return ApiService.Delete(_url, serviceUrl)
}
public static getAggregateReRoutes(payload: AggregateReRouteGetByPaged) {
let _url = '/api/ApiGateway/Aggregates'
_url += '?appId=' + payload.appId
_url += '&filter=' + payload.filter
_url += '&sorting=' + payload.sorting
_url += '&skipCount=' + payload.skipCount
_url += '&maxResultCount=' + payload.maxResultCount
return ApiService.Get<PagedResultDto<AggregateReRoute>>(_url, serviceUrl)
}
public static getAggregateReRouteByRouteId(routeId: string) {
let _url = '/api/ApiGateway/Aggregates/'
_url += routeId
return ApiService.Get<AggregateReRoute>(_url, serviceUrl)
}
public static createAggregateReRoute(payload: AggregateReRouteCreate) {
const _url = '/api/ApiGateway/Aggregates'
return ApiService.Post<AggregateReRoute>(_url, payload, serviceUrl)
}
public static updateAggregateReRoute(payload: AggregateReRouteUpdate) {
const _url = '/api/ApiGateway/Aggregates'
return ApiService.Put<AggregateReRoute>(_url, payload, serviceUrl)
}
public static deleteAggregateReRoute(routeId: string) {
let _url = '/api/ApiGateway/Aggregates'
_url += '?routeId=' + routeId
return ApiService.Delete(_url, serviceUrl)
}
public static createAggregateRouteConfig(payload: AggregateReRouteConfigCreate) {
const _url = '/api/ApiGateway/Aggregates/RouteConfig'
return ApiService.Post<AggregateReRouteConfig>(_url, payload, serviceUrl)
}
public static deleteAggregateRouteConfig(routeId: string, routeKey: string) {
let _url = '/api/ApiGateway/Aggregates/RouteConfig'
_url += '?routeId=' + routeId
_url += '&ReRouteKey=' + routeKey
return ApiService.Delete(_url, serviceUrl)
}
}
export class ServiceDiscoveryProvider {
@ -412,3 +456,100 @@ export class ReRouteGetByPagedDto extends PagedAndSortedResultRequestDto {
this.sorting = 'ReRouteName'
}
}
export class AggregateReRouteConfig {
reRouteKey = ''
parameter = ''
jsonPath = ''
}
export class AggregateReRouteConfigCreate extends AggregateReRouteConfig {
routeId = ''
}
export class AggregateReRouteBase {
reRouteKeys!: string[]
upstreamPathTemplate = ''
upstreamHost = ''
reRouteIsCaseSensitive = true
aggregator = ''
priority?: number
upstreamHttpMethod!: string[]
constructor() {
this.reRouteKeys = new Array<string>()
this.upstreamHttpMethod = new Array<string>()
}
}
export class AggregateReRoute extends AggregateReRouteBase {
appId = ''
name = ''
reRouteId = ''
concurrencyStamp = ''
reRouteKeysConfig!: AggregateReRouteConfig[]
constructor() {
super()
this.reRouteKeysConfig = new Array<AggregateReRouteConfig>()
}
public static empty() {
return new AggregateReRoute()
}
}
export class AggregateReRouteCreate extends AggregateReRouteBase {
appId = ''
name = ''
public static empty() {
return new AggregateReRouteCreate()
}
public static create(route: AggregateReRoute) {
const aggregateRoute = new AggregateReRouteCreate()
aggregateRoute.appId = route.appId
aggregateRoute.name = route.name
aggregateRoute.aggregator = route.aggregator
aggregateRoute.priority = route.priority
aggregateRoute.reRouteIsCaseSensitive = route.reRouteIsCaseSensitive
aggregateRoute.reRouteKeys = route.reRouteKeys
aggregateRoute.upstreamHost = route.upstreamHost
aggregateRoute.upstreamHttpMethod = route.upstreamHttpMethod
aggregateRoute.upstreamPathTemplate = route.upstreamPathTemplate
return aggregateRoute
}
}
export class AggregateReRouteUpdate extends AggregateReRouteBase {
routeId = ''
concurrencyStamp = ''
public static empty() {
return new AggregateReRouteUpdate()
}
public static create(route: AggregateReRoute) {
const aggregateRoute = new AggregateReRouteUpdate()
aggregateRoute.aggregator = route.aggregator
aggregateRoute.concurrencyStamp = route.concurrencyStamp
aggregateRoute.priority = route.priority
aggregateRoute.reRouteIsCaseSensitive = route.reRouteIsCaseSensitive
aggregateRoute.reRouteKeys = route.reRouteKeys
aggregateRoute.routeId = route.reRouteId
aggregateRoute.upstreamHost = route.upstreamHost
aggregateRoute.upstreamHttpMethod = route.upstreamHttpMethod
aggregateRoute.upstreamPathTemplate = route.upstreamPathTemplate
return aggregateRoute
}
}
export class AggregateReRouteGetByPaged extends PagedAndSortedResultRequestDto {
appId = ''
filter = ''
public static empty() {
return new AggregateReRouteGetByPaged()
}
}

17
vueJs/src/lang/zh.ts

@ -72,6 +72,7 @@ export default {
group: '路由分组',
global: '全局配置',
route: '路由配置',
aggregateRoute: '聚合路由',
identityServer: '身份认证服务器',
clients: '客户端管理',
apiresources: 'Api资源管理',
@ -343,6 +344,7 @@ export default {
appIdHasRequired: '应用标识不能为空!',
upstreamPathTemplate: '上游请求路径',
upstreamHttpMethod: '上游请求方式',
upstreamHost: '上游主机地址',
downstreamHostAndPorts: '下游请求地址',
downstreamPathTemplate: '下游请求路径',
serviceName: '服务名称',
@ -369,7 +371,20 @@ export default {
ipAllowedList: 'Ip白名单',
ipBlockedList: 'Ip黑名单',
authenticationProviderKey: '身份认证程序',
allowedScopes: '允许认证范围'
allowedScopes: '允许认证范围',
createAggregateRoute: '新建聚合',
aggregateRouteName: '聚合名称',
reRouteKeys: '路由标识列表',
aggregateOptions: '聚合选项',
updateAggregateRoute: '编辑聚合',
updateAggregateRouteByName: '编辑聚合 {name}',
deleteAggregateRoute: '删除聚合',
deleteAggregateRouteByName: '删除聚合 {name}',
deleteAggregateRouteSuccess: '聚合路由 {name} 已删除!',
createAggregateRouteKey: '新建聚合参数',
aggregateRouteKey: '聚合路由标识',
aggregateParameter: '聚合参数',
aggregateJsonPath: 'Json路径'
},
identityServer: {
otherOpera: '更多操作',

10
vueJs/src/router/index.ts

@ -290,6 +290,16 @@ export const asyncRoutes: RouteConfig[] = [
icon: 'route',
roles: ['ApiGateway.Route']
}
},
{
path: 'aggregateRoute',
component: () => import('@/views/admin/apigateway/aggregateRoute.vue'),
name: 'aggregateRoute',
meta: {
title: 'aggregateRoute',
icon: 'aggregateRoute',
roles: ['ApiGateway.AggregateRoute']
}
}
]
},

295
vueJs/src/views/admin/apigateway/aggregateRoute.vue

@ -0,0 +1,295 @@
<template>
<div class="app-container">
<div class="filter-container">
<label
class="radio-label"
style="padding-left:10px;"
>{{ $t('apiGateWay.appId') }}</label>
<el-select
v-model="aggregateRouteGetPagedFilter.appId"
style="width: 250px;margin-left: 10px;"
class="filter-item"
:placeholder="$t('pleaseSelectBy', {name: $t('apiGateWay.appId')})"
>
<el-option
v-for="item in routeGroupAppIdOptions"
:key="item.appId"
:label="item.appName"
:value="item.appId"
/>
</el-select>
<label
class="radio-label"
style="padding-left:10px;"
>{{ $t('queryFilter') }}</label>
<el-input
v-model="aggregateRouteGetPagedFilter.filter"
:placeholder="$t('filterString')"
style="width: 250px;margin-left: 10px;"
class="filter-item"
/>
<el-button
class="filter-item"
style="margin-left: 10px; text-alignt"
type="primary"
@click="handleGetAggregateRoutes"
>
{{ $t('searchList') }}
</el-button>
<el-button
class="filter-item"
type="primary"
:disabled="!checkPermission(['ApiGateway.AggregateRoute.Create'])"
@click="handleCreateOrEditAggregateRoute()"
>
{{ $t('apiGateWay.createAggregateRoute') }}
</el-button>
</div>
<el-table
v-loading="aggregateRouteListLoading"
row-key="reRouteId"
:data="aggregateRouteList"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="handleSortChange"
>
<el-table-column
:label="$t('apiGateWay.aggregateRouteName')"
prop="name"
sortable
width="200px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('apiGateWay.upstreamPathTemplate')"
prop="upstreamPathTemplate"
width="250px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.upstreamPathTemplate }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('apiGateWay.upstreamHost')"
prop="upstreamHost"
width="250px"
align="center"
>
<template slot-scope="{row}">
<span>{{ row.upstreamHost }}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('apiGateWay.upstreamHttpMethod')"
prop="upstreamHttpMethod"
sortable
min-width="180"
align="center"
>
<template slot-scope="{row}">
<span>
<el-tag
v-for="(method, index) in row.upstreamHttpMethod"
:key="index"
:type="method | httpMethodsFilter"
style="margin-right: 4px;margin-top: 4px;"
>
{{ method }}
</el-tag>
</span>
</template>
</el-table-column>
<el-table-column
:label="$t('apiGateWay.reRouteKeys')"
prop="reRouteKeys"
width="140px"
align="center"
>
<template slot-scope="{row}">
<span>
<el-tag
v-for="(routeKey) in row.reRouteKeys"
:key="routeKey"
style="margin-right: 4px;margin-top: 4px;"
>
{{ routeKey }}
</el-tag>
</span>
</template>
</el-table-column>
<el-table-column
:label="$t('operaActions')"
align="center"
width="250px"
fixed="right"
>
<template slot-scope="{row}">
<el-button
:disabled="!checkPermission(['ApiGateway.AggregateRoute.Update'])"
size="mini"
type="primary"
@click="handleCreateOrEditAggregateRoute(row.reRouteId, row.name)"
>
{{ $t('apiGateWay.updateAggregateRoute') }}
</el-button>
<el-button
:disabled="!checkPermission(['ApiGateway.AggregateRoute.Delete'])"
size="mini"
type="warning"
@click="handleDeleteAggregateRoute(row.reRouteId, row.name)"
>
{{ $t('apiGateWay.deleteAggregateRoute') }}
</el-button>
</template>
</el-table-column>
</el-table>
<Pagination
v-show="routesCount>0"
:total="routesCount"
:page.sync="aggregateRouteGetPagedFilter.skipCount"
:limit.sync="aggregateRouteGetPagedFilter.maxResultCount"
@pagination="handleGetAggregateRoutes"
@sort-change="handleSortChange"
/>
<el-dialog
v-el-draggable-dialog
width="800px"
:visible.sync="showEditAggregateRouteDialog"
:title="editRouteTitle"
custom-class="modal-form"
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
>
<AggregateRouteCreateOrEditForm
:aggregate-route-id="editAggregateRouteId"
:app-id-options="routeGroupAppIdOptions"
@closed="handleAggregateRouteEditFormClosed"
/>
</el-dialog>
</div>
</template>
<script lang="ts">
import { checkPermission } from '@/utils/permission'
import { Component, Vue } from 'vue-property-decorator'
import Pagination from '@/components/Pagination/index.vue'
import AggregateRouteCreateOrEditForm from './components/AggregateRouteCreateOrEditForm.vue'
import ApiGatewayService, { RouteGroupAppIdDto, AggregateReRoute, AggregateReRouteGetByPaged } from '@/api/apigateway'
@Component({
name: 'AggregateRoute',
components: {
Pagination,
AggregateRouteCreateOrEditForm
},
methods: {
checkPermission
},
filters: {
httpMethodsFilter(httpMethod: string) {
const statusMap: { [key: string]: string } = {
GET: '',
POST: 'success',
PUT: 'warning',
PATCH: 'warning',
DELETE: 'danger'
}
return statusMap[httpMethod.toUpperCase()]
}
}
})
export default class extends Vue {
private editAggregateRouteId: string
private routesCount: number
private editRouteTitle: any
private aggregateRouteList: AggregateReRoute[]
private aggregateRouteListLoading: boolean
private showEditAggregateRouteDialog: boolean
private aggregateRouteGetPagedFilter: AggregateReRouteGetByPaged
private routeGroupAppIdOptions: RouteGroupAppIdDto[]
constructor() {
super()
this.editAggregateRouteId = ''
this.routesCount = 0
this.editRouteTitle = ''
this.aggregateRouteListLoading = false
this.showEditAggregateRouteDialog = false
this.aggregateRouteList = new Array<AggregateReRoute>()
this.aggregateRouteGetPagedFilter = new AggregateReRouteGetByPaged()
this.routeGroupAppIdOptions = new Array<RouteGroupAppIdDto>()
}
mounted() {
ApiGatewayService.getRouteGroupAppIds().then(appKeys => {
this.routeGroupAppIdOptions = appKeys.items
})
}
private handleGetAggregateRoutes() {
if (this.aggregateRouteGetPagedFilter.appId) {
this.aggregateRouteListLoading = true
ApiGatewayService.getAggregateReRoutes(this.aggregateRouteGetPagedFilter).then(routes => {
this.aggregateRouteList = routes.items
this.routesCount = routes.totalCount
}).finally(() => {
this.aggregateRouteListLoading = false
})
} else {
const errorMessage = this.$t('apiGateWay.appIdHasRequired').toString()
this.$message.warning(errorMessage)
}
}
private handleSortChange(column: any) {
this.aggregateRouteGetPagedFilter.sorting = column.prop
}
private handleDeleteAggregateRoute(reRouteId: string, name: string) {
this.$confirm(this.l('apiGateWay.deleteAggregateRouteByName', { name: name }),
this.l('apiGateWay.deleteAggregateRoute'), {
callback: (action) => {
if (action === 'confirm') {
ApiGatewayService.deleteAggregateReRoute(reRouteId).then(() => {
this.$message.success(this.l('apiGateWay.deleteAggregateRouteSuccess', { name: name }))
this.handleGetAggregateRoutes()
})
}
}
})
}
private handleCreateOrEditAggregateRoute(reRouteId: string, name: string) {
this.editAggregateRouteId = reRouteId
this.editRouteTitle = this.$t('apiGateWay.createAggregateRoute')
if (reRouteId) {
this.editRouteTitle = this.$t('apiGateWay.updateAggregateRouteByName', { name: name })
}
this.showEditAggregateRouteDialog = true
}
private handleAggregateRouteEditFormClosed(changed: boolean) {
this.editAggregateRouteId = ''
this.editRouteTitle = ''
this.showEditAggregateRouteDialog = false
if (changed && this.aggregateRouteGetPagedFilter.appId) {
this.handleGetAggregateRoutes()
}
}
private l(name: string, values?: any[] | { [key: string]: any }) {
return this.$t(name, values).toString()
}
}
</script>

197
vueJs/src/views/admin/apigateway/components/AggregateRouteCreateOrEditForm.vue

@ -0,0 +1,197 @@
<template>
<el-form
ref="formAggregateRoute"
label-width="100px"
:model="aggregateRoute"
>
<el-row>
<el-col :span="24">
<el-form-item
v-if="!isEditRoute"
prop="appId"
:label="$t('apiGateWay.appId')"
>
<el-select
v-model="aggregateRoute.appId"
style="width: 100%"
:placeholder="$t('pleaseSelectBy', {name: $t('apiGateWay.appId')})"
>
<el-option
v-for="item in appIdOptions"
:key="item.appId"
:label="item.appName"
:value="item.appId"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item
prop="name"
:label="$t('apiGateWay.aggregateRouteName')"
>
<el-input
v-model="aggregateRoute.name"
:placeholder="$t('pleaseInputBy', {key: $t('apiGateWay.aggregateRouteName')})"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
prop="priority"
:label="$t('apiGateWay.priority')"
>
<el-input
v-model="aggregateRoute.priority"
type="number"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="16">
<el-form-item
prop="upstreamHost"
:label="$t('apiGateWay.upstreamHost')"
>
<el-input
v-model="aggregateRoute.upstreamHost"
:placeholder="$t('pleaseInputBy', {key: $t('apiGateWay.upstreamHost')})"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
prop="reRouteIsCaseSensitive"
:label="$t('apiGateWay.reRouteIsCaseSensitive')"
>
<el-switch
v-model="aggregateRoute.reRouteIsCaseSensitive"
:placeholder="$t('pleaseInputBy', {key: $t('apiGateWay.reRouteIsCaseSensitive')})"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item
prop="upstreamPathTemplate"
:label="$t('apiGateWay.upstreamPathTemplate')"
>
<el-input
v-model="aggregateRoute.upstreamPathTemplate"
:placeholder="$t('pleaseInputBy', {key: $t('apiGateWay.upstreamPathTemplate')})"
/>
</el-form-item>
<el-form-item
prop="upstreamHttpMethod"
:label="$t('apiGateWay.upstreamHttpMethod')"
>
<el-input-tag
v-model="aggregateRoute.upstreamHttpMethod"
:placeholder="$t('pleaseInputBy', {key: $t('apiGateWay.upstreamHttpMethod')})"
/>
</el-form-item>
<el-form-item
prop="reRouteKeys"
:label="$t('apiGateWay.reRouteKeys')"
>
<el-input-tag
v-model="aggregateRoute.reRouteKeys"
:placeholder="$t('pleaseInputBy', {key: $t('apiGateWay.reRouteKeys')})"
/>
</el-form-item>
<el-form-item>
<el-button
class="cancel"
style="width:100px;right: 120px;position: absolute;"
@click="onCancel"
>
{{ $t('global.cancel') }}
</el-button>
<el-button
class="confirm"
type="primary"
style="width:100px;right: 10px;position: absolute;"
@click="onSaveAggregateRoute"
>
{{ $t('global.confirm') }}
</el-button>
</el-form-item>
</el-form>
</template>
<script lang="ts">
import ElInputTag from '@/components/InputTag/index.vue'
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import ApiGatewayService, { RouteGroupAppIdDto, AggregateReRoute, AggregateReRouteCreate, AggregateReRouteUpdate } from '@/api/apigateway'
@Component({
name: 'AggregateRouteCreateOrEditForm',
components: {
ElInputTag
}
})
export default class extends Vue {
@Prop({ default: '' })
private aggregateRouteId!: string
@Prop({ default: () => new Array<RouteGroupAppIdDto>() })
private appIdOptions!: RouteGroupAppIdDto[]
private aggregateRoute: AggregateReRoute
get isEditRoute() {
if (this.aggregateRouteId) {
return true
}
return false
}
constructor() {
super()
this.aggregateRoute = AggregateReRoute.empty()
}
@Watch('aggregateRouteId', { immediate: true })
private onAggregateRouteIdChanged() {
if (this.aggregateRouteId) {
ApiGatewayService.getAggregateReRouteByRouteId(this.aggregateRouteId).then(aggregateRoute => {
this.aggregateRoute = aggregateRoute
})
} else {
this.aggregateRoute = AggregateReRoute.empty()
}
}
private onSaveAggregateRoute() {
if (this.isEditRoute) {
const updateAggregateRoute = AggregateReRouteUpdate.create(this.aggregateRoute)
ApiGatewayService.updateAggregateReRoute(updateAggregateRoute).then(route => {
this.aggregateRoute = route
this.reset()
this.$emit('closed', true)
})
} else {
const createAggregateRoute = AggregateReRouteCreate.create(this.aggregateRoute)
ApiGatewayService.createAggregateReRoute(createAggregateRoute).then(route => {
this.aggregateRoute = route
this.reset()
this.$emit('closed', true)
})
}
}
private onCancel() {
this.reset()
this.$emit('closed', false)
}
private reset() {
this.aggregateRoute = AggregateReRoute.empty()
const formAggregateRoute = this.$refs.formAggregateRoute as any
formAggregateRoute.resetFields()
}
}
</script>

1
vueJs/src/views/admin/apigateway/components/RouteCreateOrEditForm.vue

@ -34,7 +34,6 @@
<el-row>
<el-col :span="12">
<el-form-item
v-popover:popRouteName
prop="reRouteName"
:label="$t('apiGateWay.reRouteName')"
>

Loading…
Cancel
Save