nuget
- Ocelot 24.0.0
- Ocelot.Provider.Consul 24.0.0
- Swashbuckle.AspNetCore 6.6.2
- Microsoft.AspNetCore.Authentication.JwtBearer 8.0.13
路由配置文件
文件名称:【configuration.json】 , 需要配置复制到输出目录
此处提供两个测试服务
{
"Routes": [
{
"DownstreamPathTemplate": "/api/Common/{url}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/api/Common/{url}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"UseServiceDiscovery": true,
"ServiceName": "CommonWebApi",
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
},
{
"DownstreamPathTemplate": "/Common/swagger.json",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/Common/swagger.json",
"UpstreamHttpMethod": [ "Get", "Post" ],
"UseServiceDiscovery": true,
"ServiceName": "CommonWebApi",
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
},
{
"DownstreamPathTemplate": "/api/DevOps/{url}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/api/DevOps/{url}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"UseServiceDiscovery": true,
"ServiceName": "DevOpsWebApi",
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
},
{
"DownstreamPathTemplate": "/DevOps/swagger.json",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/DevOps/swagger.json",
"UpstreamHttpMethod": [ "Get", "Post" ],
"UseServiceDiscovery": true,
"ServiceName": "DevOpsWebApi",
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}
],
"GlobalConfiguration": {
//"BaseUrl": "http://192.168.2.1:7000",
"ServiceDiscoveryProvider": {
"Host": "192.168.0.1",
"Port": 7500,
"Type": "Consul"
}
}
}
代码
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Consul;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Add Ocelot configuration
builder.Configuration.AddJsonFile("configuration.json", optional: false, reloadOnChange: true);
//网关项目名称
string apiName = "Gateway";
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(delegate (SwaggerGenOptions c)
{
c.SwaggerDoc(apiName, new OpenApiInfo
{
Title = apiName + "接口"
});
//swagger文档文件名称
var swaggerXmlName = "Gateway.xml";
if (!string.IsNullOrWhiteSpace(swaggerXmlName.Trim()))
{
string[] array = swaggerXmlName.Split(',');
foreach (string path in array)
{
string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
if (File.Exists(filePath))
{
c.IncludeXmlComments(filePath, includeControllerXmlComments: true);
}
}
}
//token
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new List<string>()
} });
});
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = (context) =>
{
//数据验证失败时才会执行
//返回第一条报错
var error = context.ModelState.Values.FirstOrDefault(f => f.ValidationState != Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Valid);//.Select(f => new KeyValuePair<string, IEnumerable<string>>(f.Key, f.Value.Errors.Select(e => e.ErrorMessage)));
if (error != null && error.Errors != null && error.Errors.Count > 0)
{
var errMsg = error.Errors.First().ErrorMessage;
return new JsonResult(new { Code = 1, Message = errMsg });
}
return new JsonResult(new { Code = 1, Message = "ModelError", Data = context.ModelState.Values });
};
});
//JWT
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
var key = "YK0cGQWeS5zuIGCov9Om7IuQAHDRV/hd2po8YtXU0cA=";
if (string.IsNullOrWhiteSpace(key))
{
throw new Exception("请配置jwt key");
}
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = "BoawayCommon",
ValidAudience = "BoawayCommon",
ValidateIssuer = true,
ValidateAudience = true,
RequireExpirationTime = false,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
};
});
builder.Services.AddOcelot().AddConsul();
var app = builder.Build();
string swaggerName = string.Empty;
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
swaggerName = "Gateway";
//app.UseSwagger();
app.UseSwagger(c =>
{
c.RouteTemplate = "{documentName}/swagger.json";
});
}
else
{
swaggerName = "Common,DevOps";
app.UseSwagger();
}
List<string> swaggerNameList = swaggerName.Split(",").ToList();
app.UseSwaggerUI(options =>
{
swaggerNameList.ForEach(m =>
{
options.SwaggerEndpoint($"/{m}/swagger.json", m);
});
});
//app.UseDomainServices(builder.Configuration);
app.UseRouting();
app.MapControllers();
// Use Ocelot middleware
app.UseOcelot().Wait();
app.Run();
备注
- 需要配置api项目输出文档
- 需要注意configuration文件中consul的地址
- 代码中实现了在调试模式下只显示网关中的swagger,发布模式下显示微服务下其他服务的接口文档
如果需要扩展swagger功能可以参考以下内容
[参考]
.net swagger知识点汇总 自定义swagger返回值.net5 swagger 枚举注释.net5 过滤器返回通用结构 swagger使用IApplicationModelProvider自动化添加ProducesResponseType
留待后查,同时方便他人