网站首页 网站源码
using System.Text.Json.Serialization;
using AgileConfig.Client;
using Dpz.Core.Hangfire;
using Dpz.Core.Infrastructure.Configuration;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Scalar.AspNetCore;
const string originsName = "Open";
Log.Logger = new LoggerConfiguration().Enrich.FromLogContext().CreateBootstrapLogger();
try
{
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseAgileConfig(new ConfigClient(builder.Configuration));
var configuration = builder.Configuration;
var seq = configuration.GetSection("LogSeq").Get<LogSeq>();
builder.Host.ConfigurationLog(seq);
const int threads = 100;
if (ThreadPool.SetMinThreads(threads, threads))
{
Log.Information(
"set worker threads:{WorkerThreads},set completion port threads {CompletionPortThreads}",
threads,
threads
);
}
#region services
var services = builder.Services;
// IoC
services.AddDefaultServices(configuration).AddAppScoped();
services
.AddControllers()
// .AddXmlDataContractSerializerFormatters()
.AddXmlSerializerFormatters()
.AddMessagePackSerializerFormatters()
.AddJsonOptions(opts =>
{
opts.JsonSerializerOptions.Converters.Add(new TimeSpanConverter());
opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
services.AddResponseCompression(options =>
{
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "application/font-woff2", "image/svg+xml", "text/plain", "application/lrc" }
);
});
services.Configure<BrotliCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Optimal;
});
services.Configure<GzipCompressionProviderOptions>(options =>
{
options.Level = CompressionLevel.Optimal;
});
services.Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = int.MaxValue;
});
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(options =>
{
var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
var description = "";
if (!string.IsNullOrEmpty(basePath))
{
var xmlPath = Path.Combine(basePath, "Dpz.Core.WebApi.xml");
options.IncludeXmlComments(xmlPath);
var viewModelXmlPath = Path.Combine(basePath, "Dpz.Core.Public.ViewModel.xml");
options.IncludeXmlComments(viewModelXmlPath);
var readmePath = Path.Combine(basePath, "README.md");
if (File.Exists(readmePath))
{
description = File.ReadAllText(readmePath);
}
}
options.SwaggerDoc(
"v1",
new OpenApiInfo
{
Title = "Dpz.Core.WebApi",
Version = Assembly.GetEntryAssembly()?.GetName().Version?.ToString(),
Description = description,
}
);
options.AddSecurityDefinition(
"Bearer",
new OpenApiSecurityScheme
{
Description = "使用Bearer方案的JWT授权标头(示例:“ Bearer JWT_Token”)",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
}
);
options.AddSecurityRequirement(
new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer",
},
},
Array.Empty<string>()
},
}
);
});
//缓存
services.AddRedisCacheOutput(configuration.GetConnectionString("redis"));
services.AddBusinessServices(configuration);
// Cors
services.AddCors(options =>
{
options.AddPolicy(
originsName,
cfg =>
{
cfg.WithOrigins(configuration.GetSection("Origins").Get<string[]>())
.WithMethods("GET", "PUT", "POST", "DELETE", "PATCH")
.AllowAnyHeader();
}
);
});
services.Configure<TokenManagement>(configuration.GetSection("TokenManagement"));
services
.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
var token = configuration.GetSection("TokenManagement").Get<TokenManagement>();
x.RequireHttpsMetadata = true;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(token.Secret)),
ValidIssuer = token.Issuer,
ValidAudience = token.Audience,
ValidateIssuer = true,
ValidateAudience = true,
};
});
services.AddDataProtection().SetApplicationName(AuthorizeCookieName);
services
.AddOptions<KeyManagementOptions>()
.Configure<IServiceScopeFactory>(
(options, factory) =>
{
options.XmlRepository = new XmlRepositoryService(
factory,
AuthorizeCookieName + ".Key"
);
}
);
services.AddAuthorization(options =>
{
options.AddPolicy(
ApiPermission.System,
policy => policy.Requirements.Add(new PermissionRequirement(Permissions.System))
);
});
services.AddRazorPages(x =>
{
x.Conventions.AddPageRoute("/SignIn", "signIn.html");
});
var webApiHangfireCollectionPrefix =
configuration["WebApiHangfireCollectionPrefix"] ?? throw new InvalidConfigurationException();
services.AddHangfireService(configuration, webApiHangfireCollectionPrefix);
#endregion
var app = builder.Build();
#region configuration
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSerilogRequestLogging(options =>
{
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
diagnosticContext.Set(
"UserAgent",
httpContext.Request.Headers["User-Agent"].ToString()
);
diagnosticContext.Set("IpAddress", httpContext.Request.GetIpAddress());
};
});
app.UseResponseHeaders().UseRequestRecord().UseDateTimeLocalFormat();
app.UseResponseCompression();
app.UseSwagger(options =>
{
options.RouteTemplate = "{documentName}/open-api.json";
});
// app.UseSwaggerUI(options =>
// {
// options.RoutePrefix = "";
// options.SwaggerEndpoint("/v1/open-api.json", "Dpz.Core.WebApi v1");
// options.InjectStylesheet("https://dpangzi.com/darkmode/theme-material.css");
// });
app.MapScalarApiReference(options =>
{
options.Title = "Dpz.Core.WebApi v1";
options.WithOpenApiRoutePattern("/v1/open-api.json");
options.Favicon = "https://dpangzi.com/favicon.ico";
options.Theme = ScalarTheme.Moon;
options.HideDarkModeToggle = false;
});
app.GetHostingEnvironment();
// //强制HTTPS
// app.UseHttpsRedirection();
app.UseRouting();
app.MapRazorPages();
app.UseCors(originsName);
//身份认证
app.UseAuthentication();
//身份授权
app.UseAuthorization();
app.MapControllers();
//app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
#if DEBUG
app.HangfireSetting();
#endif
#endregion
app.MapGet("/ping", () => "pong");
app.MapGet("/datetime", () => $"{DateTime.Now:yyyy/Mm/dd HH:mm:ss}\r\n{Environment.MachineName}");
Log.Information("Starting web api host,current process id:{ID}", Environment.ProcessId);
app.Run();
}
catch (Exception e)
{
Console.Error.WriteLine(e);
Log.Fatal(e, "Host terminated unexpectedly");
}
/// <summary>
///
/// </summary>
public partial class Program
{
/// <summary>
/// 身份认证Cookie名称
/// </summary>
public const string AuthorizeCookieName = "Dpz.Web.Api.Server.Authoriza";
/// <summary>
/// 账号Cookie名称
/// </summary>
public const string AccountCookieName = "Dpz.Web.Api.Server.Account";
}
这段代码是一个 ASP.NET Core Web API 应用程序的启动代码,主要功能包括配置服务、设置中间件、处理请求和响应等。以下是对代码的详细解释:
代码开始部分引入了一些必要的命名空间,包括日志、配置、依赖注入、数据保护、Hangfire、Swagger等。
使用 Serilog 进行日志记录,创建一个引导日志记录器。
使用 WebApplication.CreateBuilder(args)
创建一个 Web 应用程序的构建器。
通过 builder.Host.UseAgileConfig
使用 AgileConfig 进行配置管理。
设置最小工作线程数,确保应用程序能够处理并发请求。
在 #region services
部分,配置了多个服务:
AddDefaultServices
和 AddAppScoped
方法注册默认服务和应用程序范围的服务。在 #region configuration
部分,配置了中间件:
/ping
和 /datetime
,用于测试 API 是否正常工作。在 catch
块中捕获异常并记录错误信息。
定义了一个 Program
类,包含一些常量用于身份认证和账号 Cookie 的名称。
这段代码是一个完整的 ASP.NET Core Web API 应用程序的启动配置,涵盖了服务注册、中间件配置、日志记录、身份验证、授权、CORS、Swagger 文档生成等多个方面,旨在提供一个功能齐全的 Web API 服务。