-
Notifications
You must be signed in to change notification settings - Fork 444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IApiFilter丢失AsyncLocal值 #261
Comments
这里的处理不是正确的:
正确的实现,应该是每个OnXXXAsync()的逻辑(不只是Filter的),包装为一个中间件,然后按照现在的foreach先后顺序,把他们串起来编排,m1调用m2,m2调用m3这样的逻辑传递。考虑到这个编排过程依赖于ApiRequestContext自身的ActionDescriptor和HttpContext.HttpApiOptions两个重要属性,这就只能每次请求时编排和创建与Action关联的中间件委托,不管使用不使用Action来做中间件委托的缓存,都会带来一些性能损耗。 |
那可以添加一个如下的IApiPipeFilter接口,使用者只需要实现IApiPipeFilter即可 static Func<ApiRequestContext, Task<ApiResponseContext>> Build(IApiFilter filter,
Func<ApiRequestContext, Task<ApiResponseContext>> next) =>
context => (filter as IApiPipeFilter ?? new ApiFilterWrapper(filter)).ExecuteAsync(context, next);
interface IApiPipeFilter : IApiFilter
{
Task<ApiResponseContext> ExecuteAsync(ApiRequestContext context, Func<ApiRequestContext, Task<ApiResponseContext>> next);
Task IApiFilter.OnRequestAsync(ApiRequestContext context) => Task.CompletedTask;
Task IApiFilter.OnResponseAsync(ApiResponseContext context) => Task.CompletedTask;
}
class ApiFilterWrapper(IApiFilter filter) : IApiPipeFilter
{
public async Task<ApiResponseContext> ExecuteAsync(ApiRequestContext context, Func<ApiRequestContext, Task<ApiResponseContext>> next)
{
await filter.OnRequestAsync(context);
var response = await next(context);
await filter.OnResponseAsync(response);
return response;
}
}
private sealed class TestFilter : IApiPipeFilter
{
private static readonly AsyncLocal<bool> V = new();
public async Task<ApiResponseContext> ExecuteAsync(ApiRequestContext context, Func<ApiRequestContext, Task<ApiResponseContext>> next)
{
V.Value = true;
var response = await next(context);
Assert.True(V.Value);
return response;
}
} |
好想法,我们可以在WebApiClientCore.Abstractions项目新建一个 1.注入IOptionsMonitor获取GlobalFilters,拿GlobalFilters和Attribute类型的Filter以及ApiRequestExecutor(去掉了filter执行)一起build出RequestDelegate ; 这样做之后,至少在Filter,应该能够使用AsyncLocal了 |
上面这种在OnRequestAsync里异步之后给AsyncLocal设置值,在OnResponseAsync里是获取不到的。
上面这种代码,完全不需要AsyncLocal(你可以把V当作是普通的 |
第二种AsyncLocal是要在HTTP管道中使用到AsyncLocal值,此处只是用于举例 |
解决办法需要重构ApiRequestExecuter
下面是可能的解决办法(未验证,仅限参考):
The text was updated successfully, but these errors were encountered: