sunpengfei
2025-08-20 b15ba0723040b5e9a348662a09af824f2d5ae9e6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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 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<string> SendHttpAsync(this object request, string serviceName, string route, EnumResourceMethod method, EnumResourceHttpProvider? provider = null)
        {
            serviceName = App.GetConfig<string>($"{serviceName}:ServiceName");
            var url = await GetUrl(serviceName, route);
            var builder = HttpRequestBuilder.Create(method.GetMethod(), url);
            if (method == EnumResourceMethod.Get)
                builder = builder.WithQueryParameters(request);
            else
                builder = builder.SetJsonContent(request);
            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<TResponse> SendHttpAsync<TRequest, TResponse>(this TRequest request, EnumResourceHttpProvider? provider = null)
        {
            var requestType = typeof(TRequest);
            var resourceAttribute = requestType.GetCustomAttribute<ResourceAttribute>();
            if (resourceAttribute == null) throw Oops.Oh(EnumErrorCodeType.s400, "缺失资源特性");
            var controller = resourceAttribute.Controllers.FirstOrDefault();
            var resourceControllerAttribute = controller.GetCustomAttribute<EnumResourceController, ResourceControllerAttribute>();
            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<Resource>().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<TResponse>();
            return response;
        }
 
        public static HttpMethod GetMethod(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<string> GetUrl(string serviceName, string route)
        {
            var domain = await GetHealthyServiceDomain(serviceName);
            return $"{domain}{route}";
        }
 
        /// <summary>
        /// 获取健康服务域名
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public static async Task<string> GetHealthyServiceDomain(string serviceName)
        {
            var env = App.GetConfig<string>("Environment");
            serviceName = $"{env}_{serviceName}";
 
            var queryResult = await App.GetRequiredService<IConsulClient>().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];
        }
 
    }
}