# FluentHttp **Repository Path**: yulou/FluentHttp ## Basic Information - **Project Name**: FluentHttp - **Description**: FluentHttp 原地址-https//github.com/lysilver/FluentHttp - **Primary Language**: C# - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-04-19 - **Last Updated**: 2025-08-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 声明式http调用 http调用、支持随机、轮询、加权随机负载均衡 服务健康需要自行实现IServiceDiscovery 动态改变url配置 ## 使用方式 - 引入dll Y.FluentHttp FluentHttp.SourceGenerator - DI注入 ```csharp builder.Services.AddHttpClient(); // builder.Services.AddHttpHeader(); builder.Services.AddDefaultFluentHttp(); builder.Services.AddFluentHttp(ServiceLifetime.Scoped); ``` - 自定义DI注入 ```csharp builder.Services.AddHttpClient(); // 必须 // 自行实现服务间的传递的参数通过header // builder.Services.AddHttpHeader(); builder.Services.AddLoadBalancing(); // 可选 builder.Services.AddHttpAdapter(); // 必须 // 注入生成的服务 builder.Services.AddFluentHttp(ServiceLifetime.Scoped); ``` 实现IContext接口 提供header信息 、json序列化 ```csharp public class CustContext : IContext { private readonly Func> func = () => { Dictionary keys = new() { { "trace_id", Guid.NewGuid().ToString()} }; return keys; }; public DefaultContext() { } // 根据同步的id返回不同的header public Task> GetHeader(string appId) { return Task.FromResult(func.Invoke()); } public JsonSerializerOptions? JsonSerializerOptions() { return null; } } ``` 实现IServiceDiscovery接口 提供url,默认的是从配置文件获取 注入容器,必须在FluentHttp()之前 或者在之后使用services.Replace(ServiceDescriptor.Singleton(typeof(IServiceDiscovery), typeof(CustServiceDiscovery))); ```csharp public class CustServiceDiscovery : IServiceDiscovery { private readonly string Node = "YL:FluentHttp"; private readonly IConfiguration _configuration; public DefaultServiceDiscovery(IConfiguration configuration) { _configuration = configuration; } public Task?> GetUrls() { var services = _configuration.GetSection(Node).Get>(); return Task.FromResult(services); } } ``` ```csharp // 如果添加了自行替换AddHttpHeader() 使用 services.Replace(ServiceDescriptor.Singleton(typeof(IContext), typeof(CustContext))); // 没有添加 services.TryAddSingleton(); // 放在 builder.Services.AddFluentHttp(ServiceLifetime.Scoped); 之前 // 默认实现的是配置文件 配置文件参考 services.TryAddSingleton(); ``` ### 支持请求 #### GET POST DELETE PUT PATCH - [FluentHttp(AppId = "order", Name = "OrderConsumer", Auth = "jwt")] Name-生成的类名 Auth- 验证的header取值 - [HttpGet(AppId = "order", Url = "api/v1/order/all")] - [HttpPost(AppId = "order", Url = "api/v1/order/all")] - [HttpPut(AppId = "order", Url = "api/v1/order/all")] - [HttpPatch(AppId = "order", Url = "api/v1/order/all")] - [HttpDelete(AppId = "order", Url = "api/v1/order/all")] - [HttpFileUpload(AppId = "order", Url = "api/v1/order/all")] - [HttpResponseMessage(AppId = "order", Url = "/api/v1/order", HttpMethod = HttpMethodEnum.Post)] - [FilePathVariable]文件路径 - [PathVariable]-url path变量 - AppId-服务的唯一名称 - Url - url - ReturnString - 返回string 类型 ```csharp [FluentHttp(AppId = "order", Url = "api/v1/order", Name = "OrderConsumer", Auth = "jwt")] public interface IOrderConsumer { /// /// 获取所有订单 /// /// [HttpGet(AppId = "order", Url = "all")] Task> GetOrders(); /// /// 获取所有订单 /// 接口上的AppId优先级低于方法上的 /// 前缀/开头的Url不会拼接接口上的Url /// /// [HttpGet(Url = "/api/v1/order/all")] Task> GetAllOrders(); /// /// 根据id获取订单 /// /// /// [HttpGet(AppId = "order", Url = "/api/v1/order/{id}")] Task GetOrderById([PathVariable] int id); [HttpGet(AppId = "order", Url = "/api/v1/order/{id}", ReturnString = true)] Task GetOrderByIdToString([PathVariable] int id); /// /// 创建订单 /// /// /// [HttpPost(AppId = "order", Url = "/api/v1/order")] Task CreateOrder(Order order); [HttpPut(AppId = "order", Url = "/api/v1/order/{id}")] Task UpdateOrder([PathVariable] int id, Order order); [HttpDelete(AppId = "order", Url = "/api/v1/order/{id}")] Task DeleteOrder([PathVariable] int id); [HttpFileUpload(AppId = "order", Url = "/api/v1/order/single-file")] Task UploadFileByPath([FilePathVariable] string filepath); [HttpFileUpload(AppId = "order", Url = "/api/v1/order/multi-file")] Task UploadMultipartFileByPath([FilePathVariable] List filepath); } ``` ### 配置文件参考 ```json { "YL": { "FluentHttp": { "order": { "LoadBalancingPolicy": null, "Destinations": [ { "Weight": 6, "BaseUrl": "http://localhost:9000" }, { "Weight": 2, "BaseUrl": "http://localhost:9000" } ] } } } } ``` ### demo 参考 FluentHttp.Test ### 版本 > 注意 如果更新版本可能需要删除bin obj 重新生成 #### v0.0.1 - [x] HttpGet - [x] HttpPost - [x] HttpPut - [x] HttpDelete - [x] HttpFileUpload - [x] 轮询(RoundRobin) - [x] 随机(Random) - [x] 加权随机(WeightedRandom) #### v0.0.2 fix: bug #### v0.0.3 - [x] HttpPatch - [x] HttpResponseMessage #### v0.0.4 sourcelink #### v0.0.5 - [x] 修改生成的注入的服务为当前的命名空间 - [x] add AddDefaultFluentHttp #### v0.0.6 - [x] 文件上传 #### v0.0.7 - [x] IIncrementalGenerator