using Azure;
using Consul;
using Furion;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Furion.HttpRemote;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using RabbitMQ.Client;
using RTools_NTS.Util;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace FlexJobApi.Core
{
public static class ResourceHttpUtils
{
///
/// 发送请求
///
/// 请求参数
/// 服务名称
/// 路由
/// 请求方式
/// 资源提供者
/// 访问令牌
/// 刷新令牌
///
public static async Task SendHttpAsync(
this object request,
string serviceName,
string route,
EnumResourceMethod method,
EnumResourceHttpProvider? provider = null,
string accessToken = null,
string refreshToken = null)
{
serviceName = App.GetConfig($"{serviceName}:ServiceName");
var url = await GetUrl(serviceName, route);
var builder = HttpRequestBuilder.Create(method.GetHttpMethod(), url);
if (method == EnumResourceMethod.Get)
builder = builder.WithQueryParameters(request);
else
builder = builder.SetJsonContent(request);
if (accessToken.IsNotNull())
{
builder = builder.WithHeader("Authorization", accessToken);
}
if (refreshToken.IsNotNull())
{
builder = builder.WithHeader("X-Authorization", refreshToken);
}
IResourceHttpProvider httpProvider =
provider == EnumResourceHttpProvider.SystemUser
? new SystemUserResourceHttpProvider()
: provider == EnumResourceHttpProvider.ElectronSignServer
? new ElectronSignServerResourceHttpProvider()
: provider == EnumResourceHttpProvider.ElectronSignServerCustomer
? new ElectronSignServerCustomerResourceHttpProvider()
: new DefaultResourceHttpProvider();
var response = await httpProvider.SendAsStringAsync(builder);
return response;
}
///
/// 发送请求
///
///
///
///
///
///
public static async Task SendHttpAsync(
this TRequest request,
EnumResourceHttpProvider? provider = null)
{
var requestType = typeof(TRequest);
var resourceAttribute = requestType.GetCustomAttribute();
if (resourceAttribute == null) throw Oops.Oh(EnumErrorCodeType.s400, "缺失资源特性");
var controller = resourceAttribute.Controllers.FirstOrDefault();
var resourceControllerAttribute = controller.GetCustomAttribute();
if (resourceAttribute == null) throw Oops.Oh(EnumErrorCodeType.s400, "缺失控制器特性");
var serviceName = resourceControllerAttribute.Service.ToString();
var route = resourceAttribute.Route;
var method = resourceAttribute.Method;
var requestXmlDoc = await requestType.GetXmlDocMemberAsync();
if (route.IsNull() || method == EnumResourceMethod.None)
{
var resource = await Db.GetRepository().AsQueryable().AsNoTracking()
.Where(it =>
it.ServiceName == serviceName
&& it.ControllerName == resourceControllerAttribute.ControllerName
&& it.Code == requestXmlDoc.Name)
.Select(it => new
{
it.Route,
it.Method
})
.FirstOrDefaultAsync();
if (resource == null) throw Oops.Oh(EnumErrorCodeType.s404, "资源");
route = resource.Route;
method = resource.Method;
}
var responseJson = await request.SendHttpAsync(serviceName, route, method, provider);
var response = responseJson.JsonTo();
return response;
}
///
/// 获取请求方式
///
///
///
public static HttpMethod GetHttpMethod(this EnumResourceMethod method)
{
switch (method)
{
case EnumResourceMethod.Get:
return HttpMethod.Get;
case EnumResourceMethod.Post:
return HttpMethod.Post;
case EnumResourceMethod.Put:
return HttpMethod.Put;
case EnumResourceMethod.Delete:
return HttpMethod.Delete;
default:
throw Oops.Oh(EnumErrorCodeType.s400, "不支持的请求类型");
}
}
///
/// 获取健康服务地址
///
///
///
///
public static async Task GetUrl(string serviceName, string route)
{
var domain = await GetHealthyServiceDomain(serviceName);
return $"{domain}{route}";
}
///
/// 获取健康服务域名
///
///
///
public static async Task GetHealthyServiceDomain(string serviceName)
{
var env = App.GetConfig("Environment");
serviceName = $"{env}_{serviceName}";
var queryResult = await App.GetRequiredService().Health.Service(serviceName, null, true);
if (queryResult.StatusCode != System.Net.HttpStatusCode.OK)
throw Oops.Oh(EnumErrorCodeType.s404, $"微服务{serviceName}");
var domains = queryResult.Response
.Select(s => $"http://{s.Service.Address}:{s.Service.Port}")
.ToList();
if (domains.IsNull())
throw Oops.Oh(EnumErrorCodeType.s404, $"微服务{serviceName}");
// 轮询选择实例
int randomIndex = new Random().Next(domains.Count);
return domains[randomIndex];
}
}
}