添加扩展中间件

This commit is contained in:
橙子
2021-10-12 16:52:28 +08:00
parent bba5a5039a
commit f204b211b9
34 changed files with 921 additions and 442 deletions

View File

@@ -0,0 +1,69 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Yi.Framework.WebCore
{
/// <summary>
/// appsettings.json操作类
/// </summary>
public class Appsettings
{
static IConfiguration Configuration { get; set; }
static string contentPath { get; set; }
public Appsettings(string contentPath)
{
string Path = "appsettings.json";
//如果你把配置文件 是 根据环境变量来分开了,可以这样写
//Path = $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json";
Configuration = new ConfigurationBuilder()
.SetBasePath(contentPath)
.Add(new JsonConfigurationSource { Path = Path, Optional = false, ReloadOnChange = true })//这样的话可以直接读目录里的json文件而不是 bin 文件夹下的,所以不用修改复制属性
.Build();
}
public Appsettings(IConfiguration configuration)
{
Configuration = configuration;
}
/// <summary>
/// 封装要操作的字符
/// </summary>
/// <param name="sections">节点配置</param>
/// <returns></returns>
public static string app(params string[] sections)
{
try
{
if (sections.Any())
{
return Configuration[string.Join(":", sections)];
}
}
catch (Exception) { }
return "";
}
/// <summary>
/// 递归获取配置信息数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sections"></param>
/// <returns></returns>
public static T app<T>(params string[] sections)
{
List<T> list = new List<T>();
// 引用 Microsoft.Extensions.Configuration.Binder 包
Configuration.Bind(string.Join(":", sections), list);
return list[0];
}
}
}

View File

@@ -1,8 +0,0 @@
using System;
namespace Yi.Framework.WebCore
{
public class Class1
{
}
}

View File

@@ -1,36 +1,44 @@
//using Yi.Framework.Model;
//using Microsoft.AspNetCore.Authentication;
//using Microsoft.AspNetCore.Http;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Security.Claims;
//using System.Text;
//using System.Threading.Tasks;
using Yi.Framework.Model;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Model.Models;
//namespace CC.ElectronicCommerce.WebCore
//{
// public static class CommonExtend
// {
// public static bool IsAjaxRequest(this HttpRequest request)
// {
// string header = request.Headers["X-Requested-With"];
// return "XMLHttpRequest".Equals(header);
// }
namespace Yi.Framework.WebCore
{
public static class CommonExtend
{
/// <summary>
/// 判断是否为异步请求
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public static bool IsAjaxRequest(this HttpRequest request)
{
string header = request.Headers["X-Requested-With"];
return "XMLHttpRequest".Equals(header);
}
// /// <summary>
// /// 基于HttpContext,当前鉴权方式解析,获取用户信息
// /// </summary>
// /// <param name="httpContext"></param>
// /// <returns></returns>
// public static UserInfo GetCurrentUserInfo(this HttpContext httpContext)
// {
// IEnumerable<Claim> claimlist = httpContext.AuthenticateAsync().Result.Principal.Claims;
// return new UserInfo()
// {
// id = long.Parse(claimlist.FirstOrDefault(u => u.Type == "id").Value),
// username = claimlist.FirstOrDefault(u => u.Type == "username").Value ?? "匿名"
// };
// }
// }
//}
/// <summary>
/// 基于HttpContext,当前鉴权方式解析,获取用户信息
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public static user GetCurrentUserInfo(this HttpContext httpContext)
{
IEnumerable<Claim> claimlist = httpContext.AuthenticateAsync().Result.Principal.Claims;
Int32.TryParse(claimlist.FirstOrDefault(u => u.Type == "id").Value,out int resId);
return new user()
{
id =resId,
username = claimlist.FirstOrDefault(u => u.Type == "username").Value ?? "匿名"
};
}
}
}

View File

@@ -1,18 +1,21 @@
//using Microsoft.AspNetCore.Mvc.Filters;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//namespace Zhaoxi.AgileFramework.WebCore.FilterExtend
//{
// public class CORSFilter : ActionFilterAttribute
// {
// public override void OnActionExecuting(ActionExecutingContext context)
// {
// context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
// context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT");
// context.HttpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
// }
// }
//}
namespace Yi.Framework.WebCore.FilterExtend
{
/// <summary>
/// 跨域过滤器
/// </summary>
public class CORSFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT");
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
}
}
}

View File

@@ -12,10 +12,18 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CC.ElectronicCommerce.WebCore.FilterExtend
namespace Yi.Framework.WebCore.FilterExtend
{
/// <summary>
/// 重复提交过滤器
/// </summary>
public class CustomAction2CommitFilterAttribute : ActionFilterAttribute
{
/// <summary>
/// 防重复提交周期 单位秒
/// </summary>
public int TimeOut = 1;
#region Identity
private readonly ILogger<CustomAction2CommitFilterAttribute> _logger;
private readonly CacheClientDB _cacheClientDB;
@@ -28,10 +36,6 @@ namespace CC.ElectronicCommerce.WebCore.FilterExtend
}
#endregion
/// <summary>
/// 防重复提交周期 单位秒
/// </summary>
public int TimeOut = 3;
public override void OnActionExecuting(ActionExecutingContext context)
{

View File

@@ -1,30 +1,33 @@
//using Microsoft.AspNetCore.Mvc.Filters;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//namespace Zhaoxi.AgileFramework.WebCore.FilterExtend
//{
// public class CustomActionCacheFilterAttribute : ActionFilterAttribute
// {
// public override void OnActionExecuted(ActionExecutedContext context)
// {
// context.HttpContext.Response.Headers.Add("Cache-Control", "public,max-age=6000");
// Console.WriteLine($"This {nameof(CustomActionCacheFilterAttribute)} OnActionExecuted{this.Order}");
// }
// public override void OnActionExecuting(ActionExecutingContext context)
// {
// Console.WriteLine($"This {nameof(CustomActionCacheFilterAttribute)} OnActionExecuting{this.Order}");
// }
// public override void OnResultExecuting(ResultExecutingContext context)
// {
// Console.WriteLine($"This {nameof(CustomActionCacheFilterAttribute)} OnResultExecuting{this.Order}");
// }
// public override void OnResultExecuted(ResultExecutedContext context)
// {
// Console.WriteLine($"This {nameof(CustomActionCacheFilterAttribute)} OnResultExecuted{this.Order}");
// }
// }
namespace Yi.Framework.WebCore.FilterExtend
{
/// <summary>
/// 缓存过滤器
/// </summary>
public class CustomActionCacheFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
context.HttpContext.Response.Headers.Add("Cache-Control", "public,max-age=6000");
Console.WriteLine($"This {nameof(CustomActionCacheFilterAttribute)} OnActionExecuted{this.Order}");
}
public override void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine($"This {nameof(CustomActionCacheFilterAttribute)} OnActionExecuting{this.Order}");
}
public override void OnResultExecuting(ResultExecutingContext context)
{
Console.WriteLine($"This {nameof(CustomActionCacheFilterAttribute)} OnResultExecuting{this.Order}");
}
public override void OnResultExecuted(ResultExecutedContext context)
{
Console.WriteLine($"This {nameof(CustomActionCacheFilterAttribute)} OnResultExecuted{this.Order}");
}
}
//}
}

View File

@@ -1,45 +1,43 @@
//using Microsoft.AspNetCore.Http;
//using Microsoft.AspNetCore.Mvc;
//using Microsoft.AspNetCore.Mvc.Filters;
//using Microsoft.AspNetCore.Mvc.ModelBinding;
//using Microsoft.AspNetCore.Mvc.ViewFeatures;
//using Microsoft.Extensions.Logging;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//namespace Zhaoxi.AgileFramework.WebCore.FilterExtend
//{
// public class CustomActionCheckFilterAttribute : ActionFilterAttribute
// {
// #region Identity
// private readonly ILogger<CustomActionCheckFilterAttribute> _logger;
// private readonly IModelMetadataProvider _modelMetadataProvider;
// public CustomActionCheckFilterAttribute(ILogger<CustomActionCheckFilterAttribute> logger)
// {
// this._logger = logger;
// }
// #endregion
namespace Yi.Framework.WebCore.FilterExtend
{
/// <summary>
/// 控制器检查过滤器
/// </summary>
public class CustomActionCheckFilterAttribute : ActionFilterAttribute
{
#region Identity
private readonly ILogger<CustomActionCheckFilterAttribute> _logger;
private readonly IModelMetadataProvider _modelMetadataProvider;
public CustomActionCheckFilterAttribute(ILogger<CustomActionCheckFilterAttribute> logger)
{
this._logger = logger;
}
#endregion
// public override void OnActionExecuting(ActionExecutingContext context)
// {
// //CurrentUser currentUser = context.HttpContext.GetCurrentUserBySession();
// //if (currentUser == null)
// //{
// // //if (this.IsAjaxRequest(context.HttpContext.Request))
// // //{ }
// // context.Result = new RedirectResult("~/Fourth/Login");
// //}
// //else
// //{
// // this._logger.LogDebug($"{currentUser.Name} 访问系统");
// //}
// }
// private bool IsAjaxRequest(HttpRequest request)
// {
// string header = request.Headers["X-Requested-With"];
// return "XMLHttpRequest".Equals(header);
// }
// }
//}
public override void OnActionExecuting(ActionExecutingContext context)
{
//CurrentUser currentUser = context.HttpContext.GetCurrentUserBySession();
//if (currentUser == null)
//{
// //if (this.IsAjaxRequest(context.HttpContext.Request))
// //{ }
// context.Result = new RedirectResult("~/Fourth/Login");
//}
//else
//{
// this._logger.LogDebug($"{currentUser.Name} 访问系统");
//}
}
}
}

View File

@@ -8,8 +8,11 @@ using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Yi.Framework.Common.Models;
namespace CC.ElectronicCommerce.WebCore.FilterExtend
namespace Yi.Framework.WebCore.FilterExtend
{
/// <summary>
/// 异常抓取过滤器
/// </summary>
public class CustomExceptionFilterAttribute : IExceptionFilter
{
private ILogger<CustomExceptionFilterAttribute> _logger = null;

View File

@@ -1,31 +1,31 @@
//using Microsoft.AspNetCore.Mvc.Filters;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//namespace Zhaoxi.AgileFramework.WebCore.FilterExtend
//{
// /// <summary>
// /// 基于完成Filter的依赖注入
// /// </summary>
// public class CustomIOCFilterFactoryAttribute : Attribute, IFilterFactory
// {
// private readonly Type _FilterType = null;
namespace Yi.Framework.WebCore.FilterExtend
{
/// <summary>
/// 依赖注入工厂过滤器
/// </summary>
public class CustomIOCFilterFactoryAttribute : Attribute, IFilterFactory
{
private readonly Type _FilterType = null;
// public CustomIOCFilterFactoryAttribute(Type type)
// {
// this._FilterType = type;
// }
// public bool IsReusable => true;
public CustomIOCFilterFactoryAttribute(Type type)
{
this._FilterType = type;
}
public bool IsReusable => true;
// public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
// {
// //return (IFilterMetadata)serviceProvider.GetService(typeof(CustomExceptionFilterAttribute));
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
//return (IFilterMetadata)serviceProvider.GetService(typeof(CustomExceptionFilterAttribute));
// return (IFilterMetadata)serviceProvider.GetService(this._FilterType);
// }
// }
return (IFilterMetadata)serviceProvider.GetService(this._FilterType);
}
}
//}
}

View File

@@ -1,45 +1,45 @@
//using Microsoft.AspNetCore.Mvc;
//using Microsoft.AspNetCore.Mvc.Filters;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
//namespace Zhaoxi.AgileFramework.WebCore.FilterExtend
//{
// /// <summary>
// ///
// /// </summary>
// public class CustomResourceFilterAttribute : Attribute, IResourceFilter, IFilterMetadata
// {
// private static Dictionary<string, IActionResult> CustomCache = new Dictionary<string, IActionResult>();
// /// <summary>
// /// 发生在其他动作之前
// /// </summary>
// /// <param name="context"></param>
// public void OnResourceExecuting(ResourceExecutingContext context)
// {
// Console.WriteLine($"This is {nameof(CustomResourceFilterAttribute) }OnResourceExecuting");
// //if 有缓存,直接返回缓存
// string key = context.HttpContext.Request.Path;
// if (CustomCache.ContainsKey(key))
// {
// context.Result = CustomCache[key];//断路器--到Result生成了但是Result还需要转换成Html
// }
// }
// /// <summary>
// /// 发生在其他动作之后
// /// </summary>
// /// <param name="context"></param>
// public void OnResourceExecuted(ResourceExecutedContext context)
// {
// Console.WriteLine($"This is {nameof(CustomResourceFilterAttribute) }OnResourceExecuted");
// //这个应该缓存起来
// string key = context.HttpContext.Request.Path;
// if (!CustomCache.ContainsKey(key))
// {
// CustomCache.Add(key, context.Result);
// }
// }
// }
//}
namespace Yi.Framework.WebCore.FilterExtend
{
/// <summary>
/// 资源过滤器
/// </summary>
public class CustomResourceFilterAttribute : Attribute, IResourceFilter, IFilterMetadata
{
private static Dictionary<string, IActionResult> CustomCache = new Dictionary<string, IActionResult>();
/// <summary>
/// 发生在其他动作之前
/// </summary>
/// <param name="context"></param>
public void OnResourceExecuting(ResourceExecutingContext context)
{
Console.WriteLine($"This is {nameof(CustomResourceFilterAttribute) }OnResourceExecuting");
//if 有缓存,直接返回缓存
string key = context.HttpContext.Request.Path;
if (CustomCache.ContainsKey(key))
{
context.Result = CustomCache[key];//断路器--到Result生成了但是Result还需要转换成Html
}
}
/// <summary>
/// 发生在其他动作之后
/// </summary>
/// <param name="context"></param>
public void OnResourceExecuted(ResourceExecutedContext context)
{
Console.WriteLine($"This is {nameof(CustomResourceFilterAttribute) }OnResourceExecuted");
//这个应该缓存起来
string key = context.HttpContext.Request.Path;
if (!CustomCache.ContainsKey(key))
{
CustomCache.Add(key, context.Result);
}
}
}
}

View File

@@ -7,8 +7,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CC.ElectronicCommerce.WebCore.FilterExtend
namespace Yi.Framework.WebCore.FilterExtend
{
/// <summary>
/// 日志处理过滤器
/// </summary>
public class LogActionFilterAttribute : ActionFilterAttribute
{
private ILogger<LogActionFilterAttribute> _logger = null;

View File

@@ -0,0 +1,58 @@
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Common.IOCOptions;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// HTTP模式
/// </summary>
public static class ConsulRegiterExtend
{
/// <summary>
/// 基于提供信息完成注册
/// </summary>
/// <param name="app"></param>
/// <param name="healthService"></param>
/// <returns></returns>
public static async Task UseConsulService(this IApplicationBuilder app)
{
var consulRegisterOption= Appsettings.app<ConsulRegisterOption>("ConsulRegisterOption");
var consulClientOption= Appsettings.app<ConsulClientOption>("ConsulRegisterOption");
using (ConsulClient client = new ConsulClient(c =>
{
c.Address = new Uri($"http://{consulClientOption.IP}:{consulClientOption.Port}/");
c.Datacenter = consulClientOption.Datacenter;
}))
{
await client.Agent.ServiceRegister(new AgentServiceRegistration()
{
ID = $"{consulRegisterOption.IP}-{consulRegisterOption.Port}-{Guid.NewGuid()}",//唯一Id
Name = consulRegisterOption.GroupName,//组名称-Group
Address = consulRegisterOption.IP,
Port = consulRegisterOption.Port,
Tags = new string[] { consulRegisterOption.Tag },
Check = new AgentServiceCheck()
{
Interval = TimeSpan.FromSeconds(consulRegisterOption.Interval),
HTTP = $"http://{consulRegisterOption.IP}:{consulRegisterOption.Port}{consulRegisterOption.HealthCheckUrl}",
Timeout = TimeSpan.FromSeconds(consulRegisterOption.Timeout),
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(consulRegisterOption.DeregisterCriticalServiceAfter)
}
});
Console.WriteLine($"{JsonConvert.SerializeObject(consulRegisterOption)} 完成注册");
}
}
}
}

View File

@@ -0,0 +1,34 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using System;
using System.IO;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// 通用跨域扩展
/// </summary>
public static class CorsExtension
{
public static IServiceCollection AddCorsService(this IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("CorsPolicy",//解决跨域问题
builder =>
{
builder.AllowAnyMethod()
.SetIsOriginAllowed(_ => true)
.AllowAnyHeader()
.AllowCredentials();
}));
return services;
}
public static void UseCorsService(this IApplicationBuilder app)
{
app.UseCors("CorsPolicy");
}
}
}

View File

@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using System;
using System.IO;
using Yi.Framework.Common.IOCOptions;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// 数据库扩展
/// </summary>
public static class DataBaseExtension
{
public static IServiceCollection AddDataBaseService<IocOptios>(this IServiceCollection services , string appsettings)
{
Appsettings.app<IocOptios>(appsettings);
return services;
}
public static void UseDataBaseService(this IApplicationBuilder app)
{
}
}
}

View File

@@ -0,0 +1,75 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Yi.Framework.Common.Models;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// 异常抓取反馈扩展
/// </summary>
public class ErrorHandExtension
{
private readonly RequestDelegate next;
public ErrorHandExtension(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await next(context);
}
catch (Exception ex)
{
var statusCode = context.Response.StatusCode;
if (ex is ArgumentException)
{
statusCode = 200;
}
await HandleExceptionAsync(context, statusCode, ex.Message);
}
finally
{
var statusCode = context.Response.StatusCode;
var msg = "";
switch (statusCode)
{
case 401: msg = "未授权";break;
case 403: msg = "未授权"; break;
case 404: msg = "未找到服务"; break;
case 502: msg = "请求错误"; break;
}
if (!string.IsNullOrWhiteSpace(msg))
{
await HandleExceptionAsync(context, statusCode, msg);
}
}
}
//异常错误信息捕获将错误信息用Json方式返回
private static Task HandleExceptionAsync(HttpContext context, int statusCode, string msg)
{
var result = JsonConvert.SerializeObject( Result.Error(msg).SetCode(statusCode));
context.Response.ContentType = "application/json;charset=utf-8";
return context.Response.WriteAsync(result);
}
}
//扩展方法
public static class ErrorHandlingExtensions
{
public static IApplicationBuilder UseErrorHandling(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ErrorHandExtension>();
}
}
}

View File

@@ -0,0 +1,34 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// 健康检测扩展
/// </summary>
public static class HealthCheckExtension
{
/// <summary>
/// 设置心跳响应
/// </summary>
/// <param name="app"></param>
/// <param name="checkPath">默认是/Health</param>
/// <returns></returns>
public static void UseHealthCheckMiddleware(this IApplicationBuilder app, string checkPath = "/Health")
{
app.Map(checkPath, applicationBuilder => applicationBuilder.Run(async context =>
{
Console.WriteLine($"This is Health Check");
context.Response.StatusCode = (int)HttpStatusCode.OK;
await context.Response.WriteAsync("OK");
}));
}
}
}

View File

@@ -5,18 +5,16 @@ using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace CC.ElectronicCommerce.WebCore.MiddlewareExtend
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// Axios会触发需要做个状态返回还需要指定跨域信息这里放在网关了
///
/// OPTIONS请求即预检请求可用于检测服务器允许的http方法。当发起跨域请求时由于安全原因触发一定条件时浏览器会在正式请求之前自动先发起OPTIONS请求即CORS预检请求服务器若接受该跨域请求浏览器才继续发起正式请求。
/// 预检请求扩展
/// </summary>
public class PreOptionRequestMiddleware
public class PreOptionRequestExtension
{
private readonly RequestDelegate _next;
public PreOptionRequestMiddleware(RequestDelegate next)
public PreOptionRequestExtension(RequestDelegate next)
{
_next = next;
}
@@ -42,7 +40,7 @@ namespace CC.ElectronicCommerce.WebCore.MiddlewareExtend
{
public static IApplicationBuilder UsePreOptionsRequest(this IApplicationBuilder app)
{
return app.UseMiddleware<PreOptionRequestMiddleware>();
return app.UseMiddleware<PreOptionRequestExtension>();
}
}

View File

@@ -0,0 +1,156 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// 静态化页面处理扩展
/// </summary>
public class StaticPageExtension
{
private readonly RequestDelegate _next;
private string _directoryPath = @"D:/cc-yi/";
private bool _supportDelete = false;
private bool _supportWarmup = false;
public StaticPageExtension(RequestDelegate next, string directoryPath, bool supportDelete, bool supportWarmup)
{
this._next = next;
this._directoryPath = directoryPath;
this._supportDelete = supportDelete;
this._supportWarmup = supportWarmup;
}
public async Task InvokeAsync(HttpContext context)
{
if (this._supportDelete && "Delete".Equals(context.Request.Query["ActionHeader"]))
{
this.DeleteHmtl(context.Request.Path.Value);
context.Response.StatusCode = 200;
}
else if (this._supportWarmup && "ClearAll".Equals(context.Request.Query["ActionHeader"]))
{
this.ClearDirectory(10);//考虑数据量
context.Response.StatusCode = 200;
}
else if (!context.Request.IsAjaxRequest())
{
Console.WriteLine($"This is StaticPageMiddleware InvokeAsync {context.Request.Path.Value}");
#region context.Response.Body
var originalStream = context.Response.Body;
using (var copyStream = new MemoryStream())
{
context.Response.Body = copyStream;
await _next(context);
copyStream.Position = 0;
var reader = new StreamReader(copyStream);
var content = await reader.ReadToEndAsync();
string url = context.Request.Path.Value;
this.SaveHmtl(url, content);
copyStream.Position = 0;
await copyStream.CopyToAsync(originalStream);
context.Response.Body = originalStream;
}
#endregion
}
else
{
await _next(context);
}
}
private void SaveHmtl(string url, string html)
{
try
{
//Console.WriteLine($"Response: {html}");
if (string.IsNullOrWhiteSpace(html))
return;
if (!url.EndsWith(".html"))
return;
if (Directory.Exists(_directoryPath) == false)
Directory.CreateDirectory(_directoryPath);
var totalPath = Path.Combine(_directoryPath, url.Split("/").Last());
File.WriteAllText(totalPath, html);//直接覆盖
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
/// <summary>
/// 删除某个页面
/// </summary>
/// <param name="url"></param>
/// <param name="index"></param>
private void DeleteHmtl(string url)
{
try
{
if (!url.EndsWith(".html"))
return;
var totalPath = Path.Combine(_directoryPath, url.Split("/").Last());
File.Delete(totalPath);//直接删除
}
catch (Exception ex)
{
Console.WriteLine($"Delete {url} 异常,{ex.Message}");
}
}
/// <summary>
/// 清理文件,支持重试
/// </summary>
/// <param name="index">最多重试次数</param>
private void ClearDirectory(int index)
{
if (index > 0)//简陋版---重试index次
{
try
{
var files = Directory.GetFiles(_directoryPath);
foreach (var file in files)
{
File.Delete(file);
}
}
catch (Exception ex)
{
Console.WriteLine($"ClearDirectory failed {ex.Message}");
ClearDirectory(index--);
}
}
}
}
/// <summary>
/// 扩展中间件
/// </summary>
public static class StaticPageMiddlewareExtensions
{
/// <summary>
///
/// </summary>
/// <param name="app"></param>
/// <param name="directoryPath">文件写入地址,文件夹目录</param>
/// <param name="supportDelete">是否支持删除</param>
/// <param name="supportClear">是否支持全量删除</param>
/// <returns></returns>
public static IApplicationBuilder UseStaticPageMiddleware(this IApplicationBuilder app, string directoryPath, bool supportDelete, bool supportClear)
{
return app.UseMiddleware<StaticPageExtension>(directoryPath, supportDelete, supportClear);
}
}
}

View File

@@ -1,156 +0,0 @@
//using Microsoft.AspNetCore.Builder;
//using Microsoft.AspNetCore.Http;
//using System;
//using System.Collections.Generic;
//using System.IO;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
//namespace CC.ElectronicCommerce.WebCore.MiddlewareExtend
//{
// /// <summary>
// /// 支持在返回HTML时将返回的Stream保存到指定目录
// /// </summary>
// public class StaticPageMiddleware
// {
// private readonly RequestDelegate _next;
// private string _directoryPath = @"D:/cc-ec/";
// private bool _supportDelete = false;
// private bool _supportWarmup = false;
// public StaticPageMiddleware(RequestDelegate next, string directoryPath, bool supportDelete, bool supportWarmup)
// {
// this._next = next;
// this._directoryPath = directoryPath;
// this._supportDelete = supportDelete;
// this._supportWarmup = supportWarmup;
// }
// public async Task InvokeAsync(HttpContext context)
// {
// if (this._supportDelete && "Delete".Equals(context.Request.Query["ActionHeader"]))
// {
// this.DeleteHmtl(context.Request.Path.Value);
// context.Response.StatusCode = 200;
// }
// else if (this._supportWarmup && "ClearAll".Equals(context.Request.Query["ActionHeader"]))
// {
// this.ClearDirectory(10);//考虑数据量
// context.Response.StatusCode = 200;
// }
// else if (!context.Request.IsAjaxRequest())
// {
// Console.WriteLine($"This is StaticPageMiddleware InvokeAsync {context.Request.Path.Value}");
// #region context.Response.Body
// var originalStream = context.Response.Body;
// using (var copyStream = new MemoryStream())
// {
// context.Response.Body = copyStream;
// await _next(context);
// copyStream.Position = 0;
// var reader = new StreamReader(copyStream);
// var content = await reader.ReadToEndAsync();
// string url = context.Request.Path.Value;
// this.SaveHmtl(url, content);
// copyStream.Position = 0;
// await copyStream.CopyToAsync(originalStream);
// context.Response.Body = originalStream;
// }
// #endregion
// }
// else
// {
// await _next(context);
// }
// }
// private void SaveHmtl(string url, string html)
// {
// try
// {
// //Console.WriteLine($"Response: {html}");
// if (string.IsNullOrWhiteSpace(html))
// return;
// if (!url.EndsWith(".html"))
// return;
// if (Directory.Exists(_directoryPath) == false)
// Directory.CreateDirectory(_directoryPath);
// var totalPath = Path.Combine(_directoryPath, url.Split("/").Last());
// File.WriteAllText(totalPath, html);//直接覆盖
// }
// catch (Exception ex)
// {
// Console.WriteLine(ex.Message);
// }
// }
// /// <summary>
// /// 删除某个页面
// /// </summary>
// /// <param name="url"></param>
// /// <param name="index"></param>
// private void DeleteHmtl(string url)
// {
// try
// {
// if (!url.EndsWith(".html"))
// return;
// var totalPath = Path.Combine(_directoryPath, url.Split("/").Last());
// File.Delete(totalPath);//直接删除
// }
// catch (Exception ex)
// {
// Console.WriteLine($"Delete {url} 异常,{ex.Message}");
// }
// }
// /// <summary>
// /// 清理文件,支持重试
// /// </summary>
// /// <param name="index">最多重试次数</param>
// private void ClearDirectory(int index)
// {
// if (index > 0)//简陋版---重试index次
// {
// try
// {
// var files = Directory.GetFiles(_directoryPath);
// foreach (var file in files)
// {
// File.Delete(file);
// }
// }
// catch (Exception ex)
// {
// Console.WriteLine($"ClearDirectory failed {ex.Message}");
// ClearDirectory(index--);
// }
// }
// }
// }
// /// <summary>
// /// 扩展中间件
// /// </summary>
// public static class StaticPageMiddlewareExtensions
// {
// /// <summary>
// ///
// /// </summary>
// /// <param name="app"></param>
// /// <param name="directoryPath">文件写入地址,文件夹目录</param>
// /// <param name="supportDelete">是否支持删除</param>
// /// <param name="supportClear">是否支持全量删除</param>
// /// <returns></returns>
// public static IApplicationBuilder UseStaticPageMiddleware(this IApplicationBuilder app, string directoryPath, bool supportDelete, bool supportClear)
// {
// return app.UseMiddleware<StaticPageMiddleware>(directoryPath, supportDelete, supportClear);
// }
// }
//}

View File

@@ -0,0 +1,76 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using System;
using System.IO;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// Swagger扩展
/// </summary>
public static class SwaggerExtension
{
public static IServiceCollection AddSwaggerService<Program>(this IServiceCollection services)
{
var apiInfo = new OpenApiInfo
{
Title = "Yi意框架-API接口",
Version = "v1",
Contact = new OpenApiContact { Name = "橙子", Email = "454313500@qq.com", Url = new System.Uri("https://ccnetcore.com") }
};
#region Swagger服务
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", apiInfo);
//添加注释服务
//为 Swagger JSON and UI设置xml文档注释路径
//获取应用程序所在目录(绝对路径不受工作目录影响建议采用此方法获取路径使用windwos&Linux
var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);
var apiXmlPath = Path.Combine(basePath, @"ApiDoc.xml");//控制器层注释
var entityXmlPath = Path.Combine(basePath, @"SwaggerDoc.xml");//实体注释
//c.IncludeXmlComments(apiXmlPath, true);//true表示显示控制器注释
c.IncludeXmlComments(entityXmlPath);
//添加控制器注释
//c.DocumentFilter<SwaggerDocTag>();
//添加header验证信息
//c.OperationFilter<SwaggerHeader>();
//var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, };
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Description = "文本框里输入从服务器获取的Token。格式为Bearer + 空格+token",//JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"
Name = "Authorization",////jwt默认的参数名称
In = ParameterLocation.Header,////jwt默认存放Authorization信息的位置(请求头中)
Type = SecuritySchemeType.ApiKey,
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{ new OpenApiSecurityScheme
{
Reference = new OpenApiReference()
{
Id = "Bearer",
Type = ReferenceType.SecurityScheme
}
}, Array.Empty<string>() }
});
});
#endregion
return services;
}
public static void UseSwaggerService(this IApplicationBuilder app)
{
//在 Startup.Configure 方法中,启用中间件为生成的 JSON 文档和 Swagger UI 提供服务:
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Yi.Framework"));
}
}
}