You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
4.5 KiB

4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
  1. #if NETCORE
  2. using System;
  3. using Microsoft.AspNetCore.Http;
  4. using Microsoft.AspNetCore.Hosting;
  5. using Microsoft.Extensions.Hosting;
  6. using Microsoft.Extensions.Configuration;
  7. using Microsoft.Extensions.DependencyInjection;
  8. using Microsoft.AspNetCore.Builder;
  9. using System.Threading.Tasks;
  10. using Microsoft.AspNetCore.Server.Kestrel.Core;
  11. using Microsoft.AspNetCore.ResponseCompression;
  12. namespace Apewer.Web
  13. {
  14. /// <summary></summary>
  15. public abstract class AspNetCoreStartup
  16. {
  17. /// <summary>处理 WebSocket 请求。</summary>
  18. /// <remarks>默认值:FALSE。</remarks>
  19. public virtual bool UseWebSocket { get; protected set; } = false;
  20. /// <summary>WebSocket 保持活动的间隔时间,单位为秒。</summary>
  21. /// <remarks>默认值:10。</remarks>
  22. public virtual int KeepAlive { get; } = 10;
  23. /// <summary>处理请求。</summary>
  24. /// <param name="context"></param>
  25. public abstract void OnContext(HttpContext context);
  26. /// <summary>使用压缩。</summary>
  27. public virtual bool UseCompression { get => false; }
  28. /// <summary>处理 WebSocket 请求。</summary>
  29. public virtual void OnWebSocket(HttpContext context, System.Net.WebSockets.WebSocket webSocket) { }
  30. /// <summary>限制请求体的字节数,默认值:1073741824(1GB)。</summary>
  31. public virtual long MaxRequestBodySize { get => 1073741824L; }
  32. #region Runtime
  33. bool _usedWebSocket = false;
  34. IConfiguration _configuration;
  35. /// <summary></summary>
  36. public AspNetCoreStartup() { }
  37. /// <summary></summary>
  38. public AspNetCoreStartup(IConfiguration configuration) => _configuration = configuration;
  39. /// <summary>使用此方法添加服务到容器。</summary>
  40. /// <remarks>此方法由运行时调用。</remarks>
  41. public void ConfigureServices(IServiceCollection services)
  42. {
  43. var maxRequestBodySize = MaxRequestBodySize;
  44. if (maxRequestBodySize < 1L) maxRequestBodySize = 1073741824L;
  45. services.Configure<KestrelServerOptions>(options =>
  46. {
  47. // 同步 IO。
  48. options.AllowSynchronousIO = true;
  49. // 限制请求大小。
  50. options.Limits.MaxRequestBodySize = maxRequestBodySize;
  51. // 在 Response 中不包含 Server 属性。
  52. options.AddServerHeader = false;
  53. });
  54. services.Configure<IISServerOptions>(options =>
  55. {
  56. // 同步 IO。
  57. options.AllowSynchronousIO = true;
  58. // 限制请求大小。
  59. options.MaxRequestBodySize = maxRequestBodySize;
  60. });
  61. if (UseCompression)
  62. {
  63. services.AddResponseCompression(options =>
  64. {
  65. options.EnableForHttps = true;
  66. options.Providers.Add<BrotliCompressionProvider>();
  67. options.Providers.Add<GzipCompressionProvider>();
  68. });
  69. }
  70. services.AddControllers();
  71. services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
  72. }
  73. /// <remarks>此方法由运行时调用。</remarks>
  74. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  75. {
  76. if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
  77. _usedWebSocket = UseWebSocket;
  78. if (_usedWebSocket)
  79. {
  80. var wsOptions = new WebSocketOptions();
  81. var keepAlive = KeepAlive;
  82. if (keepAlive > 0) wsOptions.KeepAliveInterval = TimeSpan.FromSeconds(keepAlive);
  83. app.UseWebSockets(wsOptions);
  84. }
  85. app.Run(Handler);
  86. }
  87. Task Handler(HttpContext context)
  88. {
  89. try
  90. {
  91. if (_usedWebSocket && UseWebSocket)
  92. {
  93. if (context.WebSockets.IsWebSocketRequest)
  94. {
  95. using (var ws = context.WebSockets.AcceptWebSocketAsync())
  96. {
  97. OnWebSocket(context, ws.Result);
  98. }
  99. return Task.CompletedTask;
  100. }
  101. }
  102. OnContext(context);
  103. }
  104. catch { }
  105. return Task.CompletedTask;
  106. }
  107. #endregion
  108. }
  109. }
  110. #endif