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.

102 lines
3.6 KiB

2 years ago
  1. using Microsoft.AspNetCore.Http.Features;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.Net.Http.Headers;
  4. using System.Net;
  5. using System.Text.Encodings.Web;
  6. using System.Text.Json;
  7. using System.Text.Unicode;
  8. using System;
  9. using System.Threading.Tasks;
  10. using Microsoft.IdentityModel.Logging;
  11. namespace Shentun.Peis
  12. {
  13. public class ErrorHandlerMiddleWare
  14. {
  15. //请求委托
  16. private readonly RequestDelegate _next;
  17. // private readonly LogHelper _nlogger;
  18. public ErrorHandlerMiddleWare(RequestDelegate next
  19. //, LogHelper nlogger
  20. )
  21. {
  22. this._next = next;
  23. // this._nlogger = nlogger;
  24. }
  25. public async Task Invoke(HttpContext context)
  26. {
  27. try
  28. {
  29. await this._next.Invoke(context);
  30. }
  31. catch (Exception ex)
  32. {
  33. await HandleExceptionAsync(context, ex);
  34. }
  35. }
  36. private async Task HandleExceptionAsync(HttpContext context, Exception exception)
  37. {
  38. if (exception == null) return;
  39. await HandleErrorResultAsync(context, exception).ConfigureAwait(false);
  40. }
  41. private async Task HandleErrorResultAsync(HttpContext context, Exception exception)
  42. {
  43. //记录日志
  44. // _nlogger.LogError(exception);
  45. //返回友好的提示
  46. var response = context.Response;
  47. //清除原有HTTP上下文信息,为了明确指定程序出现异常,防止异常未被处理而后续当做正常操作执行
  48. ClearHttpContext(context);
  49. //状态码
  50. if (exception is UnauthorizedAccessException)
  51. response.StatusCode = (int)HttpStatusCode.Unauthorized;
  52. else if (exception is BadHttpRequestException)
  53. response.StatusCode = (int)HttpStatusCode.BadRequest;
  54. else if (response.StatusCode == 403 || response.StatusCode == 404) { }
  55. else response.StatusCode = (int)HttpStatusCode.InternalServerError;
  56. response.ContentType = context.Request.Headers["Accept"];
  57. var result = new ApiResult
  58. {
  59. Code = 500,
  60. Message = exception.GetBaseException().Message
  61. };
  62. if (response.ContentType.ToLower() != "application/x-www-form-urlencoded")
  63. {
  64. response.ContentType = "application/json";
  65. }
  66. await response.WriteAsync(JsonSerializer.Serialize(result
  67. , new JsonSerializerOptions()
  68. {
  69. Encoder = JavaScriptEncoder.Create(UnicodeRanges.All),
  70. PropertyNameCaseInsensitive = true,
  71. PropertyNamingPolicy = JsonNamingPolicy.CamelCase
  72. })).ConfigureAwait(false);
  73. }
  74. private static void ClearHttpContext(HttpContext context)
  75. {
  76. context.Response.Clear();
  77. //因为可能创建了新的终结点,所以执行管道会有所调整,所以需要重新计算
  78. context.SetEndpoint(endpoint: null);
  79. var routeValuesFeature = context.Features.Get<IRouteValuesFeature>();
  80. routeValuesFeature?.RouteValues?.Clear();
  81. }
  82. private static Task ClearCacheHeaders(object state)
  83. {
  84. //清除输出缓存相关
  85. var headers = ((HttpResponse)state).Headers;
  86. headers[HeaderNames.CacheControl] = "no-cache";
  87. headers[HeaderNames.Pragma] = "no-cache";
  88. headers[HeaderNames.Expires] = "-1";
  89. headers.Remove(HeaderNames.ETag);
  90. return Task.CompletedTask;
  91. }
  92. }
  93. }